using MediatR;
using IamService.API.Application.Services;
using IamService.Domain.AggregatesModel.VerificationAggregate;
using IamService.Domain.Exceptions;

namespace IamService.API.Application.Commands.Verifications;

/// <summary>
/// EN: Handler for RequestPhoneVerificationCommand.
/// VI: Handler cho RequestPhoneVerificationCommand.
/// </summary>
public class RequestPhoneVerificationCommandHandler 
    : IRequestHandler<RequestPhoneVerificationCommand, RequestVerificationCommandResult>
{
    private readonly IIdentityVerificationRepository _verificationRepository;
    private readonly IVerificationOtpDispatcher _otpDispatcher;
    private readonly ILogger<RequestPhoneVerificationCommandHandler> _logger;

    public RequestPhoneVerificationCommandHandler(
        IIdentityVerificationRepository verificationRepository,
        IVerificationOtpDispatcher otpDispatcher,
        ILogger<RequestPhoneVerificationCommandHandler> logger)
    {
        _verificationRepository = verificationRepository;
        _otpDispatcher = otpDispatcher;
        _logger = logger;
    }

    public async Task<RequestVerificationCommandResult> Handle(
        RequestPhoneVerificationCommand request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Requesting phone verification for user: {UserId}", request.UserId);

        // EN: Check if there's an active verification
        // VI: Kiểm tra có verification đang hoạt động không
        var existingVerification = await _verificationRepository.GetActiveByUserIdAndTypeAsync(
            request.UserId,
            VerificationType.Phone,
            cancellationToken);

        if (existingVerification != null)
        {
            throw new DomainException("A phone verification is already pending. Please wait for it to expire or complete it.");
        }

        // EN: Create new phone verification
        // VI: Tạo xác thực điện thoại mới
        var (verification, otp) = IdentityVerification.CreatePhoneVerification(
            request.UserId,
            request.PhoneNumber);

        _verificationRepository.Add(verification);

        await _verificationRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        await _otpDispatcher.SendPhoneOtpAsync(
            request.UserId,
            request.PhoneNumber,
            otp,
            cancellationToken);

        return new RequestVerificationCommandResult(
            verification.Id,
            VerificationType.Phone.Name,
            verification.ExpiresAt,
            "Verification code sent to your phone number.");
    }
}

/// <summary>
/// EN: Handler for RequestEmailVerificationCommand.
/// VI: Handler cho RequestEmailVerificationCommand.
/// </summary>
public class RequestEmailVerificationCommandHandler 
    : IRequestHandler<RequestEmailVerificationCommand, RequestVerificationCommandResult>
{
    private readonly IIdentityVerificationRepository _verificationRepository;
    private readonly IVerificationOtpDispatcher _otpDispatcher;
    private readonly ILogger<RequestEmailVerificationCommandHandler> _logger;

    public RequestEmailVerificationCommandHandler(
        IIdentityVerificationRepository verificationRepository,
        IVerificationOtpDispatcher otpDispatcher,
        ILogger<RequestEmailVerificationCommandHandler> logger)
    {
        _verificationRepository = verificationRepository;
        _otpDispatcher = otpDispatcher;
        _logger = logger;
    }

    public async Task<RequestVerificationCommandResult> Handle(
        RequestEmailVerificationCommand request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Requesting email verification for user: {UserId}", request.UserId);

        // EN: Check if there's an active verification
        // VI: Kiểm tra có verification đang hoạt động không
        var existingVerification = await _verificationRepository.GetActiveByUserIdAndTypeAsync(
            request.UserId,
            VerificationType.Email,
            cancellationToken);

        if (existingVerification != null)
        {
            throw new DomainException("An email verification is already pending. Please wait for it to expire or complete it.");
        }

        // EN: Create new email verification
        // VI: Tạo xác thực email mới
        var (verification, otp) = IdentityVerification.CreateEmailVerification(
            request.UserId,
            request.Email);

        _verificationRepository.Add(verification);

        await _verificationRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        await _otpDispatcher.SendEmailOtpAsync(
            request.UserId,
            request.Email,
            otp,
            cancellationToken);

        return new RequestVerificationCommandResult(
            verification.Id,
            VerificationType.Email.Name,
            verification.ExpiresAt,
            "Verification code sent to your email address.");
    }
}
