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

namespace KArtSell.Host.Jobs;

/// <summary>
/// Daily recommendation report generation job.
/// Runs at 09:00 KST (market open), summarizes sell decisions from previous trading day.
/// Idempotent: keyed by trading date to prevent duplicate reports.
/// </summary>
public sealed class GenerateDailyRecommendationJob
{
    private readonly IServiceProvider _serviceProvider;
    private readonly IClock _clock;
    private readonly ILogger<GenerateDailyRecommendationJob> _logger;

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

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

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

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

            var idempotencyKey = $"daily:{reportDate:yyyy-MM-dd}";
            if (await reportGenerator.HasReportBeenSentAsync(idempotencyKey, cancellationToken))
            {
                _logger.LogInformation("Daily report already sent for {Date}. Skipping", reportDate);
                return;
            }

            var report = await reportGenerator.GenerateDailyRecommendationAsync(reportDate, cancellationToken);
            await reportGenerator.SendRecommendationReportAsync(report, cancellationToken);
            await reportGenerator.MarkReportSentAsync(idempotencyKey, cancellationToken);

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