using MediatR;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using IamService.Domain.AggregatesModel.UserAggregate;
using IamService.Domain.Events;

namespace IamService.API.Application.Commands.Auth;

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

    public RegisterUserCommandHandler(
        UserManager<ApplicationUser> userManager,
        ILogger<RegisterUserCommandHandler> logger)
    {
        _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<RegisterUserCommandResult> Handle(
        RegisterUserCommand request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "Registering new user with email {Email}",
            request.Email);

        // EN: Check if user already exists
        // VI: Kiểm tra xem user đã tồn tại chưa
        var existingUser = await _userManager.FindByEmailAsync(request.Email);
        if (existingUser != null)
        {
            _logger.LogWarning("User with email {Email} already exists", request.Email);
            throw new Domain.Exceptions.DuplicateResourceException("User", request.Email);
        }

        // EN: Create new user
        // VI: Tạo user mới
        var user = new ApplicationUser(request.Email, request.FirstName, request.LastName);

        // EN: Add domain event
        // VI: Thêm domain event
        user.AddDomainEvent(new UserRegisteredDomainEvent(user));

        // EN: Create user with password
        // VI: Tạo user với password
        var result = await _userManager.CreateAsync(user, request.Password);

        if (!result.Succeeded)
        {
            var errors = string.Join(", ", result.Errors.Select(e => e.Description));
            _logger.LogWarning("Failed to create user: {Errors}", errors);
            throw new InvalidOperationException($"Failed to create user: {errors}");
        }

        _logger.LogInformation(
            "Successfully registered user {UserId} with email {Email}",
            user.Id, user.Email);

        return new RegisterUserCommandResult(
            user.Id,
            user.Email!,
            user.FullName);
    }
}
