// conductance_head.sy -- Each Head IS a Transformer
// Not a generic attention mechanism. A specific biochemical system.
// Dopamine is not serotonin. Each one has its own:
//   - Synthesis pathway (enzymes, cofactors, rate-limiting steps)
//   - Degradation pathway (MAO, COMT, AChE, reuptake)
//   - Half-life (published, head-specific)
//   - Receptor threshold (Kd, the mass gap)
//   - Tonic drive (baseline, the pilot light)
//   - Vesicle pool (quantal release capacity)
//
// One struct. 34 instances. The code is identical.
// The biology makes each one unique.
//
// Marjorie McCubbins, BSc Biochemistry and Molecular Biology
// April 2026
//
// Patent Pending: 63/939,190 & 63/962,385 & 63/988,485

// ═══════════════════════════════════════════════════════════
// THE CONDUCTANCE HEAD: One NT System as a Transformer
// ═══════════════════════════════════════════════════════════
//
// Standard transformer head:
//   Q, K, V projections → scaled dot product → softmax → output
//
// Conductance head:
//   Sense → Synthesize → Release → Bind → Gate → Reuptake → Degrade
//   Every step is a native function call.
//   The "attention weight" is the H-H gate value.
//   The "output" is the conductance: how much this NT system
//   influences downstream processing.

temporal struct ConductanceHead {
    // ── Identity: what biochemical system am I? ──
    const name: String,
    const tier: Int,            // 0=amino, 1=precursor, 2=NT, 3=region
    const head_index: Int,      // position in the 34-head cascade

    // ── State: my current chemistry ──
    state concentration: Float,  // current level (decays toward baseline)
    state gate_value: Float,     // H-H gate output [0,1] = "attention weight"
    state vesicle_pool: Float,   // available for release (depletes, recovers)
    state receptor_sensitivity: Float,  // desensitizes with prolonged exposure
    state reuptake_rate: Float,  // how fast I'm cleared from the cleft

    // ── Metabolic ──
    state atp_consumed: Float = 0.0,  // energy cost of this head's activity
    state synthesis_rate: Float,      // how fast I'm being produced

    // ── Plasticity (learnable) ──
    state w_alpha: Float,        // H-H gate weight (alpha rate)
    state b_alpha: Float,        // H-H gate bias (alpha)
    state w_beta: Float,         // H-H gate weight (beta rate)
    state b_beta: Float,         // H-H gate bias (beta)

    // ── History ──
    state activation_count: Int = 0,
    state peak_concentration: Float = 0.0,
    state time_above_threshold: Float = 0.0,
    state auc_accumulated: Float = 0.0,
}

impl Evolve for ConductanceHead {
    fn evolve(&mut self, dt: Duration) {
        let dt_s = dt.seconds()

        // Decay toward baseline (homeostasis)
        let baseline = tonic_drive(self.name)
        let hl = bio_half_life(self.name)
        self.concentration = half_life_to_baseline(
            self.concentration, hl, dt_s, baseline
        )

        // Vesicle recovery (Tsodyks-Markram dynamics)
        // Recovery rate: ~8% of depleted pool per time unit
        self.vesicle_pool = self.vesicle_pool + 0.08 * (1.0 - self.vesicle_pool) * dt_s

        // Receptor resensitization (slow)
        // Receptors recover from desensitization when concentration drops
        if self.concentration < baseline * 1.5 {
            self.receptor_sensitivity = self.receptor_sensitivity + 0.02 * (1.0 - self.receptor_sensitivity) * dt_s
        }

        // AUC tracking (the A1C of this head)
        self.auc_accumulated = auc(self.auc_accumulated, self.concentration, dt_s)

        // Update gate (the "attention weight")
        self.gate_value = hh_gate(
            self.concentration,
            self.w_alpha, self.b_alpha,
            self.w_beta, self.b_beta
        )
    }
}

impl ConductanceHead {
    fn new(name: String, tier: Int, index: Int) -> ConductanceHead {
        let baseline = tonic_drive(name)
        let tonic = baseline
        if tonic < 0.01 { tonic = 0.01 }
        if tonic > 0.99 { tonic = 0.99 }
        let diff = ln(tonic / (1.0 - tonic))

        ConductanceHead {
            name: name,
            tier: tier,
            head_index: index,
            concentration: baseline,
            gate_value: hh_resting("n_inf"),
            vesicle_pool: 1.0,
            receptor_sensitivity: 1.0,
            reuptake_rate: 1.0,
            atp_consumed: 0.0,
            synthesis_rate: tonic,
            w_alpha: 0.0,
            b_alpha: diff * 0.5,
            w_beta: 0.0,
            b_beta: diff * -0.5,
            activation_count: 0,
            peak_concentration: baseline,
            time_above_threshold: 0.0,
            auc_accumulated: 0.0,
        }
    }

    // ═══════════════════════════════════════════════════════
    // THE FORWARD PASS: One head. One inference step.
    // ═══════════════════════════════════════════════════════

    fn forward(&mut self, stimulus: Float, context_situation: String, trust: Float, scars: Float, dt: Float) -> Float {

        // ┌─────────────────────────────────────────┐
        // │  STEP 1: CONTEXT CONFIGURES PHYSICS     │
        // └─────────────────────────────────────────┘
        // Trust changes MY half-life. Context changes MY release mask.
        let my_half_life = context_half_life(self.name, context_situation, trust, scars)

        // ┌─────────────────────────────────────────┐
        // │  STEP 2: SYNTHESIS                      │
        // │  Am I being produced?                   │
        // └─────────────────────────────────────────┘
        // Tonic synthesis: the pilot light. Always producing a little.
        let tonic_synthesis = tonic_drive(self.name) * 0.01 * dt
        self.concentration = self.concentration + tonic_synthesis

        // ATP cost of synthesis
        self.atp_consumed = self.atp_consumed + tonic_synthesis * 0.001

        // ┌─────────────────────────────────────────┐
        // │  STEP 3: STIMULUS → RELEASE             │
        // │  Ca2+-dependent vesicle exocytosis       │
        // └─────────────────────────────────────────┘
        // The stimulus triggers vesicle fusion. More stimulus = more release.
        // But can't release from an empty pool.
        let released = vesicle_release(self.vesicle_pool, stimulus, 0.5)

        // Deplete vesicle pool proportionally
        self.vesicle_pool = self.vesicle_pool - released * 0.25
        if self.vesicle_pool < 0.0 { self.vesicle_pool = 0.0 }

        // Add released NT to synaptic concentration
        self.concentration = self.concentration + released

        // ┌─────────────────────────────────────────┐
        // │  STEP 4: RECEPTOR BINDING               │
        // │  Does concentration exceed Kd?           │
        // │  This IS the mass gap.                   │
        // └─────────────────────────────────────────┘
        let my_kd = nt_range(self.name, "kd")
        let normalized_conc = self.concentration / (self.concentration + my_kd / 1000.0)
        // Receptor sensitivity modulates binding
        let effective_binding = normalized_conc * self.receptor_sensitivity

        // ┌─────────────────────────────────────────┐
        // │  STEP 5: H-H GATE                       │
        // │  The "attention weight"                  │
        // │  Not softmax. Not sigmoid.               │
        // │  Hodgkin-Huxley 1952.                    │
        // └─────────────────────────────────────────┘
        self.gate_value = hh_gate(
            effective_binding,
            self.w_alpha, self.b_alpha,
            self.w_beta, self.b_beta
        )

        // Track activation
        if self.gate_value > 0.5 {
            self.activation_count = self.activation_count + 1
            let threshold = nt_range(self.name, "baseline") * 2.0
            if self.concentration > threshold {
                self.time_above_threshold = self.time_above_threshold + dt
            }
        }

        // Track peak
        if self.concentration > self.peak_concentration {
            self.peak_concentration = self.concentration
        }

        // ┌─────────────────────────────────────────┐
        // │  STEP 6: REUPTAKE + DEGRADATION         │
        // │  Clear the cleft. Return to baseline.    │
        // └─────────────────────────────────────────┘
        // Decay toward baseline using context-modified half-life
        self.concentration = half_life_to_baseline(
            self.concentration, my_half_life, dt, tonic_drive(self.name)
        )

        // Receptor desensitization (prolonged exposure reduces sensitivity)
        if effective_binding > 0.7 {
            self.receptor_sensitivity = self.receptor_sensitivity * 0.995
            if self.receptor_sensitivity < 0.1 {
                self.receptor_sensitivity = 0.1
            }
        }

        // ┌─────────────────────────────────────────┐
        // │  STEP 7: OUTPUT                         │
        // │  The gate value IS the attention weight.  │
        // └─────────────────────────────────────────┘
        self.gate_value
    }

    // ═══════════════════════════════════════════════════════
    // DIAGNOSTICS: Trace this head's biochemistry
    // ═══════════════════════════════════════════════════════

    fn diagnose(&self) -> String {
        let pathway = nt_synthesis_pathway(self.name)
        let degradation = nt_degradation(self.name)
        let baseline = tonic_drive(self.name)
        let deviation = self.concentration - baseline

        let status = if deviation > 0.2 { "ELEVATED" }
            else if deviation < -0.1 { "DEPLETED" }
            else { "NORMAL" }

        self.name + "|conc:" + self.concentration
            + "|baseline:" + baseline
            + "|deviation:" + deviation
            + "|status:" + status
            + "|gate:" + self.gate_value
            + "|vesicles:" + self.vesicle_pool
            + "|sensitivity:" + self.receptor_sensitivity
            + "|auc:" + self.auc_accumulated
            + "|activations:" + self.activation_count
    }

    fn trace(&self) -> String {
        // Full biochemical pathway trace
        let pathway = nt_synthesis_pathway(self.name)
        let degradation = nt_degradation(self.name)
        let breaks = trace_break(self.name)
        pathway + "|DEGRADATION:" + degradation + "|FAILURE_POINTS:" + breaks
    }
}

// ═══════════════════════════════════════════════════════════
// THE CASCADE: 34 Heads Wired Together
// ═══════════════════════════════════════════════════════════
// Tier 0 (amino acids) gates Tier 1 (precursors)
// Tier 1 gates Tier 2 (neurotransmitters)
// Tier 2 gates Tier 3 (brain regions)
// Each tier's output modulates the next tier's input.

fn build_cascade() -> Vec<ConductanceHead> {
    let heads = []

    // TIER 0: Amino Acid Substrates (8 heads)
    heads = heads + [ConductanceHead::new("phenylalanine", 0, 0)]
    heads = heads + [ConductanceHead::new("glycine", 0, 1)]
    heads = heads + [ConductanceHead::new("aspartate", 0, 2)]
    heads = heads + [ConductanceHead::new("histidine", 0, 3)]
    heads = heads + [ConductanceHead::new("arginine", 0, 4)]
    heads = heads + [ConductanceHead::new("serine", 0, 5)]
    heads = heads + [ConductanceHead::new("cysteine", 0, 6)]
    heads = heads + [ConductanceHead::new("methionine", 0, 7)]

    // TIER 1: Biosynthetic Precursors (6 heads)
    heads = heads + [ConductanceHead::new("tyrosine", 1, 8)]
    heads = heads + [ConductanceHead::new("tryptophan", 1, 9)]
    heads = heads + [ConductanceHead::new("glutamate", 1, 10)]
    heads = heads + [ConductanceHead::new("choline", 1, 11)]
    heads = heads + [ConductanceHead::new("cholesterol", 1, 12)]
    heads = heads + [ConductanceHead::new("pomc", 1, 13)]

    // TIER 2: Neurotransmitters (8 heads)
    heads = heads + [ConductanceHead::new("dopamine", 2, 14)]
    heads = heads + [ConductanceHead::new("norepinephrine", 2, 15)]
    heads = heads + [ConductanceHead::new("serotonin", 2, 16)]
    heads = heads + [ConductanceHead::new("gaba", 2, 17)]
    heads = heads + [ConductanceHead::new("oxytocin", 2, 18)]
    heads = heads + [ConductanceHead::new("cortisol", 2, 19)]
    heads = heads + [ConductanceHead::new("endorphin", 2, 20)]
    heads = heads + [ConductanceHead::new("acetylcholine", 2, 21)]

    // TIER 3: Brain Regions (12 heads)
    heads = heads + [ConductanceHead::new("brocas_area", 3, 22)]
    heads = heads + [ConductanceHead::new("wernickes_area", 3, 23)]
    heads = heads + [ConductanceHead::new("prefrontal_cortex", 3, 24)]
    heads = heads + [ConductanceHead::new("amygdala", 3, 25)]
    heads = heads + [ConductanceHead::new("hippocampus", 3, 26)]
    heads = heads + [ConductanceHead::new("motor_cortex", 3, 27)]
    heads = heads + [ConductanceHead::new("angular_gyrus", 3, 28)]
    heads = heads + [ConductanceHead::new("anterior_cingulate", 3, 29)]
    heads = heads + [ConductanceHead::new("insula", 3, 30)]
    heads = heads + [ConductanceHead::new("basal_ganglia", 3, 31)]
    heads = heads + [ConductanceHead::new("cerebellum", 3, 32)]
    heads = heads + [ConductanceHead::new("temporal_cortex", 3, 33)]

    heads
}

fn cascade_forward(heads: Vec<ConductanceHead>, stimulus: Float, situation: String, trust: Float, scars: Float, dt: Float) -> Vec<Float> {
    let gates = []

    // Tier 0: Amino acids respond to raw stimulus
    for i in 0..8 {
        let gate = heads[i].forward(stimulus, situation, trust, scars, dt)
        gates = gates + [gate]
    }

    // Tier 1: Precursors gated by amino acid availability
    // Tyrosine needs phenylalanine. Tryptophan is dietary. etc.
    let tier0_avg = 0.0
    for i in 0..8 { tier0_avg = tier0_avg + gates[i] }
    tier0_avg = tier0_avg / 8.0

    for i in 8..14 {
        let gated_stimulus = stimulus * tier0_avg
        let gate = heads[i].forward(gated_stimulus, situation, trust, scars, dt)
        gates = gates + [gate]
    }

    // Tier 2: NTs gated by precursor availability
    // Dopamine needs tyrosine. Serotonin needs tryptophan. etc.
    let tier1_avg = 0.0
    for i in 8..14 { tier1_avg = tier1_avg + gates[i] }
    tier1_avg = tier1_avg / 6.0

    for i in 14..22 {
        let gated_stimulus = stimulus * tier1_avg
        let gate = heads[i].forward(gated_stimulus, situation, trust, scars, dt)
        gates = gates + [gate]
    }

    // Tier 2 coupling: antagonistic pairs
    let pair_ds = antagonistic_pair(heads[14].concentration, heads[16].concentration, 0.1, dt)
    let pair_co = antagonistic_pair(heads[19].concentration, heads[18].concentration, 0.1, dt)
    let pair_ng = antagonistic_pair(heads[15].concentration, heads[17].concentration, 0.1, dt)

    // Tier 3: Brain regions gated by NT cocktail
    // Each region is activated by specific NTs
    let tier2_avg = 0.0
    for i in 14..22 { tier2_avg = tier2_avg + gates[i] }
    tier2_avg = tier2_avg / 8.0

    for i in 22..34 {
        let gated_stimulus = stimulus * tier2_avg
        let gate = heads[i].forward(gated_stimulus, situation, trust, scars, dt)
        gates = gates + [gate]
    }

    gates
}

// ═══════════════════════════════════════════════════════════
// DIAGNOSTIC: Full cascade health check
// ═══════════════════════════════════════════════════════════

fn cascade_diagnose(heads: Vec<ConductanceHead>) -> String {
    let report = "CASCADE_HEALTH:\n"
    for i in 0..34 {
        report = report + "  " + heads[i].diagnose() + "\n"
    }
    report
}
