using Hangfire;
using KArtSell.BuildingBlocks.Time;
using Microsoft.Extensions.Logging;

namespace KArtSell.Host.Jobs;

/// <summary>
/// Monthly recommendation report generation job.
/// Runs on the 1st of every month at 09:00 KST, summarizes sell decisions from previous month.
/// Idempotent: keyed by month start date to prevent duplicate reports.
/// </summary>
public sealed class GenerateMonthlyRecommendationJob
{
    private readonly IServiceProvider _serviceProvider;
    private readonly IClock _clock;
    private readonly ILogger<GenerateMonthlyRecommendationJob> _logger;

    public GenerateMonthlyRecommendationJob(
        IServiceProvider serviceProvider,
        IClock clock,
        ILogger<GenerateMonthlyRecommendationJob> logger)
    {
        _serviceProvider = serviceProvider;
        _clock = clock;
        _logger = logger;
    }

    [Queue("q-recommendation")]
    public async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("MonthlyRecommendation job started");

        try
        {
            using var scope = _serviceProvider.CreateAsyncScope();
            var reportGenerator = scope.ServiceProvider.GetRequiredService<RecommendationReportGenerator>();

            var now = _clock.UtcNow;
            var currentDate = now.DateTime.Date;

            // Get start of current month
            var monthStart = new DateTime(currentDate.Year, currentDate.Month, 1);

            var idempotencyKey = $"monthly:{monthStart:yyyy-MM-dd}";
            if (await reportGenerator.HasReportBeenSentAsync(idempotencyKey, cancellationToken))
            {
                _logger.LogInformation("Monthly report already sent for {Month}. Skipping", monthStart.ToString("yyyy-MM"));
                return;
            }

            var report = await reportGenerator.GenerateMonthlyRecommendationAsync(monthStart, cancellationToken);
            await reportGenerator.SendRecommendationReportAsync(report, cancellationToken);
            await reportGenerator.MarkReportSentAsync(idempotencyKey, cancellationToken);

            _logger.LogInformation(
                "Monthly recommendation report sent. Month={Month}, Recommendations={Count}",
                monthStart.ToString("yyyy-MM"),
                report.Recommendations.Count);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Monthly recommendation job failed");
            throw;
        }
    }
}
