using Microsoft.Extensions.Logging;
using MktXService.Domain.AggregatesModel.CampaignAggregate;
using MktXService.Domain.AggregatesModel.SegmentAggregate;
using MktXService.Domain.AggregatesModel.ContactAggregate;
using MktXService.Infrastructure.ExternalServices.Twitter;
using Quartz;

namespace MktXService.Infrastructure.BackgroundJobs;

/// <summary>
/// EN: Background job for processing scheduled campaigns.
/// VI: Background job để xử lý các chiến dịch đã lên lịch.
/// </summary>
/// <remarks>
/// EN: Runs periodically to check for campaigns that need to start based on schedule.
/// VI: Chạy định kỳ để kiểm tra các chiến dịch cần bắt đầu dựa trên lịch trình.
/// </remarks>
[DisallowConcurrentExecution]
public class CampaignSchedulerJob : IJob
{
    private readonly ICampaignRepository _campaignRepository;
    private readonly ISegmentRepository _segmentRepository;
    private readonly IContactRepository _contactRepository;
    private readonly ILogger<CampaignSchedulerJob> _logger;

    public CampaignSchedulerJob(
        ICampaignRepository campaignRepository,
        ISegmentRepository segmentRepository,
        IContactRepository contactRepository,
        ILogger<CampaignSchedulerJob> logger)
    {
        _campaignRepository = campaignRepository;
        _segmentRepository = segmentRepository;
        _contactRepository = contactRepository;
        _logger = logger;
    }

    public async Task Execute(IJobExecutionContext context)
    {
        _logger.LogInformation("CampaignSchedulerJob started at {Time}", DateTimeOffset.UtcNow);

        try
        {
            // EN: Get all scheduled campaigns that should start now
            // VI: Lấy tất cả chiến dịch đã lên lịch cần bắt đầu
            var campaignsToStart = await _campaignRepository.GetScheduledCampaignsAsync(DateTime.UtcNow);

            foreach (var campaign in campaignsToStart)
            {
                try
                {
                    await ProcessCampaignAsync(campaign, context.CancellationToken);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Failed to start campaign {CampaignId}", campaign.Id);
                }
            }

            _logger.LogInformation("CampaignSchedulerJob completed. Processed {Count} campaigns", 
                campaignsToStart.Count());
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "CampaignSchedulerJob failed");
            throw new JobExecutionException(ex, refireImmediately: false);
        }
    }

    private async Task ProcessCampaignAsync(Campaign campaign, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Starting campaign {CampaignId}: {Name}", campaign.Id, campaign.Name);

        // EN: Start the campaign
        // VI: Bắt đầu chiến dịch
        campaign.Start();

        // EN: Get all segments for this campaign
        // VI: Lấy tất cả phân khúc cho chiến dịch này
        var segments = await _segmentRepository.GetByIdsAsync(campaign.SegmentIds);

        // EN: Calculate total contacts
        // VI: Tính tổng số liên hệ
        var totalContacts = 0;
        foreach (var segment in segments)
        {
            // EN: In production, apply segment conditions to query contacts
            // VI: Trong production, áp dụng điều kiện phân khúc để truy vấn liên hệ
            totalContacts += segment.ContactCount;
        }

        _logger.LogInformation("Campaign {CampaignId} targeting {ContactCount} contacts from {SegmentCount} segments",
            campaign.Id, totalContacts, segments.Count());

        // EN: Queue messages for processing (will be handled by MessageProcessorJob)
        // VI: Đưa tin nhắn vào hàng đợi để xử lý (sẽ được MessageProcessorJob xử lý)
        // In production, this would publish to a message queue like RabbitMQ

        await _campaignRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
    }
}

/// <summary>
/// EN: Schedule configuration for CampaignSchedulerJob.
/// VI: Cấu hình lịch trình cho CampaignSchedulerJob.
/// </summary>
public static class CampaignSchedulerJobSetup
{
    public static void ConfigureJob(IServiceCollectionQuartzConfigurator configurator)
    {
        var jobKey = new JobKey(nameof(CampaignSchedulerJob));

        configurator.AddJob<CampaignSchedulerJob>(opts => opts.WithIdentity(jobKey));

        configurator.AddTrigger(opts => opts
            .ForJob(jobKey)
            .WithIdentity($"{nameof(CampaignSchedulerJob)}-trigger")
            .WithCronSchedule("0 * * ? * *")); // EN: Every minute / VI: Mỗi phút
    }
}
