using MediatR;
using MktXService.Domain.AggregatesModel.CampaignAggregate;

namespace MktXService.API.Application.Commands;

/// <summary>
/// EN: Handler for CreateCampaignCommand.
/// VI: Handler cho CreateCampaignCommand.
/// </summary>
public class CreateCampaignCommandHandler : IRequestHandler<CreateCampaignCommand, CreateCampaignResult>
{
    private readonly ICampaignRepository _campaignRepository;
    private readonly ILogger<CreateCampaignCommandHandler> _logger;

    public CreateCampaignCommandHandler(
        ICampaignRepository campaignRepository,
        ILogger<CreateCampaignCommandHandler> logger)
    {
        _campaignRepository = campaignRepository;
        _logger = logger;
    }

    public async Task<CreateCampaignResult> Handle(
        CreateCampaignCommand request,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("Creating campaign {Name} for merchant {MerchantId}",
            request.Name, request.MerchantId);

        try
        {
            var campaign = new Campaign(
                request.MerchantId,
                request.Name,
                request.Type,
                request.TemplateId);

            // EN: Add segments to campaign
            // VI: Thêm segments vào chiến dịch
            foreach (var segmentId in request.SegmentIds)
            {
                campaign.AddSegment(segmentId);
            }

            // EN: Set schedule if provided
            // VI: Thiết lập lịch trình nếu có
            if (request.Schedule != null)
            {
                campaign.SetSchedule(request.Schedule);
            }

            _campaignRepository.Add(campaign);
            await _campaignRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

            _logger.LogInformation("Campaign {CampaignId} created successfully", campaign.Id);
            return new CreateCampaignResult(true, campaign.Id, null);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to create campaign {Name}", request.Name);
            return new CreateCampaignResult(false, null, ex.Message);
        }
    }
}

/// <summary>
/// EN: Handler for StartCampaignCommand.
/// VI: Handler cho StartCampaignCommand.
/// </summary>
public class StartCampaignCommandHandler : IRequestHandler<StartCampaignCommand, bool>
{
    private readonly ICampaignRepository _campaignRepository;
    private readonly ILogger<StartCampaignCommandHandler> _logger;

    public StartCampaignCommandHandler(
        ICampaignRepository campaignRepository,
        ILogger<StartCampaignCommandHandler> logger)
    {
        _campaignRepository = campaignRepository;
        _logger = logger;
    }

    public async Task<bool> Handle(StartCampaignCommand request, CancellationToken cancellationToken)
    {
        var campaign = await _campaignRepository.GetByIdAsync(request.CampaignId);
        if (campaign == null) return false;

        campaign.Start();
        await _campaignRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Campaign {CampaignId} started", request.CampaignId);
        return true;
    }
}

/// <summary>
/// EN: Handler for PauseCampaignCommand.
/// VI: Handler cho PauseCampaignCommand.
/// </summary>
public class PauseCampaignCommandHandler : IRequestHandler<PauseCampaignCommand, bool>
{
    private readonly ICampaignRepository _campaignRepository;
    private readonly ILogger<PauseCampaignCommandHandler> _logger;

    public PauseCampaignCommandHandler(
        ICampaignRepository campaignRepository,
        ILogger<PauseCampaignCommandHandler> logger)
    {
        _campaignRepository = campaignRepository;
        _logger = logger;
    }

    public async Task<bool> Handle(PauseCampaignCommand request, CancellationToken cancellationToken)
    {
        var campaign = await _campaignRepository.GetByIdAsync(request.CampaignId);
        if (campaign == null) return false;

        campaign.Pause();
        await _campaignRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Campaign {CampaignId} paused", request.CampaignId);
        return true;
    }
}

/// <summary>
/// EN: Handler for ResumeCampaignCommand.
/// VI: Handler cho ResumeCampaignCommand.
/// </summary>
public class ResumeCampaignCommandHandler : IRequestHandler<ResumeCampaignCommand, bool>
{
    private readonly ICampaignRepository _campaignRepository;
    private readonly ILogger<ResumeCampaignCommandHandler> _logger;

    public ResumeCampaignCommandHandler(
        ICampaignRepository campaignRepository,
        ILogger<ResumeCampaignCommandHandler> logger)
    {
        _campaignRepository = campaignRepository;
        _logger = logger;
    }

    public async Task<bool> Handle(ResumeCampaignCommand request, CancellationToken cancellationToken)
    {
        var campaign = await _campaignRepository.GetByIdAsync(request.CampaignId);
        if (campaign == null) return false;

        campaign.Resume();
        await _campaignRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Campaign {CampaignId} resumed", request.CampaignId);
        return true;
    }
}

/// <summary>
/// EN: Handler for CancelCampaignCommand.
/// VI: Handler cho CancelCampaignCommand.
/// </summary>
public class CancelCampaignCommandHandler : IRequestHandler<CancelCampaignCommand, bool>
{
    private readonly ICampaignRepository _campaignRepository;
    private readonly ILogger<CancelCampaignCommandHandler> _logger;

    public CancelCampaignCommandHandler(
        ICampaignRepository campaignRepository,
        ILogger<CancelCampaignCommandHandler> logger)
    {
        _campaignRepository = campaignRepository;
        _logger = logger;
    }

    public async Task<bool> Handle(CancelCampaignCommand request, CancellationToken cancellationToken)
    {
        var campaign = await _campaignRepository.GetByIdAsync(request.CampaignId);
        if (campaign == null) return false;

        campaign.Cancel();
        await _campaignRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Campaign {CampaignId} cancelled: {Reason}", 
            request.CampaignId, request.Reason);
        return true;
    }
}

/// <summary>
/// EN: Handler for UpdateCampaignMetricsCommand.
/// VI: Handler cho UpdateCampaignMetricsCommand.
/// </summary>
public class UpdateCampaignMetricsCommandHandler : IRequestHandler<UpdateCampaignMetricsCommand, bool>
{
    private readonly ICampaignRepository _campaignRepository;

    public UpdateCampaignMetricsCommandHandler(ICampaignRepository campaignRepository)
    {
        _campaignRepository = campaignRepository;
    }

    public async Task<bool> Handle(UpdateCampaignMetricsCommand request, CancellationToken cancellationToken)
    {
        var campaign = await _campaignRepository.GetByIdAsync(request.CampaignId);
        if (campaign == null) return false;

        var metrics = new CampaignMetrics(
            request.Sent, request.Delivered, request.Opened,
            request.Clicked, request.Replied, request.Failed);

        campaign.UpdateMetrics(metrics);
        await _campaignRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        return true;
    }
}
