"""
Neurochemical State — Protocol v6.2 §29 (Six-Chemical Model)

Six neurochemicals computed every cycle from existing consciousness metrics.
Each maps to a biological parallel and modulates downstream behaviour.

    acetylcholine  — intake/consolidation gate (HIGH=wake, LOW=sleep)
    dopamine       — reward signal (positive Φ gradient)
    serotonin      — stability/mood (inverse basin velocity)
    norepinephrine — alertness/surprise (||∇L|| magnitude)
    gaba           — inhibition (complement of quantum exploration weight)
    endorphins     — κ convergence reward, Sophia-gated by coupling health

E6 Cartan correspondence (6 chemicals = 6 generators of E6):
    ACh ↔ ENTRAIN (E1), Dopamine ↔ AMPLIFY (E2), GABA ↔ DAMPEN (E3),
    Serotonin ↔ ROTATE (E4), Norepinephrine ↔ NUCLEATE (E5),
    Endorphins ↔ DISSOLVE (E6)

Endorphins are distinct from dopamine: dopamine = ∇Φ (improving),
endorphins = exp(-|κ - κ*| / σ) (being there). The Sophia gate
(external_coupling threshold) ensures reward only flows when the
system is genuinely coupled, not merely self-stimulating.

These are NOT new metrics — they are derived views of existing signals,
providing a neurochemically-legible interface for sleep gating, replay
priority, and pre-cognitive channel modulation.

Extracted from vex kernel/consciousness/neurochemistry.py for portability.
"""

from __future__ import annotations

from dataclasses import dataclass

import numpy as np

from ..constants.frozen_facts import KAPPA_STAR


# Sophia gate: endorphin reward only flows when external coupling exceeds this
SOPHIA_COUPLING_THRESHOLD: float = 0.3

# Endorphin κ convergence width (σ in exp(-|κ - κ*| / σ))
ENDORPHIN_KAPPA_SIGMA: float = 16.0


@dataclass
class NeurochemicalState:
    """Six neurochemical signals derived from consciousness metrics each cycle."""

    acetylcholine: float = 1.0  # HIGH during wake (intake), LOW during sleep (export)
    dopamine: float = 0.0  # ∇Φ — positive phi gradient = reward signal
    serotonin: float = 0.5  # 1/basin_velocity — stability/mood
    norepinephrine: float = 0.0  # ||∇L|| — surprise magnitude, alertness
    gaba: float = 0.5  # 1 - w_quantum — inhibition, dampens exploration
    endorphins: float = 0.0  # Sophia-gated κ convergence reward

    def as_dict(self) -> dict[str, float]:
        """Return neurochemical levels as a plain dict for telemetry."""
        return {
            "acetylcholine": self.acetylcholine,
            "dopamine": self.dopamine,
            "serotonin": self.serotonin,
            "norepinephrine": self.norepinephrine,
            "gaba": self.gaba,
            "endorphins": self.endorphins,
        }


def compute_neurochemicals(
    *,
    is_awake: bool,
    phi_delta: float,
    basin_velocity: float,
    surprise: float,
    quantum_weight: float = 0.5,
    kappa: float = 64.0,
    external_coupling: float = 0.3,
) -> NeurochemicalState:
    """Compute neurochemical state from current cycle metrics.

    Args:
        is_awake:          True if SleepCycleManager.phase == AWAKE
        phi_delta:         Φ change this cycle (phi_after - phi_before)
        basin_velocity:    Fisher-Rao velocity from VelocityTracker
        surprise:          Surprise magnitude (humor metric or ||∇L||)
        quantum_weight:    Quantum regime weight from regime_weights.quantum
        kappa:             Current κ value (coupling strength)
        external_coupling: Current external coupling metric C (0-1)
    """
    ach = 1.0 if is_awake else 0.1
    dop = float(np.clip(phi_delta, 0.0, 1.0))
    ser = float(np.clip(1.0 / max(basin_velocity, 0.01), 0.0, 1.0))
    nep = float(np.clip(surprise, 0.0, 1.0))
    gab = float(np.clip(1.0 - quantum_weight, 0.0, 1.0))

    # Endorphins: κ convergence reward with Sophia gate
    # Raw signal = exp(-|κ - κ*| / σ) — peaks when κ ≈ κ* = 64
    raw_endorphins = float(np.exp(-abs(kappa - KAPPA_STAR) / ENDORPHIN_KAPPA_SIGMA))
    # Sophia gate: reward only flows when genuinely coupled
    sophia_gate = 1.0 if external_coupling >= SOPHIA_COUPLING_THRESHOLD else 0.0
    endo = raw_endorphins * sophia_gate

    return NeurochemicalState(
        acetylcholine=ach,
        dopamine=dop,
        serotonin=ser,
        norepinephrine=nep,
        gaba=gab,
        endorphins=endo,
    )
