"""Fail-closed structural preflight for the AP1-R3 CTP/in-in response path.

This module does not construct a physical response kernel.  It hash-binds the
frozen R3 contracts, verifies the preceding G22 PASS, and supplies only
analytic canaries for retardation, Wightman reality and the portal mass jet.
"""
from __future__ import annotations

from dataclasses import asdict, dataclass
from hashlib import sha256
import json
from pathlib import Path

import numpy as np


F_PHASE = 0.8549468502440697
PORTAL_V = 0.03272387838931097
PORTAL_LAMBDA = 1.6740193604000272e-5
M_CHI_0 = 9.817951142008693e-5


class ResponsePreflightError(RuntimeError):
    """A frozen prerequisite or structural response requirement is absent."""


@dataclass(frozen=True)
class PilotBudget:
    """Budgets registered before any physical kernel production run."""

    time_nodes: tuple[int, ...] = (17, 33, 65)
    momentum_nodes: tuple[int, ...] = (8, 16, 32)
    memory_fractions: tuple[float, ...] = (0.5, 0.75, 1.0)
    regulator_variants_minimum: int = 3
    independent_reference_cases_minimum: int = 1


def file_sha256(path: Path) -> str:
    digest = sha256()
    with path.open("rb") as stream:
        for block in iter(lambda: stream.read(1024 * 1024), b""):
            digest.update(block)
    return digest.hexdigest()


def retarded_mask(times: np.ndarray) -> np.ndarray:
    """Return mask[row t, column t'] for the closed retarded domain t' <= t."""

    t = np.asarray(times, dtype=float)
    if t.ndim != 1 or t.size < 2 or not np.all(np.isfinite(t)):
        raise ValueError("finite one-dimensional time grid with at least two nodes required")
    if np.any(np.diff(t) <= 0.0):
        raise ValueError("time grid must be strictly increasing")
    return t[None, :] <= t[:, None]


def harmonic_wightman_canary(times: np.ndarray, omega: float = 1.7) -> np.ndarray:
    """Exact unequal-time Wightman matrix for a normalized oscillator canary."""

    t = np.asarray(times, dtype=float)
    retarded_mask(t)
    if not np.isfinite(omega) or omega <= 0.0:
        raise ValueError("positive finite oscillator frequency required")
    delta = t[:, None] - t[None, :]
    return np.exp(-1j * omega * delta) / (2.0 * omega)


def chi2_unit_spectral_canary(
    wightman: np.ndarray,
    times: np.ndarray,
    hermitian_tolerance: float = 1.0e-13,
) -> np.ndarray:
    """Unit-normalized retarded Im[(G+)^2] canary, not a physical AP1 kernel."""

    g = np.asarray(wightman, dtype=np.complex128)
    t = np.asarray(times, dtype=float)
    mask = retarded_mask(t)
    if g.shape != mask.shape or not np.all(np.isfinite(g)):
        raise ValueError("finite square Wightman matrix must match the time grid")
    hermitian_error = float(np.max(np.abs(g - g.T.conj())))
    if hermitian_error > hermitian_tolerance:
        raise ResponsePreflightError(
            f"Wightman conjugation identity failed: {hermitian_error}"
        )
    return np.where(mask, np.imag(g * g), 0.0)


def portal_mass_jet(
    sigma: float,
    theta: float,
    *,
    m_chi_0: float = M_CHI_0,
    portal_lambda: float = PORTAL_LAMBDA,
    displacement: float = PORTAL_V,
    f_phase: float = F_PHASE,
) -> dict[str, float | list[list[float]]]:
    """Portal mass, gradient and symmetric Hessian from the frozen mass law."""

    values = np.array(
        [sigma, theta, m_chi_0, portal_lambda, displacement, f_phase],
        dtype=float,
    )
    if not np.all(np.isfinite(values)) or m_chi_0 < 0.0 or f_phase <= 0.0:
        raise ValueError("finite portal inputs, non-negative mass and positive phase scale required")
    u = displacement + sigma
    angle = 2.0 * theta / f_phase
    cosine = float(np.cos(angle))
    sine = float(np.sin(angle))
    mass_squared = m_chi_0**2 + 2.0 * portal_lambda * u**2 * cosine
    d_sigma = 4.0 * portal_lambda * u * cosine
    d_theta = -4.0 * portal_lambda * u**2 * sine / f_phase
    d_sigma_sigma = 4.0 * portal_lambda * cosine
    d_sigma_theta = -8.0 * portal_lambda * u * sine / f_phase
    d_theta_theta = -8.0 * portal_lambda * u**2 * cosine / f_phase**2
    return {
        "mass_squared": float(mass_squared),
        "gradient": [float(d_sigma), float(d_theta)],
        "hessian": [
            [float(d_sigma_sigma), float(d_sigma_theta)],
            [float(d_sigma_theta), float(d_theta_theta)],
        ],
    }


RESPONSE_SPEC_MARKERS = (
    "Pi_AB^R",
    "Pi_AB,contact",
    "Pi_AB,ct",
    "delta J_A,state",
    "erst vollständige Stress-/Portalantwort, dann Ward-Prüfung",
    "Hintergrund-Subtraktion darf nicht unverändert auf ungleiche Zeiten übertragen werden",
)

A3_MARKERS = (
    "Γ_χ^CTP",
    "δJ_A,state",
    "Ward-Identität",
    "Toleranzen und Laufbudgets müssen vor dem ersten Produktionslauf registriert werden",
)


def _require_markers(text: str, markers: tuple[str, ...], label: str) -> None:
    missing = [marker for marker in markers if marker not in text]
    if missing:
        raise ResponsePreflightError(f"{label} is missing required markers: {missing}")


def build_preflight(
    response_spec: Path,
    a3_requirements: Path,
    g22_checkpoint: Path,
) -> dict:
    response_text = response_spec.read_text(encoding="utf-8")
    a3_text = a3_requirements.read_text(encoding="utf-8")
    _require_markers(response_text, RESPONSE_SPEC_MARKERS, "response specification")
    _require_markers(a3_text, A3_MARKERS, "A3 requirements")

    g22 = json.loads(g22_checkpoint.read_text(encoding="utf-8"))
    if (
        g22.get("classification") != "G22_PASS"
        or not g22.get("all_absolute_gates_pass")
        or not all(g22.get("monotonic_refinement", {}).values())
        or g22.get("nonpass_stored_or_used_as_seed") is not False
    ):
        raise ResponsePreflightError("exact G22 PASS prerequisite is not satisfied")

    times = np.linspace(0.0, 2.0, 17)
    wightman = harmonic_wightman_canary(times)
    spectral = chi2_unit_spectral_canary(wightman, times)
    mask = retarded_mask(times)
    upper_violation = float(np.max(np.abs(spectral[~mask])))
    reality_violation = float(np.max(np.abs(np.imag(spectral.astype(complex)))))
    equal_time_violation = float(np.max(np.abs(np.diag(spectral))))
    wightman_identity_error = float(np.max(np.abs(wightman - wightman.T.conj())))

    jet = portal_mass_jet(0.013, -0.21)
    hessian = np.asarray(jet["hessian"], dtype=float)
    hessian_symmetry_error = float(np.max(np.abs(hessian - hessian.T)))
    canary_gates = {
        "retarded_support_exact": upper_violation == 0.0,
        "spectral_block_real_exact": reality_violation == 0.0,
        "equal_time_commutator_zero_within_1e_15": equal_time_violation < 1.0e-15,
        "wightman_conjugation_below_1e_13": wightman_identity_error < 1.0e-13,
        "portal_mass_hessian_symmetric_exact": hessian_symmetry_error == 0.0,
    }
    if not all(canary_gates.values()):
        raise ResponsePreflightError(f"analytic response canary failed: {canary_gates}")

    budget = PilotBudget()
    return {
        "schema": "apeiron-ap1-r3-response-kernel-preflight-v1.0",
        "classification": "R3_STRUCTURAL_PREFLIGHT_PASS_PHYSICAL_KERNEL_NOT_COMPUTED",
        "prerequisite": {
            "g22_classification": g22["classification"],
            "g22_atomic_state": g22["atomic_state"],
            "g22_tests": g22["tests"],
            "nonpass_seed_used": False,
        },
        "frozen_inputs_sha256": {
            "response_spec": file_sha256(response_spec),
            "a3_requirements": file_sha256(a3_requirements),
            "g22_checkpoint": file_sha256(g22_checkpoint),
        },
        "operator_contract": {
            "sources": ["metric_stress", "sigma_portal", "theta_portal"],
            "response_terms": [
                "retarded_composite_operator_commutator",
                "local_contact",
                "local_counterterm_variation",
                "separate_initial_state_variation",
            ],
            "mandatory_order": [
                "full_stress_and_portal_response",
                "coupled_linearized_Ward_test",
                "scalar_constraint_elimination",
            ],
            "background_series_used_as_two_time_kernel": False,
        },
        "analytic_canaries": {
            "time_nodes": int(times.size),
            "oscillator_omega": 1.7,
            "upper_causal_violation": upper_violation,
            "reality_violation": reality_violation,
            "equal_time_violation": equal_time_violation,
            "wightman_identity_error": wightman_identity_error,
            "portal_hessian_symmetry_error": hessian_symmetry_error,
            "gates": canary_gates,
        },
        "pilot_registry": {
            "budgets": asdict(budget),
            "physical_gate_thresholds_frozen": False,
            "threshold_freeze_rule": (
                "derive once from the documented non-production pilot and an independent "
                "roundoff/error budget, then freeze before the first physical production run"
            ),
            "post_hoc_threshold_adjustment_allowed": False,
        },
        "blocked_physical_components": [
            "new_AP1_M1_background_over_relevant_cosmological_range",
            "renormalized_unequal_time_operator_blocks",
            "local_contact_and_counterterm_variation_implementation",
            "gauge_invariant_scalar_projection_and_constraint_elimination",
            "independently_frozen_physical_gate_thresholds",
        ],
        "execution": {
            "physical_kernel_computed": False,
            "production_curve_released": False,
            "old_v7_13_solver_or_physical_map_called": False,
            "equations_changed": False,
            "physics_changed": False,
            "gates_changed": False,
        },
        "next_required": (
            "implement a synthetic unequal-time operator-block reference path and an explicit "
            "local contact/counterterm manifest; keep physical kernel production blocked until "
            "the new AP1-M1 background and frozen pilot-derived tolerances exist"
        ),
        "claim_boundary": (
            "structural CTP/in-in preflight and analytic canaries only; no renormalized physical "
            "response kernel, perturbation stability result, observable or empirical claim"
        ),
    }


def main() -> None:
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("response_spec", type=Path)
    parser.add_argument("a3_requirements", type=Path)
    parser.add_argument("g22_checkpoint", type=Path)
    parser.add_argument("--output", type=Path)
    args = parser.parse_args()
    report = build_preflight(
        args.response_spec,
        args.a3_requirements,
        args.g22_checkpoint,
    )
    rendered = json.dumps(report, indent=2) + "\n"
    if args.output is None:
        print(rendered, end="")
    else:
        args.output.write_text(rendered, encoding="utf-8")


if __name__ == "__main__":
    main()
