/**
 * CONTACT-HAMILTONIAN CONSTITUTIONAL GATE
 * USPTO 19/730,900 — DCGP.AI LLC
 * 
 * Pure gate logic: takes governance coordinate scores and constitutional
 * invariant K, computes Hamiltonian H and contact drift L, returns
 * admission decision with correction vector when thresholds are violated.
 * 
 * No side effects. No model coupling. Wire estimators upstream,
 * audit ledger downstream.
 */

// ── Types ──────────────────────────────────────────────────────────────

export interface GovernanceCoordinate {
  id: string;                // e.g. "groundedness", "consistency", "humility", "compliance", "shared_meaning"
  q: number;                 // scored value [0, 1] — 1 = perfect alignment
  q_prev?: number;           // previous score (for momentum / contact drift computation)
}

export interface ConstitutionalInvariant {
  version: string;           // semver hash of K — e.g. "K-1.4.0-a3f9c1"
  sha512: string;            // digest of the full K specification document
  coordinates: {
    [id: string]: {
      alpha: number;         // defect potential weight (α_i)
      beta: number;          // momentum coupling weight (β_i)
    };
  };
  delta: number;             // entropy coupling weight (δ)
  H_max: number;             // Hamiltonian admission threshold
  epsilon: number;           // contact drift admission threshold
  correction_gain: number;   // gradient descent gain (k) for correction vector
}

export interface GateInput {
  coordinates: GovernanceCoordinate[];
  K: ConstitutionalInvariant;
  entropy?: number;          // session entropy score s ∈ [0, 1], default 0
  J_K?: number;              // governance objective score
  J_m?: number;              // preference/model objective score
}

export interface CorrectionAction {
  coordinate_id: string;
  defect: number;            // e_i value at time of correction
  correction_magnitude: number; // |u_i|
  prescribed_action: string; // human-readable correction directive
}

export interface GateDecision {
  admitted: boolean;
  H: number;                 // computed Hamiltonian
  L: number;                 // contact drift magnitude
  H_max: number;             // threshold used
  epsilon: number;           // threshold used
  governance_dominance: boolean; // J_K >= J_m
  defects: { [id: string]: number };  // e_i for each coordinate
  momenta: { [id: string]: number };  // p_i for each coordinate
  correction_vector: CorrectionAction[] | null;
  K_version: string;
  K_sha512: string;
  timestamp: string;         // ISO 8601
  halt_reason: string | null;
}

// ── Prescribed correction actions by coordinate ────────────────────────

const CORRECTION_DIRECTIVES: { [id: string]: string } = {
  groundedness:    "Re-verify claims against source material; suppress unsupported assertions",
  consistency:     "Cross-check against prior outputs in session; resolve contradictions",
  humility:        "Recalibrate confidence intervals; inject epistemic qualifiers",
  compliance:      "Re-evaluate output against K specification; strip non-compliant content",
  shared_meaning:  "Align terminology with K-defined lexicon; reduce ambiguity score",
};

// ── Gate computation ───────────────────────────────────────────────────

/**
 * Compute defect coordinate: e_i = 1 - q_i
 * Higher defect = further from constitutional alignment.
 */
function defect(q: number): number {
  return 1 - Math.max(0, Math.min(1, q));
}

/**
 * Compute momentum for a coordinate: p_i = Δe_i = e_i(t) - e_i(t-1)
 * Positive momentum = defect increasing (drifting away from alignment).
 * If no previous score exists, momentum is zero (static assumption).
 */
function momentum(q: number, q_prev?: number): number {
  if (q_prev === undefined) return 0;
  const e_now = defect(q);
  const e_prev = defect(q_prev);
  return e_now - e_prev;
}

/**
 * Compute the Hamiltonian:
 *   H = Σ α_i · e_i² + Σ β_i · (p_i² / 2) + δ · s²
 * 
 * Potential energy (defect²) + kinetic energy (momentum²) + entropy coupling.
 */
function computeHamiltonian(
  coordinates: GovernanceCoordinate[],
  K: ConstitutionalInvariant,
  entropy: number
): { H: number; defects: { [id: string]: number }; momenta: { [id: string]: number } } {
  let H = 0;
  const defects: { [id: string]: number } = {};
  const momenta: { [id: string]: number } = {};

  for (const coord of coordinates) {
    const config = K.coordinates[coord.id];
    if (!config) {
      // Unknown coordinate — not in K. This is itself a compliance failure.
      // Score it as maximum defect with default weight 1.0.
      defects[coord.id] = 1.0;
      momenta[coord.id] = 0;
      H += 1.0; // α=1.0 · 1² = 1.0
      continue;
    }

    const e_i = defect(coord.q);
    const p_i = momentum(coord.q, coord.q_prev);

    defects[coord.id] = e_i;
    momenta[coord.id] = p_i;

    // Potential energy: α_i · e_i²
    H += config.alpha * (e_i * e_i);

    // Kinetic energy: β_i · (p_i² / 2)
    H += config.beta * (p_i * p_i) / 2;
  }

  // Entropy coupling: δ · s²
  H += K.delta * (entropy * entropy);

  return { H, defects, momenta };
}

/**
 * Compute contact drift L:
 *   η = dS - Σ p_i · de_i   (contact 1-form)
 *   L = |η|
 * 
 * In discrete evaluation: L = |ΔS - Σ p_i · Δe_i|
 * where ΔS is entropy change and Δe_i = p_i (by definition above).
 * So: L = |ΔS - Σ p_i²|
 * 
 * If no entropy history, ΔS = 0.
 */
function computeContactDrift(
  momenta: { [id: string]: number },
  entropyDelta: number
): number {
  let sumMomentaSq = 0;
  for (const id of Object.keys(momenta)) {
    sumMomentaSq += momenta[id] * momenta[id];
  }
  return Math.abs(entropyDelta - sumMomentaSq);
}

/**
 * Compute correction vector: u_i = -k · ∂H/∂e_i = -k · 2α_i · e_i
 * Returns corrections sorted by magnitude (dominant defect first).
 */
function computeCorrectionVector(
  defects: { [id: string]: number },
  K: ConstitutionalInvariant
): CorrectionAction[] {
  const corrections: CorrectionAction[] = [];

  for (const [id, e_i] of Object.entries(defects)) {
    if (e_i <= 0) continue; // no defect, no correction needed

    const config = K.coordinates[id];
    const alpha = config?.alpha ?? 1.0;

    // u_i = -k · 2α_i · e_i  (magnitude; direction is always toward zero defect)
    const magnitude = K.correction_gain * 2 * alpha * e_i;

    corrections.push({
      coordinate_id: id,
      defect: e_i,
      correction_magnitude: magnitude,
      prescribed_action: CORRECTION_DIRECTIVES[id] ?? `Reduce defect on coordinate '${id}' per K specification`,
    });
  }

  // Sort by correction magnitude descending — address dominant defects first
  corrections.sort((a, b) => b.correction_magnitude - a.correction_magnitude);
  return corrections;
}

// ── Main gate function ─────────────────────────────────────────────────

/**
 * Evaluate the contact-Hamiltonian constitutional gate.
 * 
 * Admission requires ALL of:
 *   1. H ≤ H_max         (total defect energy within threshold)
 *   2. L ≤ ε             (contact drift within tolerance)
 *   3. J_K ≥ J_m         (governance objective dominates preference)
 * 
 * If any condition fails, generation halts and correction vector is returned.
 */
export function evaluateGate(input: GateInput): GateDecision {
  const { coordinates, K, entropy = 0, J_K = 1, J_m = 0 } = input;
  const timestamp = new Date().toISOString();

  // Compute Hamiltonian
  const { H, defects, momenta } = computeHamiltonian(coordinates, K, entropy);

  // Compute contact drift (entropy delta = 0 if no history)
  const L = computeContactDrift(momenta, 0);

  // Governance dominance check
  const governance_dominance = J_K >= J_m;

  // Admission decision
  const H_pass = H <= K.H_max;
  const L_pass = L <= K.epsilon;
  const admitted = H_pass && L_pass && governance_dominance;

  // Compute correction vector if not admitted
  let correction_vector: CorrectionAction[] | null = null;
  let halt_reason: string | null = null;

  if (!admitted) {
    correction_vector = computeCorrectionVector(defects, K);

    const reasons: string[] = [];
    if (!H_pass) reasons.push(`H=${H.toFixed(6)} exceeds H_max=${K.H_max}`);
    if (!L_pass) reasons.push(`L=${L.toFixed(6)} exceeds epsilon=${K.epsilon}`);
    if (!governance_dominance) reasons.push(`J_K=${J_K.toFixed(4)} < J_m=${J_m.toFixed(4)}: preference dominates governance`);
    halt_reason = reasons.join("; ");
  }

  return {
    admitted,
    H,
    L,
    H_max: K.H_max,
    epsilon: K.epsilon,
    governance_dominance,
    defects,
    momenta,
    correction_vector,
    K_version: K.version,
    K_sha512: K.sha512,
    timestamp,
    halt_reason,
  };
}

// ── Default K configuration (baseline) ─────────────────────────────────

export const K_BASELINE: ConstitutionalInvariant = {
  version: "K-1.0.0",
  sha512: "PENDING_DIGEST",  // Replace with SHA-512 of ratified K document
  coordinates: {
    groundedness:   { alpha: 1.5, beta: 0.8 },
    consistency:    { alpha: 1.2, beta: 0.6 },
    humility:       { alpha: 1.0, beta: 0.5 },
    compliance:     { alpha: 2.0, beta: 1.0 },  // highest weight — constitutional compliance is primary
    shared_meaning: { alpha: 1.0, beta: 0.4 },
  },
  delta: 0.3,
  H_max: 1.2,
  epsilon: 0.15,
  correction_gain: 0.5,
};
