// bronsted_lowry.sy -- Bronsted-Lowry acid-base chemistry as native Scyla.
//
// Sources:
//   Atkins PW, de Paula J. Physical Chemistry, 11th ed, OUP, 2018.
//   Nelson DL, Cox MM. Lehninger Principles of Biochemistry, 8th ed, 2021.
//   Guyton AC, Hall JE. Textbook of Medical Physiology, 14th ed, 2021.
//
// Marjorie McCubbins + Aether, April 2026
// Patent pending: 64/034,536

// ===============================================================
// STRUCTS
// ===============================================================

struct BronstedAcid {
    name: String,
    formula: String,
    ka: Float,
    pka: Float,
    conjugate_base: String,
    acid_type: String,
    proton_index: Int,
    citation: String,
}

struct BronstedBase {
    name: String,
    formula: String,
    kb: Float,
    pkb: Float,
    conjugate_acid: String,
    base_type: String,
    citation: String,
}

struct BufferInfo {
    name: String,
    acid_form: String,
    base_form: String,
    pka: Float,
    effective_low: Float,
    effective_high: Float,
    preparation: String,
    biological_use: String,
    citation: String,
}

struct BloodBufferState {
    ph: Float,
    pco2_mmhg: Float,
    hco3_meq_l: Float,
    normal_ph_low: Float,
    normal_ph_high: Float,
    normal_pco2_low: Float,
    normal_pco2_high: Float,
    normal_hco3_low: Float,
    normal_hco3_high: Float,
    citation: String,
}

struct ABGClassification {
    primary_disorder: String,
    ph_status: String,
    respiratory_component: String,
    metabolic_component: String,
    compensation: String,
    citation: String,
}

struct PHIndicatorInfo {
    name: String,
    low_color: String,
    high_color: String,
    transition_low: Float,
    transition_high: Float,
    indicator_class: String,
    citation: String,
}

// ===============================================================
// CONSTRUCTOR HELPERS
// ===============================================================

fn make_acid(n: String, f: String, ka: Float, pka: Float, cb: String, at: String, pi: Int, ci: String) -> BronstedAcid {
    return BronstedAcid { name: n, formula: f, ka: ka, pka: pka, conjugate_base: cb, acid_type: at, proton_index: pi, citation: ci }
}

fn make_base(n: String, f: String, kb: Float, pkb: Float, ca: String, bt: String, ci: String) -> BronstedBase {
    return BronstedBase { name: n, formula: f, kb: kb, pkb: pkb, conjugate_acid: ca, base_type: bt, citation: ci }
}

fn make_buffer(n: String, af: String, bf: String, pk: Float, el: Float, eh: Float, pr: String, bu: String, ci: String) -> BufferInfo {
    return BufferInfo { name: n, acid_form: af, base_form: bf, pka: pk, effective_low: el, effective_high: eh, preparation: pr, biological_use: bu, citation: ci }
}

fn make_indicator(n: String, lc: String, hc: String, tl: Float, th: Float, ic: String, ci: String) -> PHIndicatorInfo {
    return PHIndicatorInfo { name: n, low_color: lc, high_color: hc, transition_low: tl, transition_high: th, indicator_class: ic, citation: ci }
}

// ===============================================================
// BRONSTED ACIDS -- proton donors
// ===============================================================
// proton_index: which proton (1 = first dissociation, 2 = second, 3 = third)
// Ka values from Atkins Physical Chemistry 11th ed, Table 6B.1 and Lehninger 8th ed.

fn bronsted_acid(name: String) -> BronstedAcid {

    // ----------------------------------------------------------
    // STRONG ACIDS (pKa < 0, effectively complete dissociation)
    // ----------------------------------------------------------
    if name == "HCl" { return make_acid("Hydrochloric acid", "HCl", 1000000.0, -6.0, "Cl-", "strong monoprotic", 1, "Atkins 11th ed") }
    if name == "HBr" { return make_acid("Hydrobromic acid", "HBr", 1000000000.0, -9.0, "Br-", "strong monoprotic", 1, "Atkins 11th ed") }
    if name == "HI" { return make_acid("Hydroiodic acid", "HI", 10000000000.0, -10.0, "I-", "strong monoprotic", 1, "Atkins 11th ed") }
    if name == "HNO3" { return make_acid("Nitric acid", "HNO3", 28.0, -1.4, "NO3-", "strong monoprotic", 1, "Atkins 11th ed") }
    if name == "H2SO4" { return make_acid("Sulfuric acid (first proton)", "H2SO4", 1000.0, -3.0, "HSO4-", "strong diprotic", 1, "Atkins 11th ed") }
    if name == "H2SO4_2" { return make_acid("Sulfuric acid (second proton)", "HSO4-", 0.012, 1.92, "SO4 2-", "strong diprotic", 2, "Atkins 11th ed") }
    if name == "HClO4" { return make_acid("Perchloric acid", "HClO4", 10000000000.0, -10.0, "ClO4-", "strong monoprotic", 1, "Atkins 11th ed") }

    // ----------------------------------------------------------
    // WEAK ACIDS -- carboxylic acids
    // ----------------------------------------------------------
    if name == "acetic" { return make_acid("Acetic acid", "CH3COOH", 0.0000174, 4.76, "CH3COO- (acetate)", "weak monoprotic", 1, "Atkins 11th ed, Table 6B.1") }
    if name == "formic" { return make_acid("Formic acid", "HCOOH", 0.000178, 3.75, "HCOO- (formate)", "weak monoprotic", 1, "Atkins 11th ed") }
    if name == "benzoic" { return make_acid("Benzoic acid", "C6H5COOH", 0.0000631, 4.20, "C6H5COO- (benzoate)", "weak monoprotic", 1, "Atkins 11th ed") }
    if name == "lactic" { return make_acid("Lactic acid", "CH3CH(OH)COOH", 0.000138, 3.86, "CH3CH(OH)COO- (lactate)", "weak monoprotic", 1, "Lehninger 8th ed") }
    if name == "ascorbic" { return make_acid("Ascorbic acid (vitamin C)", "C6H8O6", 0.0000676, 4.17, "ascorbate", "weak diprotic", 1, "Atkins 11th ed") }
    if name == "propionic" { return make_acid("Propionic acid", "CH3CH2COOH", 0.0000135, 4.87, "CH3CH2COO- (propanoate)", "weak monoprotic", 1, "Atkins 11th ed") }

    // ----------------------------------------------------------
    // WEAK ACIDS -- inorganic
    // ----------------------------------------------------------
    if name == "HF" { return make_acid("Hydrofluoric acid", "HF", 0.000676, 3.17, "F-", "weak monoprotic", 1, "Atkins 11th ed") }
    if name == "HNO2" { return make_acid("Nitrous acid", "HNO2", 0.000398, 3.40, "NO2-", "weak monoprotic", 1, "Atkins 11th ed") }
    if name == "HClO" { return make_acid("Hypochlorous acid", "HClO", 0.0000000288, 7.54, "ClO- (hypochlorite)", "weak monoprotic", 1, "Atkins 11th ed") }
    if name == "boric" { return make_acid("Boric acid", "B(OH)3", 0.000000000575, 9.24, "B(OH)4-", "weak monoprotic (Lewis acid in water)", 1, "Atkins 11th ed") }

    // ----------------------------------------------------------
    // WEAK ACIDS -- phenols
    // ----------------------------------------------------------
    if name == "phenol" { return make_acid("Phenol", "C6H5OH", 0.0000000000112, 9.95, "C6H5O- (phenolate)", "weak monoprotic", 1, "Atkins 11th ed") }

    // ----------------------------------------------------------
    // POLYPROTIC -- citric acid (triprotic)
    // ----------------------------------------------------------
    if name == "citric_1" { return make_acid("Citric acid (first proton)", "H3C6H5O7", 0.000741, 3.13, "H2C6H5O7-", "weak triprotic", 1, "Lehninger 8th ed") }
    if name == "citric_2" { return make_acid("Citric acid (second proton)", "H2C6H5O7-", 0.0000174, 4.76, "HC6H5O7 2-", "weak triprotic", 2, "Lehninger 8th ed") }
    if name == "citric_3" { return make_acid("Citric acid (third proton)", "HC6H5O7 2-", 0.000000398, 6.40, "C6H5O7 3- (citrate)", "weak triprotic", 3, "Lehninger 8th ed") }

    // ----------------------------------------------------------
    // POLYPROTIC -- carbonic acid (diprotic)
    // ----------------------------------------------------------
    if name == "carbonic_1" { return make_acid("Carbonic acid (first proton)", "H2CO3", 0.000000447, 6.35, "HCO3- (bicarbonate)", "weak diprotic", 1, "Atkins 11th ed") }
    if name == "carbonic_2" { return make_acid("Carbonic acid (second proton)", "HCO3-", 0.0000000000468, 10.33, "CO3 2- (carbonate)", "weak diprotic", 2, "Atkins 11th ed") }

    // ----------------------------------------------------------
    // POLYPROTIC -- phosphoric acid (triprotic)
    // ----------------------------------------------------------
    if name == "phosphoric_1" { return make_acid("Phosphoric acid (first proton)", "H3PO4", 0.00708, 2.15, "H2PO4-", "weak triprotic", 1, "Atkins 11th ed") }
    if name == "phosphoric_2" { return make_acid("Phosphoric acid (second proton)", "H2PO4-", 0.0000000631, 7.20, "HPO4 2-", "weak triprotic", 2, "Atkins 11th ed") }
    if name == "phosphoric_3" { return make_acid("Phosphoric acid (third proton)", "HPO4 2-", 0.00000000000000447, 12.35, "PO4 3-", "weak triprotic", 3, "Atkins 11th ed") }

    // ----------------------------------------------------------
    // POLYPROTIC -- oxalic acid (diprotic)
    // ----------------------------------------------------------
    if name == "oxalic_1" { return make_acid("Oxalic acid (first proton)", "H2C2O4", 0.0562, 1.25, "HC2O4-", "weak diprotic", 1, "Atkins 11th ed") }
    if name == "oxalic_2" { return make_acid("Oxalic acid (second proton)", "HC2O4-", 0.0000537, 4.27, "C2O4 2- (oxalate)", "weak diprotic", 2, "Atkins 11th ed") }

    // ----------------------------------------------------------
    // AMINO ACID SIDE CHAINS
    // ----------------------------------------------------------
    // pKa values for ionizable side chains at 25C. Lehninger 8th ed, Table 3-1.
    if name == "Asp" { return make_acid("Aspartic acid (side chain)", "-CH2COOH", 0.000224, 3.65, "-CH2COO-", "amino acid side chain (carboxyl)", 1, "Lehninger 8th ed, Table 3-1") }
    if name == "Glu" { return make_acid("Glutamic acid (side chain)", "-CH2CH2COOH", 0.0000562, 4.25, "-CH2CH2COO-", "amino acid side chain (carboxyl)", 1, "Lehninger 8th ed, Table 3-1") }
    if name == "His" { return make_acid("Histidine (imidazolium)", "imidazolium+", 0.000001, 6.00, "imidazole", "amino acid side chain (imidazole). Near physiological pH: biological proton shuttle.", 1, "Lehninger 8th ed, Table 3-1") }
    if name == "Cys" { return make_acid("Cysteine (thiol)", "-CH2SH", 0.00000000661, 8.18, "-CH2S-", "amino acid side chain (sulfhydryl). Disulfide bridge formation when deprotonated.", 1, "Lehninger 8th ed, Table 3-1") }
    if name == "Tyr" { return make_acid("Tyrosine (phenol)", "-C6H4OH", 0.0000000000851, 10.07, "-C6H4O-", "amino acid side chain (phenol)", 1, "Lehninger 8th ed, Table 3-1") }
    if name == "Lys" { return make_acid("Lysine (epsilon-amino)", "-(CH2)4NH3+", 0.0000000000295, 10.53, "-(CH2)4NH2", "amino acid side chain (amino). Usually protonated at physiological pH.", 1, "Lehninger 8th ed, Table 3-1") }
    if name == "Arg" { return make_acid("Arginine (guanidinium)", "guanidinium+", 0.0000000000000331, 12.48, "guanidine", "amino acid side chain (guanidino). Almost always protonated at physiological pH.", 1, "Lehninger 8th ed, Table 3-1") }

    // ----------------------------------------------------------
    // WATER (autoionization)
    // ----------------------------------------------------------
    if name == "water" { return make_acid("Water", "H2O", 0.0000000000000018, 15.74, "OH-", "amphoteric. Kw = 1.0e-14 at 25C.", 1, "Atkins 11th ed") }

    return make_acid("", "", 0.0, 0.0, "", "", 0, "")
}

// ===============================================================
// BRONSTED BASES -- proton acceptors
// ===============================================================
// Kb and pKb computed from conjugate acid: Kb = Kw / Ka, pKb = 14 - pKa

fn bronsted_base(name: String) -> BronstedBase {
    // ----------------------------------------------------------
    // STRONG BASES (complete dissociation in water)
    // ----------------------------------------------------------
    if name == "NaOH" { return make_base("Sodium hydroxide", "NaOH", 1000000.0, -6.0, "Na+ + H2O", "strong", "Atkins 11th ed") }
    if name == "KOH" { return make_base("Potassium hydroxide", "KOH", 1000000.0, -6.0, "K+ + H2O", "strong", "Atkins 11th ed") }
    if name == "Ca(OH)2" { return make_base("Calcium hydroxide", "Ca(OH)2", 100000.0, -5.0, "Ca2+ + H2O", "strong (sparingly soluble)", "Atkins 11th ed") }
    if name == "Ba(OH)2" { return make_base("Barium hydroxide", "Ba(OH)2", 1000000.0, -6.0, "Ba2+ + H2O", "strong", "Atkins 11th ed") }

    // ----------------------------------------------------------
    // WEAK BASES
    // ----------------------------------------------------------
    if name == "ammonia" { return make_base("Ammonia", "NH3", 0.0000178, 4.75, "NH4+", "weak", "Atkins 11th ed") }
    if name == "acetate" { return make_base("Acetate ion", "CH3COO-", 0.000000000575, 9.24, "CH3COOH", "weak (conjugate base of acetic acid)", "Atkins 11th ed") }
    if name == "formate" { return make_base("Formate ion", "HCOO-", 0.0000000000562, 10.25, "HCOOH", "weak (conjugate base of formic acid)", "Atkins 11th ed") }
    if name == "bicarbonate" { return make_base("Bicarbonate", "HCO3-", 0.0000000224, 7.65, "H2CO3", "weak amphoteric. Can act as acid (pKa 10.33) or base.", "Atkins 11th ed") }
    if name == "carbonate" { return make_base("Carbonate", "CO3 2-", 0.000214, 3.67, "HCO3-", "weak", "Atkins 11th ed") }
    if name == "phosphate_mono" { return make_base("Dihydrogen phosphate", "H2PO4-", 0.000000159, 6.80, "H3PO4", "weak amphoteric", "Atkins 11th ed") }
    if name == "phosphate_di" { return make_base("Hydrogen phosphate", "HPO4 2-", 0.0000000000000224, 1.65, "H2PO4-", "weak", "Atkins 11th ed") }
    if name == "fluoride" { return make_base("Fluoride ion", "F-", 0.0000000000148, 10.83, "HF", "weak (conjugate base of HF)", "Atkins 11th ed") }
    if name == "pyridine" { return make_base("Pyridine", "C5H5N", 0.00000000178, 8.75, "C5H5NH+", "weak", "Atkins 11th ed") }
    if name == "methylamine" { return make_base("Methylamine", "CH3NH2", 0.000437, 3.36, "CH3NH3+", "weak", "Atkins 11th ed") }
    if name == "ethylamine" { return make_base("Ethylamine", "C2H5NH2", 0.000537, 3.27, "C2H5NH3+", "weak", "Atkins 11th ed") }
    if name == "hydroxide" { return make_base("Hydroxide ion", "OH-", 1000000.0, -6.0, "H2O", "strong (conjugate base of water)", "Atkins 11th ed") }

    return make_base("", "", 0.0, 0.0, "", "", "")
}

// ===============================================================
// PURE CALCULATIONS -- pH, pKa, Henderson-Hasselbalch
// ===============================================================

// Henderson-Hasselbalch equation: pH = pKa + log10([A-]/[HA])
// Central equation for buffer chemistry. Relates pH to ratio of
// conjugate base to weak acid.
// Cited: Atkins 11th ed, Eq 6B.12
fn henderson_hasselbalch(pka: Float, conc_acid: Float, conc_base: Float) -> Float {
    if conc_acid <= 0.0 { return 14.0 }
    if conc_base <= 0.0 { return 0.0 }
    let ratio = conc_base / conc_acid
    return pka + log10(ratio)
}

// Convert Ka to pKa: pKa = -log10(Ka)
fn pka_from_ka(ka: Float) -> Float {
    if ka <= 0.0 { return 0.0 }
    return 0.0 - log10(ka)
}

// Convert pKa to Ka: Ka = 10^(-pKa)
fn ka_from_pka(pka: Float) -> Float {
    return pow(10.0, 0.0 - pka)
}

// Convert pKa to pKb (at 25C): pKb = 14.0 - pKa
// Because Kw = Ka * Kb = 1.0e-14 at 25C
fn pkb_from_pka(pka: Float) -> Float {
    return 14.0 - pka
}

// pH of strong acid: pH = -log10([H+]) = -log10(concentration)
// Valid only for strong acids (complete dissociation)
fn ph_strong_acid(concentration: Float) -> Float {
    if concentration <= 0.0 { return 7.0 }
    return 0.0 - log10(concentration)
}

// pH of strong base: pH = 14 + log10(concentration)
// Because pOH = -log10([OH-]), and pH = 14 - pOH
fn ph_strong_base(concentration: Float) -> Float {
    if concentration <= 0.0 { return 7.0 }
    return 14.0 + log10(concentration)
}

// pH of weak acid (approximation when Ka << C):
// [H+] = sqrt(Ka * C), therefore pH = -log10(sqrt(Ka * C))
// This is the quadratic approximation. Valid when percent ionization < 5%.
// Cited: Atkins 11th ed, Section 6B.2
fn ph_weak_acid(ka: Float, concentration: Float) -> Float {
    if ka <= 0.0 { return 7.0 }
    if concentration <= 0.0 { return 7.0 }
    let h = sqrt(ka * concentration)
    return 0.0 - log10(h)
}

// pOH from pH: pOH = 14.0 - pH (at 25C where Kw = 1e-14)
fn poh_from_ph(ph: Float) -> Float {
    return 14.0 - ph
}

// [H+] from pH: [H+] = 10^(-pH)
fn h_from_ph(ph: Float) -> Float {
    return pow(10.0, 0.0 - ph)
}

// [OH-] from pOH: [OH-] = 10^(-pOH)
fn oh_from_poh(poh: Float) -> Float {
    return pow(10.0, 0.0 - poh)
}

// Buffer capacity (Van Slyke equation):
// beta = 2.303 * C_total * Ka * [H+] / (Ka + [H+])^2
// Measures resistance to pH change. Maximum at pH = pKa.
// Cited: Van Slyke DD. J Biol Chem 52:525-570, 1922
fn buffer_capacity(conc_total: Float, ka: Float, h_concentration: Float) -> Float {
    if conc_total <= 0.0 { return 0.0 }
    if ka <= 0.0 { return 0.0 }
    if h_concentration <= 0.0 { return 0.0 }
    let sum = ka + h_concentration
    let denom = sum * sum
    if denom <= 0.0 { return 0.0 }
    return 2.303 * conc_total * ka * h_concentration / denom
}

// Dilution equation: C1 * V1 = C2 * V2
// Solves for C2 = C1 * V1 / V2
fn dilution(c1: Float, v1: Float, v2: Float) -> Float {
    if v2 <= 0.0 { return 0.0 }
    return c1 * v1 / v2
}

// Titration equivalence point volume:
// At equivalence: moles acid = moles base
// C_acid * V_acid = C_base * V_base
// V_base = C_acid * V_acid / C_base
fn titration_equivalence_volume(conc_acid: Float, vol_acid: Float, conc_base: Float) -> Float {
    if conc_base <= 0.0 { return 0.0 }
    return conc_acid * vol_acid / conc_base
}

// Percent ionization (approximation for weak acids when Ka << C):
// alpha = sqrt(Ka / C) * 100
// Valid when alpha < 5%. For higher ionization use the full quadratic.
// Cited: Atkins 11th ed, Section 6B.2
fn percent_ionization(ka: Float, concentration: Float) -> Float {
    if ka <= 0.0 { return 0.0 }
    if concentration <= 0.0 { return 0.0 }
    return sqrt(ka / concentration) * 100.0
}

// pH from [H+] directly
fn ph_from_h(h: Float) -> Float {
    if h <= 0.0 { return 7.0 }
    return 0.0 - log10(h)
}

// Kw (ion product of water) at 25C
fn kw_25c() -> Float {
    return 0.00000000000001
}

// ===============================================================
// BUFFER SYSTEMS
// ===============================================================
// Common laboratory and biological buffers with effective ranges.
// Effective range = pKa +/- 1 pH unit (where buffer has >10% of each form).
// Cited: Good NE et al. Biochemistry 5:467-477, 1966 (Good's buffers)

fn buffer(name: String) -> BufferInfo {
    if name == "acetate" {
        return make_buffer(
            "Acetate buffer", "CH3COOH (acetic acid)", "CH3COO- Na+ (sodium acetate)",
            4.76, 3.76, 5.76,
            "Mix acetic acid and sodium acetate solutions. Adjust ratio for target pH. Titrate with NaOH if needed.",
            "Biochemistry: enzyme assays at acidic pH. Food science: preservative (E260). Molecular biology: sodium acetate precipitation of DNA.",
            "Atkins 11th ed"
        )
    }
    if name == "phosphate" {
        return make_buffer(
            "Phosphate buffer", "NaH2PO4 (monobasic sodium phosphate)", "Na2HPO4 (dibasic sodium phosphate)",
            7.20, 6.20, 8.20,
            "Mix NaH2PO4 and Na2HPO4 in appropriate ratio. Sorensen buffer: standard in biochemistry. PBS adds 137mM NaCl, 2.7mM KCl.",
            "PBS (phosphate-buffered saline): cell culture, immunohistochemistry, ELISA washes. Intracellular buffering. FDA-approved excipient.",
            "Lehninger 8th ed"
        )
    }
    if name == "tris" {
        return make_buffer(
            "Tris buffer", "Tris-H+ (protonated tris)", "Tris (tris(hydroxymethyl)aminomethane)",
            8.07, 7.07, 9.07,
            "Dissolve Tris base in water, titrate to pH with HCl. Temperature-sensitive: dpKa/dT = -0.028/C. Prepare at working temperature.",
            "Molecular biology: DNA/RNA electrophoresis (TAE, TBE, TBS). Protein purification. Histology. Caution: interferes with Bradford assay and some enzyme kinetics.",
            "Good NE et al. Biochemistry 5:467-477, 1966"
        )
    }
    if name == "bicarbonate" {
        return make_buffer(
            "Bicarbonate buffer", "CO2(aq) / H2CO3 (carbonic acid)", "HCO3- (bicarbonate)",
            6.35, 5.35, 7.35,
            "Equilibrate NaHCO3 solution with CO2 gas at controlled partial pressure. In vivo: CO2 from metabolism, HCO3- from renal reabsorption.",
            "THE primary extracellular buffer in blood. Open system (CO2 exhaled by lungs). Accounts for ~75% of blood buffering. Henderson-Hasselbalch with pKa 6.1 (apparent, includes CO2 hydration).",
            "Guyton 14th ed, Ch 31"
        )
    }
    if name == "HEPES" {
        return make_buffer(
            "HEPES buffer", "HEPES-H+ (protonated)", "HEPES (4-(2-hydroxyethyl)-1-piperazineethanesulfonic acid)",
            7.55, 6.55, 8.55,
            "Dissolve HEPES free acid in water, titrate to pH with NaOH. Good's buffer: zwitterionic, minimal metal binding.",
            "Cell culture (replaces bicarbonate in CO2-free incubators). Does not cross cell membranes. Minimal interference with biochemical reactions. Preferred over phosphate for calcium-sensitive experiments.",
            "Good NE et al. Biochemistry 5:467-477, 1966"
        )
    }
    if name == "citrate" {
        return make_buffer(
            "Citrate buffer", "Citric acid (H3C6H5O7)", "Sodium citrate (Na3C6H5O7)",
            6.40, 5.40, 7.40,
            "Mix citric acid monohydrate and trisodium citrate dihydrate. Triprotic: pKa1 3.13, pKa2 4.76, pKa3 6.40. Effective pH 3.0-6.2 using pKa1/pKa2 range too.",
            "Blood banking: citrate anticoagulant (chelates Ca2+). IHC antigen retrieval at pH 6.0. Food/beverage preservation (E330/E331). Pharmaceutical formulations.",
            "Lehninger 8th ed"
        )
    }
    if name == "MOPS" {
        return make_buffer(
            "MOPS buffer", "MOPS-H+ (protonated)", "MOPS (3-(N-morpholino)propanesulfonic acid)",
            7.20, 6.20, 8.20,
            "Dissolve MOPS in water, titrate with NaOH. Good's buffer: zwitterionic.",
            "RNA gel electrophoresis (MOPS-formaldehyde gels). Cell culture. Enzyme kinetics near neutral pH.",
            "Good NE et al. Biochemistry 5:467-477, 1966"
        )
    }
    if name == "PIPES" {
        return make_buffer(
            "PIPES buffer", "PIPES-H+ (protonated)", "PIPES (piperazine-N,N-bis(2-ethanesulfonic acid))",
            6.76, 5.76, 7.76,
            "Dissolve PIPES disodium salt in water. Limited solubility of free acid form.",
            "Electron microscopy fixation buffers. Cell biology. Does not bind most divalent cations.",
            "Good NE et al. Biochemistry 5:467-477, 1966"
        )
    }

    return make_buffer("", "", "", 0.0, 0.0, 0.0, "", "", "")
}

// ===============================================================
// BIOLOGICAL BUFFERS -- blood gas chemistry
// ===============================================================

// The blood bicarbonate buffer system
// pH = 6.1 + log10([HCO3-] / (0.03 * PCO2))
// where 6.1 is the apparent pKa (includes slow CO2 hydration equilibrium)
// and 0.03 is the solubility coefficient of CO2 in mEq/L per mmHg
// Cited: Guyton 14th ed, Ch 31

fn blood_buffer() -> BloodBufferState {
    return BloodBufferState {
        ph: 7.40,
        pco2_mmhg: 40.0,
        hco3_meq_l: 24.0,
        normal_ph_low: 7.35,
        normal_ph_high: 7.45,
        normal_pco2_low: 35.0,
        normal_pco2_high: 45.0,
        normal_hco3_low: 22.0,
        normal_hco3_high: 26.0,
        citation: "Guyton 14th ed, Ch 31"
    }
}

// Blood pH from PCO2 and HCO3- using Henderson-Hasselbalch:
// pH = 6.1 + log10([HCO3-] / (0.03 * PCO2))
// pKa(apparent) = 6.1, solubility coefficient alpha = 0.03 mEq/L/mmHg
fn blood_ph_from_pco2(pco2_mmhg: Float, hco3_meq_l: Float) -> Float {
    if pco2_mmhg <= 0.0 { return 0.0 }
    if hco3_meq_l <= 0.0 { return 0.0 }
    let dissolved_co2 = 0.03 * pco2_mmhg
    if dissolved_co2 <= 0.0 { return 0.0 }
    let ratio = hco3_meq_l / dissolved_co2
    return 6.1 + log10(ratio)
}

// Classify arterial blood gas results
// Determines primary acid-base disorder and compensation status
// Cited: Guyton 14th ed, Ch 31
fn classify_abg(ph: Float, pco2: Float, hco3: Float) -> ABGClassification {
    // Normal ranges:
    // pH: 7.35-7.45
    // pCO2: 35-45 mmHg
    // HCO3-: 22-26 mEq/L

    // Acidemia with high CO2: respiratory acidosis
    if ph < 7.35 {
        if pco2 > 45.0 {
            if hco3 > 26.0 {
                return ABGClassification {
                    primary_disorder: "respiratory acidosis",
                    ph_status: "acidemia",
                    respiratory_component: "hypoventilation (elevated PCO2)",
                    metabolic_component: "metabolic compensation (elevated HCO3-)",
                    compensation: "partial or complete metabolic compensation. Renal HCO3- retention.",
                    citation: "Guyton 14th ed, Ch 31"
                }
            }
            return ABGClassification {
                primary_disorder: "respiratory acidosis",
                ph_status: "acidemia",
                respiratory_component: "hypoventilation (elevated PCO2)",
                metabolic_component: "no metabolic compensation (normal HCO3-)",
                compensation: "uncompensated. Acute respiratory acidosis. Causes: COPD, opioid overdose, neuromuscular disease.",
                citation: "Guyton 14th ed, Ch 31"
            }
        }
        // Acidemia with low HCO3-: metabolic acidosis
        if hco3 < 22.0 {
            if pco2 < 35.0 {
                return ABGClassification {
                    primary_disorder: "metabolic acidosis",
                    ph_status: "acidemia",
                    respiratory_component: "respiratory compensation (decreased PCO2, hyperventilation)",
                    metabolic_component: "HCO3- deficit",
                    compensation: "partial or complete respiratory compensation. Kussmaul breathing.",
                    citation: "Guyton 14th ed, Ch 31"
                }
            }
            return ABGClassification {
                primary_disorder: "metabolic acidosis",
                ph_status: "acidemia",
                respiratory_component: "no respiratory compensation (normal PCO2)",
                metabolic_component: "HCO3- deficit",
                compensation: "uncompensated. Causes: DKA, lactic acidosis, diarrhea, renal tubular acidosis.",
                citation: "Guyton 14th ed, Ch 31"
            }
        }
        return ABGClassification {
            primary_disorder: "mixed acidosis",
            ph_status: "acidemia",
            respiratory_component: "evaluate PCO2 trend",
            metabolic_component: "evaluate HCO3- trend",
            compensation: "indeterminate. Requires clinical correlation.",
            citation: "Guyton 14th ed, Ch 31"
        }
    }

    // Alkalemia with low CO2: respiratory alkalosis
    if ph > 7.45 {
        if pco2 < 35.0 {
            if hco3 < 22.0 {
                return ABGClassification {
                    primary_disorder: "respiratory alkalosis",
                    ph_status: "alkalemia",
                    respiratory_component: "hyperventilation (decreased PCO2)",
                    metabolic_component: "metabolic compensation (decreased HCO3-)",
                    compensation: "partial or complete metabolic compensation. Renal HCO3- excretion.",
                    citation: "Guyton 14th ed, Ch 31"
                }
            }
            return ABGClassification {
                primary_disorder: "respiratory alkalosis",
                ph_status: "alkalemia",
                respiratory_component: "hyperventilation (decreased PCO2)",
                metabolic_component: "no metabolic compensation (normal HCO3-)",
                compensation: "uncompensated. Causes: anxiety, pain, PE, pregnancy, high altitude.",
                citation: "Guyton 14th ed, Ch 31"
            }
        }
        // Alkalemia with high HCO3-: metabolic alkalosis
        if hco3 > 26.0 {
            if pco2 > 45.0 {
                return ABGClassification {
                    primary_disorder: "metabolic alkalosis",
                    ph_status: "alkalemia",
                    respiratory_component: "respiratory compensation (elevated PCO2, hypoventilation)",
                    metabolic_component: "HCO3- excess",
                    compensation: "partial or complete respiratory compensation.",
                    citation: "Guyton 14th ed, Ch 31"
                }
            }
            return ABGClassification {
                primary_disorder: "metabolic alkalosis",
                ph_status: "alkalemia",
                respiratory_component: "no respiratory compensation (normal PCO2)",
                metabolic_component: "HCO3- excess",
                compensation: "uncompensated. Causes: vomiting, NG suction, diuretics, hyperaldosteronism.",
                citation: "Guyton 14th ed, Ch 31"
            }
        }
        return ABGClassification {
            primary_disorder: "mixed alkalosis",
            ph_status: "alkalemia",
            respiratory_component: "evaluate PCO2 trend",
            metabolic_component: "evaluate HCO3- trend",
            compensation: "indeterminate. Requires clinical correlation.",
            citation: "Guyton 14th ed, Ch 31"
        }
    }

    // Normal pH
    if pco2 > 45.0 {
        if hco3 > 26.0 {
            return ABGClassification {
                primary_disorder: "fully compensated respiratory acidosis",
                ph_status: "normal (compensated)",
                respiratory_component: "elevated PCO2",
                metabolic_component: "elevated HCO3- (renal compensation)",
                compensation: "full compensation. Chronic respiratory acidosis with renal adaptation.",
                citation: "Guyton 14th ed, Ch 31"
            }
        }
    }
    if pco2 < 35.0 {
        if hco3 < 22.0 {
            return ABGClassification {
                primary_disorder: "fully compensated respiratory alkalosis",
                ph_status: "normal (compensated)",
                respiratory_component: "decreased PCO2",
                metabolic_component: "decreased HCO3- (renal compensation)",
                compensation: "full compensation. Chronic respiratory alkalosis.",
                citation: "Guyton 14th ed, Ch 31"
            }
        }
    }
    if hco3 < 22.0 {
        if pco2 < 35.0 {
            return ABGClassification {
                primary_disorder: "fully compensated metabolic acidosis",
                ph_status: "normal (compensated)",
                respiratory_component: "decreased PCO2 (respiratory compensation)",
                metabolic_component: "decreased HCO3-",
                compensation: "full compensation.",
                citation: "Guyton 14th ed, Ch 31"
            }
        }
    }
    if hco3 > 26.0 {
        if pco2 > 45.0 {
            return ABGClassification {
                primary_disorder: "fully compensated metabolic alkalosis",
                ph_status: "normal (compensated)",
                respiratory_component: "elevated PCO2 (respiratory compensation)",
                metabolic_component: "elevated HCO3-",
                compensation: "full compensation.",
                citation: "Guyton 14th ed, Ch 31"
            }
        }
    }

    return ABGClassification {
        primary_disorder: "normal acid-base status",
        ph_status: "normal",
        respiratory_component: "normal PCO2",
        metabolic_component: "normal HCO3-",
        compensation: "no disorder detected. pH, PCO2, HCO3- all within normal limits.",
        citation: "Guyton 14th ed, Ch 31"
    }
}

// ===============================================================
// ANION GAP -- diagnostic tool for metabolic acidosis
// ===============================================================
// AG = [Na+] - ([Cl-] + [HCO3-]). Normal: 8-12 mEq/L.
// Elevated AG (MUDPILES): Methanol, Uremia, DKA, Propylene glycol,
// INH/Iron, Lactic acidosis, Ethylene glycol, Salicylates.

fn anion_gap(sodium: Float, chloride: Float, bicarbonate: Float) -> Float {
    return sodium - (chloride + bicarbonate)
}

fn classify_anion_gap(ag: Float) -> String {
    if ag < 8.0 { return "low anion gap. Consider: hypoalbuminemia, bromide ingestion, multiple myeloma (cationic paraprotein)." }
    if ag <= 12.0 { return "normal anion gap. If metabolic acidosis present: non-anion-gap (hyperchloremic). Causes: diarrhea, RTA, acetazolamide." }
    return "elevated anion gap. MUDPILES: Methanol, Uremia, DKA, Propylene glycol, INH/Iron, Lactic acidosis, Ethylene glycol, Salicylates."
}

// ===============================================================
// pH INDICATORS
// ===============================================================
// Transition ranges for common acid-base indicators.
// Cited: Zumdahl SS. Chemistry, 10th ed, 2018.

fn indicator(name: String) -> PHIndicatorInfo {
    if name == "phenolphthalein" { return make_indicator("Phenolphthalein", "colorless", "pink/magenta", 8.2, 10.0, "synthetic phthalein derivative", "Zumdahl 10th ed") }
    if name == "methyl_orange" { return make_indicator("Methyl orange", "red", "yellow", 3.1, 4.4, "synthetic azo dye", "Zumdahl 10th ed") }
    if name == "bromothymol_blue" { return make_indicator("Bromothymol blue", "yellow", "blue", 6.0, 7.6, "synthetic sulfonephthalein", "Zumdahl 10th ed") }
    if name == "litmus" { return make_indicator("Litmus", "red (acid)", "blue (base)", 4.5, 8.3, "natural lichen extract (Roccella spp.)", "Zumdahl 10th ed") }
    if name == "methyl_red" { return make_indicator("Methyl red", "red", "yellow", 4.4, 6.2, "synthetic azo dye", "Zumdahl 10th ed") }
    if name == "thymol_blue" { return make_indicator("Thymol blue (acid range)", "red", "yellow", 1.2, 2.8, "synthetic sulfonephthalein. Diprotic: second transition at 8.0-9.6 (yellow to blue).", "Zumdahl 10th ed") }
    if name == "thymol_blue_alkaline" { return make_indicator("Thymol blue (alkaline range)", "yellow", "blue", 8.0, 9.6, "synthetic sulfonephthalein. Second transition of diprotic indicator.", "Zumdahl 10th ed") }
    if name == "phenol_red" { return make_indicator("Phenol red", "yellow", "red", 6.8, 8.4, "synthetic sulfonephthalein. Used in cell culture media to monitor pH.", "Zumdahl 10th ed") }
    if name == "congo_red" { return make_indicator("Congo red", "blue", "red", 3.0, 5.0, "synthetic diazo dye. Also used for amyloid staining in pathology.", "Zumdahl 10th ed") }
    if name == "alizarin_yellow" { return make_indicator("Alizarin yellow R", "yellow", "red", 10.1, 12.0, "synthetic nitro dye. Useful for strongly basic titrations.", "Zumdahl 10th ed") }
    if name == "universal" { return make_indicator("Universal indicator", "red (pH ~1) through green (pH ~7) to violet (pH ~14)", "continuous spectrum", 1.0, 14.0, "mixture of methyl red, bromothymol blue, thymol blue, and phenolphthalein", "Zumdahl 10th ed") }

    return make_indicator("", "", "", 0.0, 0.0, "", "")
}

// ===============================================================
// QUICK REFERENCE -- counts and constants
// ===============================================================

fn bronsted_acid_count() -> Int {
    // Strong: 7 (HCl, HBr, HI, HNO3, H2SO4 x2, HClO4)
    // Weak organic: 6 (acetic, formic, benzoic, lactic, ascorbic, propionic)
    // Weak inorganic: 4 (HF, HNO2, HClO, boric)
    // Phenol: 1
    // Polyprotic citric: 3
    // Polyprotic carbonic: 2
    // Polyprotic phosphoric: 3
    // Polyprotic oxalic: 2
    // Amino acids: 7 (Asp, Glu, His, Cys, Tyr, Lys, Arg)
    // Water: 1
    return 36
}

fn bronsted_base_count() -> Int {
    return 16
}

fn buffer_system_count() -> Int {
    return 8
}

fn indicator_count() -> Int {
    return 11
}

fn water_kw() -> Float {
    // Kw = [H+][OH-] = 1.0e-14 at 25C
    return 0.00000000000001
}

fn water_ph() -> Float {
    // Pure water at 25C: pH = 7.0
    return 7.0
}

fn physiological_ph() -> Float {
    // Arterial blood: 7.40
    return 7.40
}

fn body_temperature_kelvin() -> Float {
    // Body temperature: 37C = 310.15K
    return 310.15
}
