using MediatR;
using MiningService.Domain.AggregatesModel.MinerAggregate;
using MiningService.Domain.AggregatesModel.ReferralAggregate;

namespace MiningService.API.IntegrationEvents.Handlers;

/// <summary>
/// EN: Handler for UserRegisteredIntegrationEvent - creates a new Miner when user registers.
/// VI: Handler cho UserRegisteredIntegrationEvent - tạo Miner mới khi user đăng ký.
/// </summary>
public class UserRegisteredIntegrationEventHandler : INotificationHandler<UserRegisteredNotification>
{
    private readonly IMinerRepository _minerRepository;
    private readonly IReferralRepository _referralRepository;
    private readonly ILogger<UserRegisteredIntegrationEventHandler> _logger;

    public UserRegisteredIntegrationEventHandler(
        IMinerRepository minerRepository,
        IReferralRepository referralRepository,
        ILogger<UserRegisteredIntegrationEventHandler> logger)
    {
        _minerRepository = minerRepository;
        _referralRepository = referralRepository;
        _logger = logger;
    }

    public async Task Handle(UserRegisteredNotification notification, CancellationToken cancellationToken)
    {
        var @event = notification.Event;
        
        // Check if miner already exists
        var existingMiner = await _minerRepository.GetByUserIdAsync(@event.UserId, cancellationToken);
        if (existingMiner != null)
        {
            _logger.LogWarning("Miner already exists for user {UserId}", @event.UserId);
            return;
        }

        // Create new miner
        var miner = Miner.Create(@event.UserId);
        _minerRepository.Add(miner);

        // If referral code provided, create referral relationship
        if (!string.IsNullOrEmpty(@event.ReferralCode))
        {
            var referrer = await _minerRepository.GetByReferralCodeAsync(@event.ReferralCode, cancellationToken);
            if (referrer != null)
            {
                var referral = Referral.Create(referrer.Id, miner.Id, @event.ReferralCode);
                _referralRepository.Add(referral);
                _logger.LogInformation("Created referral from {ReferrerId} to {ReferredId}", referrer.Id, miner.Id);
            }
        }

        await _minerRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
        _logger.LogInformation("Created miner for user {UserId} with referral code {ReferralCode}", 
            @event.UserId, miner.ReferralCode);
    }
}

/// <summary>
/// EN: Handler for UserKycCompletedIntegrationEvent - activates referral when user completes KYC.
/// VI: Handler cho UserKycCompletedIntegrationEvent - kích hoạt referral khi user hoàn thành KYC.
/// </summary>
public class UserKycCompletedIntegrationEventHandler : INotificationHandler<UserKycCompletedNotification>
{
    private readonly IMinerRepository _minerRepository;
    private readonly IReferralRepository _referralRepository;
    private readonly ILogger<UserKycCompletedIntegrationEventHandler> _logger;

    public UserKycCompletedIntegrationEventHandler(
        IMinerRepository minerRepository,
        IReferralRepository referralRepository,
        ILogger<UserKycCompletedIntegrationEventHandler> logger)
    {
        _minerRepository = minerRepository;
        _referralRepository = referralRepository;
        _logger = logger;
    }

    public async Task Handle(UserKycCompletedNotification notification, CancellationToken cancellationToken)
    {
        var @event = notification.Event;
        
        var miner = await _minerRepository.GetByUserIdAsync(@event.UserId, cancellationToken);
        if (miner == null)
        {
            _logger.LogWarning("Miner not found for user {UserId} during KYC completion", @event.UserId);
            return;
        }

        // Find inactive referral for this user
        var referral = await _referralRepository.GetByReferredIdAsync(miner.Id, cancellationToken);
        if (referral != null && !referral.IsActive)
        {
            referral.Activate();
            _logger.LogInformation("Activated referral {ReferralId} for user {UserId}", referral.Id, @event.UserId);
            await _referralRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
        }
    }
}

// MediatR notification wrappers
public record UserRegisteredNotification(UserRegisteredIntegrationEvent Event) : INotification;
public record UserKycCompletedNotification(UserKycCompletedIntegrationEvent Event) : INotification;
