using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;

public sealed class UnacknowledgedAlertsCheck
{
    public static readonly ReconciliationCheckType CheckType = ReconciliationCheckType.UnacknowledgedCriticalAlert;

    private readonly AppDbContext _db;
    private readonly ReconciliationPublisher _publisher;
    private readonly ReconciliationJobOptions _opts;
    private readonly ILogger<UnacknowledgedAlertsCheck> _logger;

    public UnacknowledgedAlertsCheck(
        AppDbContext db,
        ReconciliationPublisher publisher,
        IOptions<ReconciliationJobOptions> opts,
        ILogger<UnacknowledgedAlertsCheck> logger)
    {
        _db        = db;
        _publisher = publisher;
        _opts      = opts.Value;
        _logger    = logger;
    }

    public async Task<int> RunAsync(CancellationToken ct)
    {
        var cutoff = DateTimeOffset.UtcNow
            .AddMinutes(-_opts.UnacknowledgedAlertThresholdMinutes);

        // Load all stale critical alerts, grouped by encounter.
        var staleAlerts = await _db.ClinicalAlerts
            .Where(a => a.Severity == AlertSeverity.Critical
                     && a.Status   == AlertStatus.Open
                     && a.TriggeredAt < cutoff)
            .Select(a => new { a.Id, a.EncounterId, a.PatientId, a.TriggeredAt, a.Details })
            .ToListAsync(ct);

        if (!staleAlerts.Any())
        {
            _logger.LogDebug("[RECONCILIATION] Check1 — no stale critical alerts");
            return 0;
        }

        // Group by encounter so one reconciliation_alert covers all alerts in that encounter.
        var byEncounter = staleAlerts
            .GroupBy(a => new { a.EncounterId, a.PatientId })
            .ToList();

        var inserted = 0;
        foreach (var group in byEncounter)
        {
            // Deduplication: skip if an open reconciliation_alert already exists
            // for this check type and encounter (partial index makes this fast).
            var alreadyOpen = await _db.ReconciliationAlerts
                .AnyAsync(r => r.CheckType   == CheckType
                            && r.EncounterId == group.Key.EncounterId
                            && r.ResolvedAt  == null, ct);
            if (alreadyOpen) continue;

            var alertIds = group.Select(a => a.Id).ToList();
            var oldest   = group.Min(a => a.TriggeredAt);
            var details  = $"{alertIds.Count} unacknowledged CRITICAL alert(s) for encounter "
                         + $"{group.Key.EncounterId}. Oldest triggered at {oldest:u}. "
                         + $"Alert IDs: {string.Join(", ", alertIds)}.";

            var rec = new ReconciliationAlert
            {
                Id          = Guid.NewGuid(),
                CheckType   = CheckType,  // ReconciliationCheckType enum
                EncounterId = group.Key.EncounterId,
                PatientId   = group.Key.PatientId,
                Details     = details,
                CreatedAt   = DateTimeOffset.UtcNow,
            };

            _db.ReconciliationAlerts.Add(rec);
            await _db.SaveChangesAsync(ct);
            await _publisher.PublishAsync(rec, ct);

            _logger.LogWarning(
                "[RECONCILIATION] {CheckType} — encounter {EncounterId}: {Details}",
                CheckType, group.Key.EncounterId, details);

            inserted++;
        }

        return inserted;
    }
}