#!/usr/bin/env python3
"""
Shared helpers for TOE verifier scripts.

The older verifiers are standalone; new audit verifiers can import this
module to keep pass/fail accounting and numeric tolerances consistent.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import List, Optional


@dataclass
class CheckResult:
    label: str
    ok: bool
    computed: object = ""
    claimed: object = ""
    detail: str = ""


class Verifier:
    def __init__(self, name: str):
        self.name = name
        self.results: List[CheckResult] = []
        print("=" * 72)
        print(name)
        print("=" * 72)

    def check(
        self,
        label: str,
        computed: float,
        claimed: float,
        *,
        rel: Optional[float] = 1e-3,
        abs_tol: Optional[float] = None,
        detail: str = "",
    ) -> bool:
        if abs_tol is not None:
            ok = abs(computed - claimed) <= abs_tol
            err = abs(computed - claimed)
            err_detail = f"abs err={err:.6g}, tol={abs_tol:.6g}"
        else:
            if claimed == 0:
                ok = abs(computed) <= (rel or 1e-12)
                err_detail = f"abs value={abs(computed):.6g}, tol={rel:.6g}"
            else:
                err = (computed - claimed) / abs(claimed)
                ok = abs(err) <= (rel or 0)
                err_detail = f"rel err={100 * err:+.6g}%, tol={100 * (rel or 0):.6g}%"
        return self.record(label, ok, computed, claimed, f"{err_detail}" + (f"; {detail}" if detail else ""))

    def record(self, label: str, ok: bool, computed: object = "", claimed: object = "", detail: str = "") -> bool:
        self.results.append(CheckResult(label, ok, computed, claimed, detail))
        status = "PASS" if ok else "FAIL"
        print(f"[{status}] {label}")
        if computed != "" or claimed != "":
            print(f"       computed: {computed}")
            print(f"       claimed : {claimed}")
        if detail:
            print(f"       {detail}")
        return ok

    def summary(self) -> int:
        passed = sum(r.ok for r in self.results)
        failed = len(self.results) - passed
        print()
        print("=" * 72)
        print(f"SUMMARY: {passed} PASS, {failed} FAIL, {len(self.results)} TOTAL")
        print("=" * 72)
        if failed:
            print("Failed checks:")
            for r in self.results:
                if not r.ok:
                    print(f"  - {r.label}")
            return 1
        return 0

