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

namespace KArtSell.Host.Jobs;

/// <summary>
/// Weekly recommendation report generation job.
/// Runs every Monday at 09:00 KST, summarizes sell decisions from previous week.
/// Idempotent: keyed by week start date to prevent duplicate reports.
/// </summary>
public sealed class GenerateWeeklyRecommendationJob
{
    private readonly IServiceProvider _serviceProvider;
    private readonly IClock _clock;
    private readonly ILogger<GenerateWeeklyRecommendationJob> _logger;

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

    [Queue("q-recommendation")]
    public async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("WeeklyRecommendation 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 week (Saturday)
            var daysToSubtract = (int)currentDate.DayOfWeek - (int)DayOfWeek.Saturday;
            if (daysToSubtract < 0)
                daysToSubtract += 7;
            var weekStart = currentDate.AddDays(-daysToSubtract);

            var idempotencyKey = $"weekly:{weekStart:yyyy-MM-dd}";
            if (await reportGenerator.HasReportBeenSentAsync(idempotencyKey, cancellationToken))
            {
                _logger.LogInformation("Weekly report already sent for week starting {Date}. Skipping", weekStart);
                return;
            }

            var report = await reportGenerator.GenerateWeeklyRecommendationAsync(weekStart, cancellationToken);
            await reportGenerator.SendRecommendationReportAsync(report, cancellationToken);
            await reportGenerator.MarkReportSentAsync(idempotencyKey, cancellationToken);

            _logger.LogInformation(
                "Weekly recommendation report sent. WeekStart={Date}, Recommendations={Count}",
                weekStart,
                report.Recommendations.Count);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Weekly recommendation job failed");
            throw;
        }
    }
}
