using MediatR;
using Microsoft.AspNetCore.Identity;
using IamService.Domain.AggregatesModel.UserAggregate;
using IamService.Domain.Exceptions;

namespace IamService.API.Application.Commands.Users;

/// <summary>
/// EN: Handler for UpdateUserCommand.
/// VI: Handler cho UpdateUserCommand.
/// </summary>
public class UpdateUserCommandHandler : IRequestHandler<UpdateUserCommand, UpdateUserCommandResult>
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly ILogger<UpdateUserCommandHandler> _logger;

    public UpdateUserCommandHandler(
        UserManager<ApplicationUser> userManager,
        ILogger<UpdateUserCommandHandler> logger)
    {
        _userManager = userManager;
        _logger = logger;
    }

    public async Task<UpdateUserCommandResult> Handle(UpdateUserCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Updating user: {UserId}", request.UserId);

        var user = await _userManager.FindByIdAsync(request.UserId.ToString());

        if (user == null)
        {
            _logger.LogWarning("User not found: {UserId}", request.UserId);
            throw new DomainException($"User with ID {request.UserId} not found.");
        }

        // EN: Update user properties
        // VI: Cập nhật thuộc tính user
        if (!string.IsNullOrWhiteSpace(request.FirstName))
        {
            user.UpdateProfile(request.FirstName, user.LastName);
        }

        if (!string.IsNullOrWhiteSpace(request.LastName))
        {
            user.UpdateProfile(user.FirstName, request.LastName);
        }

        // EN: If both are provided, update together
        // VI: Nếu cả hai được cung cấp, cập nhật cùng lúc
        if (!string.IsNullOrWhiteSpace(request.FirstName) && !string.IsNullOrWhiteSpace(request.LastName))
        {
            user.UpdateProfile(request.FirstName, request.LastName);
        }

        var result = await _userManager.UpdateAsync(user);

        if (!result.Succeeded)
        {
            var errors = string.Join(", ", result.Errors.Select(e => e.Description));
            _logger.LogError("Failed to update user {UserId}: {Errors}", request.UserId, errors);
            throw new DomainException($"Failed to update user: {errors}");
        }

        _logger.LogInformation("User {UserId} updated successfully", request.UserId);

        return new UpdateUserCommandResult(
            user.Id,
            user.Email ?? string.Empty,
            user.FirstName,
            user.LastName,
            user.FullName);
    }
}
