public static class SofaCalculator
{
    public static readonly IReadOnlyList<string> SofaObservationCodes = new[]
    {
        "PAO2_MMHG", "FIO2_PCT", "PLATELET_K_UL", "BILIRUBIN_MG_DL",
        "CREATININE_MG_DL", "URINE_OUTPUT_ML_H",
        "SYSTOLIC_BP", "DIASTOLIC_BP", "SPO2", "SUPPLEMENTAL_O2"
    };

    public static readonly IReadOnlySet<string> SofaCodeSet =
        new HashSet<string>(SofaObservationCodes);

    public static bool IsSofaCode(string observationCode) =>
        SofaCodeSet.Contains(observationCode);

    // GCS components and gcs.scored also trigger SOFA re-score (CNS organ system)
    public static bool TriggersRescore(string observationCode) =>
        IsSofaCode(observationCode) || GcsCalculator.IsGcsCode(observationCode);

    public static string CacheKey(Guid encounterId, string code) =>
        $"sofa:{encounterId}:{code}";

    // --- 1. Respiratory: PaO2/FiO2 ratio ---
    public static int ScoreRespiratory(decimal? pao2, decimal? fio2, bool onMechanicalVent)
    {
        if (pao2 is null || fio2 is null || fio2 == 0) return 0;
        var ratio = pao2.Value / (fio2.Value / 100m);
        return ratio switch
        {
            >= 400 when onMechanicalVent     => 0,
            >= 400                           => 0,
            >= 300                           => 1,
            >= 200                           => 2,
            >= 100 when onMechanicalVent     => 3,
            >= 100                           => 2,
            _ when onMechanicalVent          => 4,
            _                                => 3
        };
    }

    // SpO2/FiO2 proxy when PaO2 unavailable (Rice et al. 2007)
    public static int ScoreRespiratoryFromSpo2(decimal? spo2, decimal? fio2, bool onMechanicalVent)
    {
        if (spo2 is null || fio2 is null || fio2 == 0) return 0;
        var sfRatio = spo2.Value / (fio2.Value / 100m);
        return sfRatio switch
        {
            >= 315                           => 0,
            >= 235                           => 1,
            >= 150                           => 2,
            >= 67 when onMechanicalVent      => 3,
            >= 67                            => 2,
            _ when onMechanicalVent          => 4,
            _                                => 3
        };
    }

    // --- 2. Coagulation: Platelet count (k/µL) ---
    public static int ScoreCoagulation(decimal? platelets)
    {
        if (platelets is null) return 0;
        return platelets.Value switch
        {
            >= 150 => 0,
            >= 100 => 1,
            >= 50  => 2,
            >= 20  => 3,
            _      => 4
        };
    }

    // --- 3. Liver: Bilirubin (mg/dL) ---
    public static int ScoreLiver(decimal? bilirubin)
    {
        if (bilirubin is null) return 0;
        return bilirubin.Value switch
        {
            < 1.2m  => 0,
            < 2.0m  => 1,
            < 6.0m  => 2,
            < 12.0m => 3,
            _       => 4
        };
    }

    // --- 4. Cardiovascular: MAP and vasopressor dose ---
    public static int ScoreCardiovascular(decimal? map, VasopressorInfo? vasopressor)
    {
        if (vasopressor is not null)
        {
            return vasopressor.DrugName.ToUpperInvariant() switch
            {
                "DOPAMINE" when vasopressor.DoseUgKgMin > 15m  => 4,
                "EPINEPHRINE" when vasopressor.DoseUgKgMin > 0.1m => 4,
                "NOREPINEPHRINE" when vasopressor.DoseUgKgMin > 0.1m => 4,
                "DOPAMINE" when vasopressor.DoseUgKgMin > 5m   => 3,
                "EPINEPHRINE"                                  => 3,
                "NOREPINEPHRINE"                               => 3,
                "DOPAMINE"                                     => 2,
                "DOBUTAMINE"                                   => 2,
                _                                              => 1
            };
        }

        if (map is null) return 0;
        return map.Value < 70m ? 1 : 0;
    }

    // --- 5. CNS: Glasgow Coma Scale (from Phase 25) ---
    public static int ScoreCns(int? gcsTotal) =>
        GcsCalculator.ToSofaCnsScore(gcsTotal ?? 15);

    // --- 6. Renal: Creatinine (mg/dL) or urine output (mL/day) ---
    public static int ScoreRenal(decimal? creatinine, decimal? urineOutputMlPerDay)
    {
        var creatScore = creatinine switch
        {
            null     => 0,
            < 1.2m   => 0,
            < 2.0m   => 1,
            < 3.5m   => 2,
            < 5.0m   => 3,
            _        => 4
        };

        var urineScore = urineOutputMlPerDay switch
        {
            null    => 0,
            < 200m  => 4,
            < 500m  => 3,
            _       => 0
        };

        return Math.Max(creatScore, urineScore);
    }

    public static SofaResult ComputeTotal(
        int respiratory, int coagulation, int liver,
        int cardiovascular, int cns, int renal) =>
        new(
            Total: respiratory + coagulation + liver + cardiovascular + cns + renal,
            Respiratory: respiratory,
            Coagulation: coagulation,
            Liver: liver,
            Cardiovascular: cardiovascular,
            Cns: cns,
            Renal: renal);

    // Count organ systems with component data for baseline eligibility
    public static int CountPopulatedOrganSystems(
        bool hasRespiratory,
        bool hasCoagulation,
        bool hasLiver,
        bool hasCardiovascular,
        bool hasCns,
        bool hasRenal) =>
        new[] { hasRespiratory, hasCoagulation, hasLiver,
                hasCardiovascular, hasCns, hasRenal }
            .Count(hasData => hasData);
}