using Microsoft.Extensions.Options;

public sealed class ReconciliationScheduler : BackgroundService
{
    private readonly IServiceScopeFactory _scopes;
    private readonly ReconciliationJobOptions _opts;
    private readonly ILogger<ReconciliationScheduler> _logger;

    public ReconciliationScheduler(
        IServiceScopeFactory scopes,
        IOptions<ReconciliationJobOptions> opts,
        ILogger<ReconciliationScheduler> logger)
    {
        _scopes = scopes;
        _opts   = opts.Value;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // Wait for RabbitMQ topology and migrations before first cycle.
        await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);

        _logger.LogInformation(
            "ReconciliationScheduler started — interval {IntervalMinutes} min", _opts.IntervalMinutes);

        using var timer = new PeriodicTimer(TimeSpan.FromMinutes(_opts.IntervalMinutes));

        while (await timer.WaitForNextTickAsync(stoppingToken))
        {
            _logger.LogInformation("[RECONCILIATION] Starting reconciliation cycle");

            await RunCheckAsync<UnacknowledgedAlertsCheck>(
                check => check.RunAsync(stoppingToken), stoppingToken);

            await RunCheckAsync<PendingOrdersCheck>(
                check => check.RunAsync(stoppingToken), stoppingToken);

            await RunCheckAsync<DisconnectedMonitorsCheck>(
                check => check.RunAsync(stoppingToken), stoppingToken);

            _logger.LogInformation("[RECONCILIATION] Cycle complete");
        }
    }

    private async Task RunCheckAsync<T>(Func<T, Task<int>> run, CancellationToken ct)
        where T : notnull
    {
        try
        {
            await using var scope = _scopes.CreateAsyncScope();
            var check  = scope.ServiceProvider.GetRequiredService<T>();
            var count  = await run(check);
            _logger.LogInformation(
                "[RECONCILIATION] {Check} — new alerts: {Count}", typeof(T).Name, count);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "[RECONCILIATION] {Check} failed", typeof(T).Name);
        }
    }
}