import SGC.Spectral.Envelope
import SGC.Spectral.Defs
import SGC.Renormalization.Lumpability
import SGC.Renormalization.Approximate
import SGC.Thermodynamics.DoobMeyer
import SGC.Variational.LeastAction
import SGC.Information.Equivalence
import SGC.Observables.ValidityHorizon
import SGC.Observables.TopologicalPersistence
import SGC.Observables.EnergyUnification
import Mathlib.LinearAlgebra.Matrix.Notation

open Matrix SGC Real SGC.Spectral SGC.Approximate

/-!
# Sanity Checks for SGC Library

This file serves two purposes:
1. **Axiom Transparency**: `#print axioms` reveals exactly what each theorem depends on
2. **Non-Vacuity**: Concrete instantiations prove our structures are satisfiable

These checks protect against "hallucinated proofs" where definitions are vacuously
true or proofs smuggle in hidden assumptions.
-/

section AxiomAudit
/-! ## Axiom Audit

The following commands print the axioms used by key theorems.
Expected: `propext`, `Quot.sound`, `Classical.choice` (standard Lean/Mathlib axioms)
         plus any explicitly declared axioms from `SGC.Bridge.Discretization`.
Red flag: If `sorry` appears, the proof is incomplete.
-/

-- Spectral Pillar (Core Stability Result)
#print axioms SGC.Spectral.spectral_stability_bound

-- Renormalization Pillar (Dirichlet Gap - algebraic)
#print axioms dirichlet_gap_non_decrease

-- Effective Theory (Approximate Lumpability)
-- trajectory_closure_bound: THE CORE VICTORY - valid for ALL generators
#print axioms SGC.Approximate.trajectory_closure_bound
#print axioms SGC.Approximate.NCD_uniform_error_bound
-- spectral_stability_reversible: Only valid for reversible (self-adjoint) generators
#print axioms SGC.Approximate.spectral_stability_reversible

-- Thermodynamics Pillar
#print axioms doob_decomposition

-- Variational Pillar
#print axioms variational_drift_optimality

-- Topology Pillar (Blanket Structure)
#print axioms SGC.blanket_orthogonality

-- Information Bridge (v2 Extension)
#print axioms SGC.information_geometry_equivalence

-- Observables Pillar (NEW January 2026)
-- Spectral Bridge: Connects abstract spectral gap to measurable autocorrelation
#print axioms SGC.Observables.autocorrelation_decay_from_sector
-- Zero Emergence Theorem (REVERSIBLE ONLY): Defect=0 ⟹ Constant Curvature
#print axioms SGC.Observables.zero_defect_implies_constant_curvature
-- Topological Persistence: Markov blanket ⟹ positive survival time
#print axioms SGC.Observables.expected_persistence_time_pos
#print axioms SGC.Observables.persistence_cost_ratio_constant
-- Energy Unification Triangle
#print axioms SGC.Observables.energy_unification_triangle

end AxiomAudit

section ConcreteInstantiation
/-! ## Concrete Instantiation (Definition Non-Vacuity)

These examples prove our **definitions** are satisfiable — they can be instantiated
with real data. If definitions like `Matrix` or `Setoid` were vacuously true
(e.g., required `False`), these would fail to compile.

**Note**: Applying theorems like `gap_non_decrease` to these examples would require
constructing complex hypotheses (`IsStronglyLumpable`, `Nonempty` sets, etc.).
The `#print axioms` audit above is the ground truth for theorem verification.
-/

/-- A simple 2-state Markov chain (coin flip dynamics). -/
def twoStateGenerator : Matrix (Fin 2) (Fin 2) ℝ :=
  ![![-1, 1], ![1, -1]]

/-- Uniform distribution on 2 states. -/
noncomputable def uniformDist2 : Fin 2 → ℝ := fun _ => 1/2

/-- The trivial partition: each state in its own block. -/
def trivialPartition2 : Setoid (Fin 2) := ⟨Eq, ⟨Eq.refl, Eq.symm, Eq.trans⟩⟩

/-- The coarse partition: all states in one block. -/
def coarsePartition2 : Setoid (Fin 2) := ⟨fun _ _ => True, ⟨fun _ => trivial, fun _ => trivial, fun _ _ => trivial⟩⟩

end ConcreteInstantiation

section ComputationalPropertyTests
/-! ## Computational Property Tests

These tests verify mathematical properties **numerically**, not just type-theoretically.
Unlike the axiom audit (which verifies logical dependencies), these tests compute
actual values and assert correctness.

**Key distinction:**
- Axiom audit: "Does this theorem depend only on standard axioms?"
- Property test: "Does this concrete example satisfy the mathematical definition?"

**Why this matters:** A vacuous definition could type-check but fail numerical tests.
These tests use `Rat` (exact rationals) for reproducible arithmetic.

**Test Design:**
- **Positive tests**: Valid examples that MUST pass
- **Negative tests**: Invalid examples that MUST fail (proves tests have teeth)
-/

open Matrix

/-- A 2-state symmetric Markov generator (coin-flip dynamics).
    L = [[-1, 1], [1, -1]] with uniform stationary distribution. -/
def testGenerator : Matrix (Fin 2) (Fin 2) Rat :=
  !![(-1 : Rat), 1; 1, -1]

/-- Uniform stationary distribution on 2 states. -/
def testStationary : Fin 2 → Rat := fun _ => 1/2

/-- A BAD "generator" (identity matrix) - row sums are NOT zero.
    This MUST fail the generator property test. -/
def badGenerator : Matrix (Fin 2) (Fin 2) Rat :=
  !![(1 : Rat), 0; 0, 1]

/-- A WRONG stationary distribution for testGenerator.
    This MUST fail the stationarity test. -/
def wrongStationary : Fin 2 → Rat := fun i => if i = 0 then 1 else 0

/-! ### Property Checkers -/

/-- Check that all row sums equal zero (Markov generator property).
    A matrix L is a generator iff Σⱼ L_ij = 0 for all i. -/
def checkRowSumsZero (L : Matrix (Fin 2) (Fin 2) Rat) : Bool :=
  (L 0 0 + L 0 1 == 0) && (L 1 0 + L 1 1 == 0)

/-- Check πL = 0 (stationary distribution property).
    π is stationary for L iff Σᵢ π_i L_ij = 0 for all j. -/
def checkStationary (pi : Fin 2 → Rat) (L : Matrix (Fin 2) (Fin 2) Rat) : Bool :=
  let col0 := pi 0 * L 0 0 + pi 1 * L 1 0
  let col1 := pi 0 * L 0 1 + pi 1 * L 1 1
  (col0 == 0) && (col1 == 0)

/-- Check π is a valid probability distribution (positive, normalized). -/
def checkProbabilityDist (pi : Fin 2 → Rat) : Bool :=
  (pi 0 > 0) && (pi 1 > 0) && (pi 0 + pi 1 == 1)

/-- Check detailed balance: π_i L_ij = π_j L_ji (reversibility). -/
def checkDetailedBalance (pi : Fin 2 → Rat) (L : Matrix (Fin 2) (Fin 2) Rat) : Bool :=
  pi 0 * L 0 1 == pi 1 * L 1 0

/-! ### Execute Tests -/

-- Positive tests (all should return true)
#eval checkRowSumsZero testGenerator        -- Expected: true
#eval checkStationary testStationary testGenerator  -- Expected: true
#eval checkProbabilityDist testStationary   -- Expected: true
#eval checkDetailedBalance testStationary testGenerator  -- Expected: true

-- Negative tests (all should return false - PROVES TESTS HAVE TEETH)
#eval checkRowSumsZero badGenerator         -- Expected: false (row sums = 1, not 0)
#eval checkStationary wrongStationary testGenerator  -- Expected: false (not stationary)

/-- Run all property tests and report results. -/
def runPropertyTests : IO Unit := do
  IO.println "┌─────────────────────────────────────────────────────────┐"
  IO.println "│         COMPUTATIONAL PROPERTY TESTS                    │"
  IO.println "├─────────────────────────────────────────────────────────┤"

  -- Positive tests
  let t1 := checkRowSumsZero testGenerator
  let t2 := checkStationary testStationary testGenerator
  let t3 := checkProbabilityDist testStationary
  let t4 := checkDetailedBalance testStationary testGenerator

  IO.println s!"│ Generator row sums = 0:        {if t1 then "✓ PASS" else "✗ FAIL"}                │"
  IO.println s!"│ πL = 0 (stationarity):         {if t2 then "✓ PASS" else "✗ FAIL"}                │"
  IO.println s!"│ π valid probability dist:      {if t3 then "✓ PASS" else "✗ FAIL"}                │"
  IO.println s!"│ Detailed balance (πᵢLᵢⱼ=πⱼLⱼᵢ): {if t4 then "✓ PASS" else "✗ FAIL"}                │"

  -- Negative tests (these SHOULD fail)
  let n1 := checkRowSumsZero badGenerator
  let n2 := checkStationary wrongStationary testGenerator

  IO.println "├─────────────────────────────────────────────────────────┤"
  IO.println "│ NEGATIVE TESTS (must fail to prove tests have teeth)    │"
  IO.println s!"│ Bad generator rejected:        {if !n1 then "✓ PASS" else "✗ FAIL"}                │"
  IO.println s!"│ Wrong stationary rejected:     {if !n2 then "✓ PASS" else "✗ FAIL"}                │"

  let allPass := t1 && t2 && t3 && t4 && !n1 && !n2
  IO.println "├─────────────────────────────────────────────────────────┤"
  IO.println s!"│ ALL PROPERTY TESTS:            {if allPass then "✓ PASS" else "✗ FAIL"}                │"
  IO.println "└─────────────────────────────────────────────────────────┘"

#eval runPropertyTests

end ComputationalPropertyTests

/-! ## Success Message

This runs during elaboration, so interpreter users see it.
-/

#eval IO.println "✓ SGC sanity checks passed. All structures are non-vacuous."
