using Microsoft.EntityFrameworkCore;

public class LocalWarningEvaluator
{
    private readonly GatewayDbContext _db;
    private readonly ILogger<LocalWarningEvaluator> _logger;

    public LocalWarningEvaluator(GatewayDbContext db, ILogger<LocalWarningEvaluator> logger)
    {
        _db = db;
        _logger = logger;
    }

    public async Task<bool> TryEvaluateAsync(
        Guid observationId, Guid encounterId, Guid patientId,
        string observationCode, decimal value, ThresholdCacheEntry threshold)
    {
        if (!IsWarningBreach(value, threshold)) return false;
        if (IsCriticalBreach(value, threshold)) return false;

        var alertType = AlertTypeExtensions.WarningFor(observationCode);
        var clientAlertId = Guid.NewGuid();
        var triggeredAt = DateTimeOffset.UtcNow;
        var details = BuildWarningDetails(observationCode, value, threshold);

        var exists = await _db.ClinicalAlerts.AnyAsync(a =>
            a.EncounterId == encounterId
            && a.AlertType == alertType
            && (a.Status == AlertStatus.Open || a.Status == AlertStatus.Acknowledged));
        if (exists) return false;

        var alert = new LocalClinicalAlert
        {
            Id = Guid.NewGuid(),
            ClientAlertId = clientAlertId,
            EncounterId = encounterId,
            PatientId = patientId,
            ObservationId = observationId,
            AlertType = alertType,
            Severity = AlertSeverity.Warning,
            Details = details,
            Status = AlertStatus.Open,
            TriggeredAt = triggeredAt
        };
        _db.ClinicalAlerts.Add(alert);

        BufferedSyncWriter.Enqueue(_db, BufferedSyncItemType.Alert, new
        {
            clientAlertId,
            encounterId,
            alertType = alertType.ToDbString(),
            severity = AlertSeverity.Warning.ToDbString(),
            details,
            generatedAt = triggeredAt
        }, $"alert:{clientAlertId}", encounterId, triggeredAt);

        _logger.LogInformation(
            "WARNING alert {AlertId} created locally for encounter {EncounterId}",
            alert.Id, encounterId);
        return true;
    }

    private static bool IsWarningBreach(decimal value, ThresholdCacheEntry t) =>
        (t.WarningHigh.HasValue && value > t.WarningHigh.Value) ||
        (t.WarningLow.HasValue && value < t.WarningLow.Value);

    private static bool IsCriticalBreach(decimal value, ThresholdCacheEntry t) =>
        (t.CriticalLow.HasValue && value < t.CriticalLow.Value) ||
        (t.CriticalHigh.HasValue && value > t.CriticalHigh.Value);

    private static string BuildWarningDetails(string code, decimal value, ThresholdCacheEntry t) =>
        t.WarningHigh.HasValue && value > t.WarningHigh.Value
            ? $"{code} value {value} is above warning high of {t.WarningHigh}."
            : $"{code} value {value} is below warning low of {t.WarningLow}.";
}
