using ColaFlow.Modules.Identity.Application.Services;
using ColaFlow.Modules.Identity.Domain.Aggregates.Users;
using ColaFlow.Modules.Identity.Domain.Entities;
using ColaFlow.Modules.Identity.Domain.Repositories;
using ColaFlow.Modules.Identity.Domain.Services;
using MediatR;
using Microsoft.Extensions.Logging;

namespace ColaFlow.Modules.Identity.Application.Commands.SendVerificationEmail;

public class SendVerificationEmailCommandHandler : IRequestHandler<SendVerificationEmailCommand, Unit>
{
    private readonly IUserRepository _userRepository;
    private readonly IEmailVerificationTokenRepository _tokenRepository;
    private readonly ISecurityTokenService _tokenService;
    private readonly IEmailService _emailService;
    private readonly IEmailTemplateService _templateService;
    private readonly ILogger<SendVerificationEmailCommandHandler> _logger;

    public SendVerificationEmailCommandHandler(
        IUserRepository userRepository,
        IEmailVerificationTokenRepository tokenRepository,
        ISecurityTokenService tokenService,
        IEmailService emailService,
        IEmailTemplateService templateService,
        ILogger<SendVerificationEmailCommandHandler> logger)
    {
        _userRepository = userRepository;
        _tokenRepository = tokenRepository;
        _tokenService = tokenService;
        _emailService = emailService;
        _templateService = templateService;
        _logger = logger;
    }

    public async Task<Unit> Handle(SendVerificationEmailCommand request, CancellationToken cancellationToken)
    {
        var userId = UserId.Create(request.UserId);
        var user = await _userRepository.GetByIdAsync(userId, cancellationToken);

        if (user == null)
        {
            _logger.LogWarning("User {UserId} not found, cannot send verification email", request.UserId);
            return Unit.Value;
        }

        // If already verified, no need to send email
        if (user.IsEmailVerified)
        {
            _logger.LogInformation("User {UserId} email already verified, skipping verification email", request.UserId);
            return Unit.Value;
        }

        // Generate token
        var token = _tokenService.GenerateToken();
        var tokenHash = _tokenService.HashToken(token);

        // Create verification token entity
        var verificationToken = EmailVerificationToken.Create(
            userId,
            tokenHash,
            DateTime.UtcNow.AddHours(24));

        await _tokenRepository.AddAsync(verificationToken, cancellationToken);

        // Send email (non-blocking)
        var verificationLink = $"{request.BaseUrl}/verify-email?token={token}";
        var htmlBody = _templateService.RenderVerificationEmail(user.FullName.Value, verificationLink);

        var emailMessage = new EmailMessage(
            To: request.Email,
            Subject: "Verify your email address - ColaFlow",
            HtmlBody: htmlBody,
            PlainTextBody: $"Click the link to verify your email: {verificationLink}");

        var success = await _emailService.SendEmailAsync(emailMessage, cancellationToken);

        if (!success)
        {
            _logger.LogWarning(
                "Failed to send verification email to {Email} for user {UserId}",
                request.Email,
                request.UserId);
        }
        else
        {
            _logger.LogInformation(
                "Verification email sent to {Email} for user {UserId}",
                request.Email,
                request.UserId);
        }

        return Unit.Value;
    }
}
