// energy.sy -- ATP/ADP/AMP Metabolic Energy System
// Three-pool conservation: ATP + ADP + AMP = 1.0 always.
// AMPK gate uses H-H rate function, NOT sigmoid.
//
// References:
//   Attwell & Laughlin (2001) J Cereb Blood Flow Metab
//   Hardie (2007) Annu Rev Pharmacol Toxicol
//   Harris et al. (2012) Neuron
//
// Aislinn McCubbins, April 2026

temporal struct ATPCycling {
    state atp: Float = 1.0,
    state adp: Float = 0.0,
    state amp: Float = 0.0,

    const k_atp_cost: Float = 1.5,
    const k_mito_recovery: Float = 0.04,
    const k_amp_degradation: Float = 0.05,
    const k_amp_recovery: Float = 0.008,
}

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

        // Mitochondrial recovery: ADP -> ATP
        let mito = self.k_mito_recovery * self.adp * dt_s
        self.atp = self.atp + mito
        self.adp = self.adp - mito

        // Emergency degradation: ADP -> AMP (when ADP > 0.3)
        let excess = self.adp - 0.3
        if excess < 0.0 { excess = 0.0 }
        let degrade = self.k_amp_degradation * excess * dt_s
        self.adp = self.adp - degrade
        self.amp = self.amp + degrade

        // Slow recovery: AMP -> ADP (adenylate kinase)
        let recov = self.k_amp_recovery * self.amp * dt_s
        self.amp = self.amp - recov
        self.adp = self.adp + recov

        // Conservation law
        let total = self.atp + self.adp + self.amp + 0.0000001
        self.atp = self.atp / total
        self.adp = self.adp / total
        self.amp = self.amp / total
    }
}

impl ATPCycling {
    fn fire(&mut self, intensity: Float) {
        let cost = intensity * self.k_atp_cost
        if cost > self.atp { cost = self.atp }
        self.atp = self.atp - cost
        self.adp = self.adp + cost
    }

    fn ampk_gate(&self) -> Float {
        // H-H rate function, NOT sigmoid
        let ratio = self.atp / (self.amp + 0.05)
        let alpha = exp((ratio - 1.0))
        let beta = exp((1.0 - ratio))
        alpha / (alpha + beta + 0.00000001)
    }

    fn is_depleted(&self) -> Bool {
        self.ampk_gate() < 0.5
    }

    fn reset(&mut self) {
        self.atp = 1.0
        self.adp = 0.0
        self.amp = 0.0
    }
}
