public static class MimicItemMap
{
    public record ChartItemMapping(
        string Code, string Unit, string Source,
        int Priority = 0,
        bool ConvertFahrenheit = false);

    public record LabItemMapping(string Code, string Unit);

    private static readonly Dictionary<int, ChartItemMapping> ChartMappings = new()
    {
        [220045] = new("HEART_RATE", "bpm", "Device"),
        [220210] = new("RESP_RATE", "/min", "Device"),
        [220179] = new("SYSTOLIC_BP", "mmHg", "Device"),
        [220180] = new("DIASTOLIC_BP", "mmHg", "Device"),
        [220050] = new("SYSTOLIC_BP", "mmHg", "Device", Priority: 1),
        [220051] = new("DIASTOLIC_BP", "mmHg", "Device", Priority: 1),
        [223762] = new("TEMP_C", "°C", "Manual"),
        [223761] = new("TEMP_C", "°C", "Manual", ConvertFahrenheit: true),
        [220277] = new("SPO2", "%", "Device"),
        [223835] = new("FIO2_PCT", "%", "Device"),
        [220739] = new("GCS_EYE", "score", "Manual"),
        [223900] = new("GCS_VERBAL", "score", "Manual"),
        [223901] = new("GCS_MOTOR", "score", "Manual"),
        [220615] = new("CREATININE_MG_DL", "mg/dL", "Lab"),
        [225690] = new("BILIRUBIN_MG_DL", "mg/dL", "Lab"),
        [225678] = new("PLATELET_K_UL", "k/µL", "Lab"),
        [220224] = new("PAO2_MMHG", "mmHg", "Lab"),
    };

    private static readonly Dictionary<int, LabItemMapping> LabMappings = new()
    {
        [50912] = new("CREATININE_MG_DL", "mg/dL"),
        [51704] = new("PLATELET_K_UL", "k/µL"),
        [50885] = new("BILIRUBIN_MG_DL", "mg/dL"),
        [50813] = new("LACTATE_MMOL_L", "mmol/L"),
        [51301] = new("WBC_K_UL", "k/µL"),
        [50971] = new("POTASSIUM_MEQ_L", "mEq/L"),
        [50931] = new("GLUCOSE_MG_DL", "mg/dL"),
        [50821] = new("PAO2_MMHG", "mmHg"),
    };

    // GCS text → numeric fallback (in case valuenum is missing)
    private static readonly Dictionary<string, int> GcsEyeText = new(StringComparer.OrdinalIgnoreCase)
    {
        ["None"] = 1, ["No Response"] = 1,
        ["To Pain"] = 2,
        ["To Speech"] = 3,
        ["Spontaneously"] = 4,
    };

    private static readonly Dictionary<string, int> GcsVerbalText = new(StringComparer.OrdinalIgnoreCase)
    {
        ["No Response"] = 1, ["No Response-ETT"] = 1,
        ["Incomprehensible sounds"] = 2, ["Incomprehensible Sounds"] = 2,
        ["Inappropriate Words"] = 3,
        ["Confused"] = 4,
        ["Oriented"] = 5,
    };

    private static readonly Dictionary<string, int> GcsMotorText = new(StringComparer.OrdinalIgnoreCase)
    {
        ["No response"] = 1, ["No Response"] = 1,
        ["Abnormal extension"] = 2, ["Abnormal Extension"] = 2,
        ["Abnormal Flexion"] = 3,
        ["Flex-withdraws"] = 3, ["Flex-Withdraws"] = 3,
        ["Localizes Pain"] = 4,
        ["Obeys Commands"] = 6,
    };

    public static readonly HashSet<int> AllChartItemIds = new(ChartMappings.Keys);
    public static readonly HashSet<int> AllLabItemIds = new(LabMappings.Keys);

    public static bool TryMapChartEvent(int itemId, out ChartItemMapping mapping)
        => ChartMappings.TryGetValue(itemId, out mapping!);

    public static bool TryMapLabEvent(int itemId, out LabItemMapping mapping)
        => LabMappings.TryGetValue(itemId, out mapping!);

    public static decimal ConvertValue(decimal rawValue, ChartItemMapping mapping)
    {
        if (mapping.ConvertFahrenheit)
            return Math.Round((rawValue - 32m) * 5m / 9m, 1);
        return rawValue;
    }

    public static decimal? ResolveGcsValue(int itemId, string? textValue, decimal? numericValue)
    {
        if (numericValue.HasValue && numericValue.Value > 0)
            return numericValue.Value;

        if (string.IsNullOrWhiteSpace(textValue))
            return null;

        var lookup = itemId switch
        {
            220739 => GcsEyeText,
            223900 => GcsVerbalText,
            223901 => GcsMotorText,
            _ => null
        };

        if (lookup is not null && lookup.TryGetValue(textValue, out var score))
            return score;

        return null;
    }

    public static bool IsGcsItem(int itemId) => itemId is 220739 or 223900 or 223901;
}
