from __future__ import annotations

import os
from pathlib import Path
import unittest

import numpy as np

from ap1_r2c_implicit_dae_preflight import (
    build_preflight,
    dae_dimensions,
    lobatto_grid_and_D,
    positive_friedmann_root,
)


STATE = Path(os.environ["APEIRON_AP1_STATE_NPZ"])


class ImplicitDAEPreflightTests(unittest.TestCase):
    def test_lobatto_derivative_is_exact_for_quartic_canary(self):
        N, D = lobatto_grid_and_D(17, 1.0e-7)
        x = 2.0 * N / 1.0e-7 - 1.0
        exact = 8.0e7 * x**3
        np.testing.assert_allclose(D @ x**4, exact, rtol=2.0e-12, atol=1.0e-5)

    def test_dae_system_is_square(self):
        self.assertTrue(dae_dimensions(33)["square"])
        self.assertEqual(dae_dimensions(33)["unknowns"], 232)

    def test_nonpositive_friedmann_density_fails_closed(self):
        with self.assertRaises(ValueError):
            positive_friedmann_root(np.array([1.0, 0.0]))

    def test_physical_seed_preflight_passes_without_candidate_claim(self):
        report = build_preflight(STATE)
        self.assertEqual(report["classification"], "IMPLICIT_DAE_FORMULATION_PREFLIGHT_PASS_SOLVE_NOT_RUN")
        self.assertIn("no candidate PASS", report["claim_boundary"])
        self.assertFalse(report["gates"]["old_solver_or_physical_map_called"])


if __name__ == "__main__":
    unittest.main()
