// EN: Handler for Enable2FACommand
// VI: Handler cho Enable2FACommand

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 Enable2FACommand.
/// VI: Handler cho Enable2FACommand.
/// </summary>
public class Enable2FACommandHandler : IRequestHandler<Enable2FACommand, Enable2FAResult>
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly ITwoFactorService _twoFactorService;
    private readonly ILogger<Enable2FACommandHandler> _logger;

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

    public async Task<Enable2FAResult> Handle(
        Enable2FACommand request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Enabling 2FA 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);
            throw new InvalidOperationException("User not found");
        }

        // EN: Check if 2FA is already enabled
        // VI: Kiểm tra xem 2FA đã được bật chưa
        if (await _userManager.GetTwoFactorEnabledAsync(user))
        {
            _logger.LogInformation("2FA is already enabled for user {UserId}", request.UserId);
            throw new InvalidOperationException("Two-factor authentication is already enabled.");
        }

        // EN: Generate new secret key
        // VI: Tạo secret key mới
        var secretKey = _twoFactorService.GenerateSecretKey();

        // EN: Store the key temporarily (will be confirmed after verification)
        // VI: Lưu key tạm thời (sẽ được xác nhận sau khi xác minh)
        await _userManager.SetAuthenticationTokenAsync(
            user,
            "[TwoFactor]",
            "PendingSecretKey",
            secretKey);

        // EN: Generate QR code
        // VI: Tạo QR code
        var qrCodeBase64 = _twoFactorService.GenerateQrCodeBase64(user.Email!, secretKey);

        // EN: Generate recovery codes
        // VI: Tạo mã khôi phục
        var recoveryCodes = _twoFactorService.GenerateRecoveryCodes(10).ToArray();

        // EN: Store recovery codes (hashed)
        // VI: Lưu mã khôi phục (đã hash)
        await _userManager.SetAuthenticationTokenAsync(
            user,
            "[TwoFactor]",
            "RecoveryCodes",
            string.Join(";", recoveryCodes));

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

        return new Enable2FAResult(
            Success: true,
            SecretKey: secretKey,
            QrCodeBase64: qrCodeBase64,
            ManualEntryKey: secretKey,
            RecoveryCodes: recoveryCodes);
    }
}
