using System.Text.Json;
using Microsoft.EntityFrameworkCore;

public static class ClinicalAlertFactory
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    };

    public static string SerializeOutboxPayload(object payload) =>
        JsonSerializer.Serialize(payload, JsonOptions);

    /// <summary>
    /// Idempotent INSERT. Returns true when a new row was created.
    /// When <paramref name="observationCode"/> is null, dedupes on encounter + alert type only
    /// (NEWS2, SOFA, GCS). When set, dedupes on encounter + alert type + observation code (trend).
    /// </summary>
    public static async Task<bool> TryInsertAsync(
        AppDbContext db,
        Guid alertId,
        Guid encounterId,
        Guid patientId,
        AlertType alertType,
        AlertSeverity severity,
        string details,
        AlertExplanation? explanation,
        string? observationCode,
        DateTimeOffset triggeredAt,
        CancellationToken ct)
    {
        var explanationJson = explanation is null
            ? null
            : JsonSerializer.Serialize(explanation, JsonOptions);

        var affected = observationCode is null
            ? await db.Database.ExecuteSqlInterpolatedAsync($"""
                INSERT INTO clinical_alerts
                    (id, encounter_id, patient_id, alert_type, severity,
                     details, explanation, status, triggered_at)
                SELECT {alertId}, {encounterId}, {patientId},
                       {alertType.ToDbString()}, {severity.ToDbString()},
                       {details}, {explanationJson}::jsonb, 'OPEN', {triggeredAt}
                WHERE NOT EXISTS (
                    SELECT 1 FROM clinical_alerts
                    WHERE  encounter_id = {encounterId}
                      AND  alert_type   = {alertType.ToDbString()}
                      AND  status       IN ('OPEN', 'ESCALATED')
                )
                """, ct)
            : await db.Database.ExecuteSqlInterpolatedAsync($"""
                INSERT INTO clinical_alerts
                    (id, encounter_id, patient_id, alert_type, severity,
                     details, explanation, observation_code, status, triggered_at)
                SELECT {alertId}, {encounterId}, {patientId},
                       {alertType.ToDbString()}, {severity.ToDbString()},
                       {details}, {explanationJson}::jsonb,
                       {observationCode}, 'OPEN', {triggeredAt}
                WHERE NOT EXISTS (
                    SELECT 1 FROM clinical_alerts
                    WHERE  encounter_id     = {encounterId}
                      AND  alert_type       = {alertType.ToDbString()}
                      AND  observation_code = {observationCode}
                      AND  status           IN ('OPEN', 'ESCALATED')
                )
                """, ct);

        return affected > 0;
    }
}
