using Hangfire;

namespace foodmarket.Api.Background;

/// <summary>Регистрирует recurring jobs Hangfire при старте приложения.
/// Идемпотентно: RecurringJob.AddOrUpdate перетирает существующее
/// определение, так что миграции job'ов проходят без ручной очистки таблицы
/// <c>hangfire.recurring_jobs</c>.
///
/// Cron-выражения берутся из конфига (<c>Hangfire:Cron:*</c>) с дефолтом
/// «каждый день в 03:30 UTC» для cleanup-джобов — за 30 минут до бэкапа,
/// чтобы бэкап не цеплял временные блокировки PruneStockMovements.</summary>
public class HangfireJobsConfigurator : IHostedService
{
    private readonly IRecurringJobManager _jobs;
    private readonly IConfiguration _cfg;

    public HangfireJobsConfigurator(IRecurringJobManager jobs, IConfiguration cfg)
    {
        _jobs = jobs;
        _cfg = cfg;
    }

    public Task StartAsync(CancellationToken ct)
    {
        // Cron в Hangfire — стандартный 5-полевой (UTC по умолчанию).
        var cronStock = _cfg["Hangfire:Cron:PruneStockMovements"] ?? "30 3 * * *";
        var cronAudit = _cfg["Hangfire:Cron:PruneAuditLog"] ?? "45 3 * * *";

        _jobs.AddOrUpdate<HousekeepingJobs>(
            recurringJobId: "prune-stock-movements",
            methodCall: j => j.PruneStockMovementsAsync(CancellationToken.None),
            cronExpression: cronStock,
            options: new RecurringJobOptions { TimeZone = TimeZoneInfo.Utc });

        _jobs.AddOrUpdate<HousekeepingJobs>(
            recurringJobId: "prune-audit-log",
            methodCall: j => j.PruneAuditLogAsync(CancellationToken.None),
            cronExpression: cronAudit,
            options: new RecurringJobOptions { TimeZone = TimeZoneInfo.Utc });

        // Email-уведомления: weekly-summary в понедельник 07:00 UTC,
        // low-stock каждый день в 08:00 UTC (после weekly чтобы не дублить
        // если оба совпадают). Cron-ы конфигурируются — на тестовом стенде
        // имеет смысл сдвинуть/отключить через "off" специальное значение
        // (не реализовано, пока просто кастомные cron).
        var cronWeekly = _cfg["Hangfire:Cron:WeeklySummary"] ?? "0 7 * * 1";
        var cronLowStock = _cfg["Hangfire:Cron:LowStockAlert"] ?? "0 8 * * *";

        _jobs.AddOrUpdate<EmailNotificationJobs>(
            recurringJobId: "weekly-summary",
            methodCall: j => j.SendWeeklySummariesAsync(CancellationToken.None),
            cronExpression: cronWeekly,
            options: new RecurringJobOptions { TimeZone = TimeZoneInfo.Utc });

        _jobs.AddOrUpdate<EmailNotificationJobs>(
            recurringJobId: "low-stock-alert",
            methodCall: j => j.SendLowStockAlertsAsync(CancellationToken.None),
            cronExpression: cronLowStock,
            options: new RecurringJobOptions { TimeZone = TimeZoneInfo.Utc });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken ct) => Task.CompletedTask;
}
