using MediatR;
using Microsoft.EntityFrameworkCore;
using IamService.Domain.AggregatesModel.UserAggregate;
using IamService.Domain.Exceptions;
using IamService.Infrastructure;

namespace IamService.API.Application.Commands.UserProfiles;

/// <summary>
/// EN: Handler for SetProfileAttributeCommand.
/// VI: Handler cho SetProfileAttributeCommand.
/// </summary>
public class SetProfileAttributeCommandHandler 
    : IRequestHandler<SetProfileAttributeCommand, SetProfileAttributeCommandResult>
{
    private readonly IamServiceContext _context;
    private readonly ILogger<SetProfileAttributeCommandHandler> _logger;

    public SetProfileAttributeCommandHandler(
        IamServiceContext context,
        ILogger<SetProfileAttributeCommandHandler> logger)
    {
        _context = context;
        _logger = logger;
    }

    public async Task<SetProfileAttributeCommandResult> Handle(
        SetProfileAttributeCommand request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Setting attribute {Key} for user: {UserId}", request.Key, request.UserId);

        // EN: Get or create user profile
        // VI: Lấy hoặc tạo user profile
        var profile = await _context.UserProfiles
            .Include(p => p.Attributes)
            .FirstOrDefaultAsync(p => EF.Property<Guid>(p, "_userId") == request.UserId, cancellationToken);

        if (profile == null)
        {
            profile = UserProfile.Create(request.UserId);
            _context.UserProfiles.Add(profile);
        }

        // EN: Set attribute based on type
        // VI: Đặt attribute dựa trên loại
        ProfileAttribute attribute = request.ValueType.ToLowerInvariant() switch
        {
            "number" => profile.SetAttribute(request.Key, decimal.Parse(request.Value)),
            "boolean" => profile.SetAttribute(request.Key, bool.Parse(request.Value)),
            "date" => profile.SetAttribute(request.Key, DateTime.Parse(request.Value)),
            "json" => profile.SetJsonAttribute(request.Key, request.Value),
            _ => profile.SetAttribute(request.Key, request.Value)  // Default: string
        };

        await _context.SaveChangesAsync(cancellationToken);

        _logger.LogInformation("Attribute {Key} set for user {UserId}", request.Key, request.UserId);

        return new SetProfileAttributeCommandResult(
            profile.Id,
            attribute.Key,
            attribute.Value,
            attribute.ValueType?.Name ?? "String");
    }
}
