// EN: Handler for Verify2FACommand
// VI: Handler cho Verify2FACommand

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

namespace IamService.API.Application.Commands.Auth;

/// <summary>
/// EN: Handler for Verify2FACommand.
/// VI: Handler cho Verify2FACommand.
/// </summary>
public class Verify2FACommandHandler : IRequestHandler<Verify2FACommand, Verify2FAResult>
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly ITwoFactorService _twoFactorService;
    private readonly ILogger<Verify2FACommandHandler> _logger;

    public Verify2FACommandHandler(
        UserManager<ApplicationUser> userManager,
        ITwoFactorService twoFactorService,
        ILogger<Verify2FACommandHandler> logger)
    {
        _userManager = userManager;
        _twoFactorService = twoFactorService;
        _logger = logger;
    }

    public async Task<Verify2FAResult> Handle(
        Verify2FACommand request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Verifying 2FA code for user {UserId}", request.UserId);

        // EN: Find user by ID
        // VI: Tìm user theo ID
        var user = await _userManager.FindByIdAsync(request.UserId.ToString());
        if (user == null)
        {
            _logger.LogWarning("User not found with ID {UserId}", request.UserId);
            return new Verify2FAResult(false, "User not found.");
        }

        // EN: Get pending secret key
        // VI: Lấy secret key đang chờ
        var pendingSecretKey = await _userManager.GetAuthenticationTokenAsync(
            user,
            "[TwoFactor]",
            "PendingSecretKey");

        if (string.IsNullOrEmpty(pendingSecretKey))
        {
            _logger.LogWarning("No pending 2FA setup found for user {UserId}", request.UserId);
            return new Verify2FAResult(false, "No pending 2FA setup found. Please enable 2FA first.");
        }

        // EN: Validate the code
        // VI: Xác minh mã
        var isValid = _twoFactorService.ValidateCode(pendingSecretKey, request.Code);

        if (!isValid)
        {
            _logger.LogWarning("Invalid 2FA code for user {UserId}", request.UserId);
            return new Verify2FAResult(false, "Invalid verification code.");
        }

        // EN: Enable 2FA for user
        // VI: Bật 2FA cho user
        var result = await _userManager.SetTwoFactorEnabledAsync(user, true);

        if (!result.Succeeded)
        {
            var errors = string.Join(", ", result.Errors.Select(e => e.Description));
            _logger.LogWarning("Failed to enable 2FA for user {UserId}: {Errors}", request.UserId, errors);
            return new Verify2FAResult(false, $"Failed to enable 2FA: {errors}");
        }

        // EN: Store the confirmed secret key
        // VI: Lưu secret key đã xác nhận
        await _userManager.SetAuthenticationTokenAsync(
            user,
            "[TwoFactor]",
            "SecretKey",
            pendingSecretKey);

        // EN: Remove pending secret key
        // VI: Xóa secret key đang chờ
        await _userManager.RemoveAuthenticationTokenAsync(
            user,
            "[TwoFactor]",
            "PendingSecretKey");

        _logger.LogInformation("2FA enabled successfully for user {UserId}", request.UserId);

        return new Verify2FAResult(true, "Two-factor authentication enabled successfully.");
    }
}
