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

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

public class VerifyEmailCommandHandler(
    IEmailVerificationTokenRepository tokenRepository,
    IUserRepository userRepository,
    ISecurityTokenService tokenService,
    ILogger<VerifyEmailCommandHandler> logger)
    : IRequestHandler<VerifyEmailCommand, bool>
{
    public async Task<bool> Handle(VerifyEmailCommand request, CancellationToken cancellationToken)
    {
        // Hash the token to look it up
        var tokenHash = tokenService.HashToken(request.Token);
        var verificationToken = await tokenRepository.GetByTokenHashAsync(tokenHash, cancellationToken);

        if (verificationToken == null)
        {
            logger.LogWarning("Email verification token not found");
            return false;
        }

        if (!verificationToken.IsValid)
        {
            logger.LogWarning(
                "Email verification token is invalid. IsExpired: {IsExpired}, IsVerified: {IsVerified}",
                verificationToken.IsExpired,
                verificationToken.IsVerified);
            return false;
        }

        // Get user and mark email as verified
        var user = await userRepository.GetByIdAsync(verificationToken.UserId, cancellationToken);
        if (user == null)
        {
            logger.LogError("User {UserId} not found for email verification", verificationToken.UserId);
            return false;
        }

        // Mark token as verified
        verificationToken.MarkAsVerified();
        await tokenRepository.UpdateAsync(verificationToken, cancellationToken);

        // Mark user email as verified (will emit domain event)
        user.VerifyEmail();
        await userRepository.UpdateAsync(user, cancellationToken);

        logger.LogInformation("Email verified for user {UserId}", user.Id);

        return true;
    }
}
