using Microsoft.EntityFrameworkCore;

public sealed class WardGatewayMetricsCollector : BackgroundService
{
    private readonly IServiceScopeFactory _scopes;
    private readonly ClinicalMetrics _metrics;
    private readonly ILogger<WardGatewayMetricsCollector> _logger;

    public WardGatewayMetricsCollector(
        IServiceScopeFactory scopes,
        ClinicalMetrics metrics,
        ILogger<WardGatewayMetricsCollector> logger)
    {
        _scopes = scopes;
        _metrics = metrics;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        using var timer = new PeriodicTimer(TimeSpan.FromSeconds(60));
        while (await timer.WaitForNextTickAsync(ct))
            await CollectAsync(ct);
    }

    private async Task CollectAsync(CancellationToken ct)
    {
        try
        {
            await using var scope = _scopes.CreateAsyncScope();
            var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();

            var offlineBySite = await db.WardGateways
                .Include(g => g.Site)
                .Where(g => g.Status != GatewayStatus.Online)
                .GroupBy(g => g.Site.SiteCode)
                .Select(g => new { SiteCode = g.Key, Count = g.Count() })
                .ToListAsync(ct);

            foreach (var row in offlineBySite)
                _metrics.WardGatewaysOffline.WithLabels(row.SiteCode).Set(row.Count);

            var allGateways = await db.WardGateways
                .AsNoTracking()
                .ToListAsync(ct);

            foreach (var g in allGateways)
                _metrics.WardGatewayBufferDepth
                    .WithLabels(g.GatewayCode, g.Department)
                    .Set(g.ReportedBufferDepth);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "WardGatewayMetricsCollector failed");
        }
    }
}