from __future__ import annotations

import os
import json
import datetime
from .common import sha256_file


def _utc_now_z() -> str:
    return datetime.datetime.now(datetime.UTC).isoformat(timespec="seconds").replace("+00:00", "Z")


def gate_nz(dataset_dir: str) -> dict:
    path = os.path.join(dataset_dir, "nz_metrics.json")

    with open(path, "r", encoding="utf-8") as f:
        m = json.load(f)

    smin_L = float(m["smin_L"])
    smin_U = float(m["smin_U"])
    rho_max = float(m["rho_max"])
    eps_m = float(m.get("eps_m", 0.0))
    slack_rule = (smin_L > 0.0) and (smin_U > 0.0)
    spectral_rule = rho_max <= (1.0 - eps_m)
    pass_rule = slack_rule and spectral_rule

    return {
        "row": 22,
        "gate": "neutral_zone_sandwich",
        "context": "LIVE",
        "tier": "Diagnostic",
        "timestamp_utc": _utc_now_z(),
        "metrics": {
            "smin_L": smin_L,
            "smin_U": smin_U,
            "rho_max": rho_max,
            "eps_m": eps_m,
        },
        "rule": "smin_L > 0 and smin_U > 0 and rho_max <= 1 - eps_m",
        "checks": {
            "lower_slack_positive": smin_L > 0.0,
            "upper_slack_positive": smin_U > 0.0,
            "spectral_guard_holds": spectral_rule,
        },
        "status": "PASS_NZ_SLACKS_AND_SPECTRAL_GUARD" if pass_rule else "FAIL_NZ_SLACK_OR_SPECTRAL_GUARD",
        "verdict": "PASS" if pass_rule else "FAIL",
        "blocking": False,
        "inputs": {
            "hashes": {
                "nz_metrics.json": sha256_file(path)
            }
        }
    }


def _write_row22_tex(res: dict, tex_path: str) -> None:
    def tex_escape(s: object) -> str:
        text = str(s)
        return (
            text.replace("\\", r"\textbackslash{}")
            .replace("{", r"\{")
            .replace("}", r"\}")
            .replace("_", r"\_")
            .replace("&", r"\&")
            .replace("%", r"\%")
            .replace("#", r"\#")
        )

    metrics = res.get("metrics", {})

    lines = [
        rf"\def\RowXXIIVerdict{{{tex_escape(res.get('verdict', 'PENDING_DATA'))}}}",
        rf"\def\RowXXIIRunTag{{{tex_escape(res.get('gate', 'neutral_zone_sandwich'))}}}",
        rf"\def\RowXXIITier{{{tex_escape(res.get('tier', 'Diagnostic'))}}}",
        rf"\def\RowXXIIContext{{{tex_escape(res.get('context', 'LIVE'))}}}",
        rf"\def\RowXXIIRule{{{tex_escape(res.get('rule', 'rho_max <= 1 - eps_m'))}}}",
        rf"\def\RowXXIISMinL{{{tex_escape(metrics.get('smin_L', ''))}}}",
        rf"\def\RowXXIISMinU{{{tex_escape(metrics.get('smin_U', ''))}}}",
        rf"\def\RowXXIIRhoMax{{{tex_escape(metrics.get('rho_max', ''))}}}",
        rf"\def\RowXXIIEpsM{{{tex_escape(metrics.get('eps_m', ''))}}}",
    ]

    with open(tex_path, "w", encoding="utf-8") as f:
        f.write("\n".join(lines) + "\n")


if __name__ == "__main__":
    here = os.path.dirname(__file__)
    repo_root = os.path.abspath(os.path.join(here, ".."))
    dataset_dir = os.path.join(repo_root, "datasets")
    out_dir = os.path.join(repo_root, "results", "row22_nz")
    tex_path = os.path.join(repo_root, "results", "row22_results.tex")

    os.makedirs(out_dir, exist_ok=True)

    res = gate_nz(dataset_dir)

    with open(os.path.join(out_dir, "result.json"), "w", encoding="utf-8") as f:
        json.dump(res, f, indent=2, sort_keys=True)

    _write_row22_tex(res, tex_path)

    print(res["verdict"])