"""Pre-registered multi-resolution gate for the AP1-M1 short candidate."""
from __future__ import annotations

from dataclasses import asdict
import json
from pathlib import Path

from ap1_r2c_self_consistent_candidate import CandidateConfig, run_candidate


G22_THRESHOLDS = {
    "max_abs_friedmann_residual": 1.0e-6,
    "ward_normalized": 2.0e-6,
    "validation_source_relative_change": 1.0e-4,
    "validation_wronskian_relative_error": 1.0e-11,
}


def classify(levels: list[dict]) -> dict:
    keys = tuple(G22_THRESHOLDS)
    complete = len(levels) == 3 and all(level.get("success", True) for level in levels)
    if not complete:
        return {
            "structural_gates_pass": False,
            "monotonic_refinement": {key: False for key in keys},
            "fine_level_threshold_pass": {key: False for key in keys},
            "pass": False,
            "classification": "G22_ORANGE_REFINEMENT_FAILURE",
        }
    series = {key: [float(level["diagnostics"][key]) for level in levels] for key in keys}
    monotonic = {
        key: all(values[i + 1] <= values[i] for i in range(len(values) - 1))
        for key, values in series.items()
    }
    fine_pass = {
        key: values[-1] <= G22_THRESHOLDS[key]
        for key, values in series.items()
    }
    structural = all(
        level["diagnostics"][gate]
        for level in levels
        for gate in ("finite", "positive_H")
    ) and all(
        level["diagnostics"][gate] > 0.0
        for level in levels
        for gate in ("min_PX", "min_K")
    )
    passed = structural and all(monotonic.values()) and all(fine_pass.values())
    return {
        "structural_gates_pass": structural,
        "monotonic_refinement": monotonic,
        "fine_level_threshold_pass": fine_pass,
        "pass": passed,
        "classification": "G22_PASS" if passed else "G22_ORANGE_NOT_PASS",
    }


def run_suite(state_path: Path) -> dict:
    levels = []
    for nodes in (17, 33, 65):
        cfg = CandidateConfig(candidate_nodes=nodes)
        try:
            result = run_candidate(state_path, cfg)
            levels.append({
                "candidate_nodes": nodes,
                "success": True,
                "config": asdict(cfg),
                "diagnostics": result["diagnostics"],
                "seed": result["seed"],
            })
        except (RuntimeError, ValueError, FloatingPointError) as exc:
            levels.append({
                "candidate_nodes": nodes,
                "success": False,
                "config": asdict(cfg),
                "error_type": type(exc).__name__,
                "error": str(exc),
            })
            break
    verdict = classify(levels)
    return {
        "schema": "apeiron-ap1-r2c-candidate-multiresolution-v1.0",
        "thresholds_frozen_before_33_and_65_node_runs": G22_THRESHOLDS,
        "levels": levels,
        "verdict": verdict,
        "old_solver_or_physical_map_called": False,
        "claim_boundary": "short local convergence gate only; no production H(z), growth, lensing, fit, or empirical claim",
    }


def main() -> None:
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("state", type=Path)
    parser.add_argument("--output", type=Path)
    args = parser.parse_args()
    rendered = json.dumps(run_suite(args.state), indent=2) + "\n"
    if args.output:
        args.output.write_text(rendered, encoding="utf-8")
    else:
        print(rendered, end="")


if __name__ == "__main__":
    main()
