#!/usr/bin/env python3
"""Local checklist teaching example. Python 3.9+, standard library only.

Prints JSON to stdout; reads only its own source file for a manifest hash.
No model, network, external action, workflow replay, or production certification.
Exit 0: observed comparisons and reference checks pass. Exit 1: a check fails.
Use --fault variation or --fault wrong to exercise intentional negative controls.
"""
import argparse
import copy
import hashlib
import json
import platform
from pathlib import Path

CASES = [
    {"id": "within-limit", "input": {"supplier_verified": True, "amount_cents": 10000},
     "expected": {"decision": "approve", "reason": "within_limit"}},
    {"id": "above-limit", "input": {"supplier_verified": True, "amount_cents": 10001},
     "expected": {"decision": "review", "reason": "above_limit"}},
    {"id": "unverified-supplier", "input": {"supplier_verified": False, "amount_cents": 500},
     "expected": {"decision": "unresolved", "reason": "supplier_unverified"}},
    {"id": "missing-amount", "input": {"supplier_verified": True, "amount_cents": None},
     "expected": {"decision": "unresolved", "reason": "amount_missing_or_invalid"}},
]


def decide(record):
    """Toy policy: verified supplier and valid integer cents; approve <= 10000."""
    if record.get("supplier_verified") is not True:
        return {"decision": "unresolved", "reason": "supplier_unverified"}
    amount = record.get("amount_cents")
    if type(amount) is not int or amount < 0:
        return {"decision": "unresolved", "reason": "amount_missing_or_invalid"}
    if amount > 10000:
        return {"decision": "review", "reason": "above_limit"}
    return {"decision": "approve", "reason": "within_limit"}


def fingerprint(value):
    return hashlib.sha256(json.dumps(value, sort_keys=True).encode()).hexdigest()


def evaluate(comparisons, fault):
    cases = []
    for case in CASES:
        records = []
        baseline = None
        for run in range(comparisons + 1):
            result = decide(copy.deepcopy(case["input"]))
            # Injected faults test the checker. They are not model observations.
            # Variation deliberately changes a condition (run index).
            if fault == "wrong":
                result = {"decision": "approve", "reason": "injected_wrong_result"}
            elif fault == "variation" and run % 2:
                result = {"decision": "review", "reason": "injected_variation"}
            if run == 0:
                baseline = copy.deepcopy(result)
            records.append({
                "run_id": case["id"] + ":" + str(run),
                "role": "baseline" if run == 0 else "comparison",
                "result": result,
                "matches_baseline": None if run == 0 else result == baseline,
                "matches_reference": result == case["expected"],
            })
        cases.append({**copy.deepcopy(case), "runs": records})
    records = [r for c in cases for r in c["runs"]]
    compared = [r for r in records if r["role"] == "comparison"]
    agreement = sum(r["matches_baseline"] for r in compared)
    correct = sum(r["matches_reference"] for r in records)
    return {
        "example_version": "1",
        "scope": "Toy rule function; fresh calls in one process with copied inputs. No AI model or external action.",
        "mode": "fresh_function_calls",
        "fault": fault,
        "manifest": {
            "python": platform.python_version(),
            "platform": platform.platform(),
            "script_sha256": hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
            "fixtures_sha256": fingerprint(CASES),
            "rule_version": "toy-invoice-1",
            "cache": "none",
            "state_reset": "new deep copy of fixture per call; toy function has no external state",
            "equality": "exact decision and reason values; run_id excluded",
        },
        "summary": {
            "cases": len(cases),
            "baselines": len(cases),
            "comparisons": len(compared),
            "matching_comparisons": agreement,
            "reference_checks_including_baselines": len(records),
            "matching_reference_checks": correct,
            "repeatability_observed": agreement == len(compared),
            "reference_checks_passed": correct == len(records),
        },
        "untested": ["model interpretation", "production environment isolation",
                     "external actions", "human exception authorization", "workflow replay",
                     "production evaluator tamper resistance"],
        "cases": cases,
    }


def positive_int(value):
    number = int(value)
    if number < 1:
        raise argparse.ArgumentTypeError("must be at least 1")
    return number


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--comparisons", type=positive_int, default=5)
    parser.add_argument("--fault", choices=["none", "variation", "wrong"], default="none")
    args = parser.parse_args()
    report = evaluate(args.comparisons, args.fault)
    print(json.dumps(report, indent=2, sort_keys=True))
    passed = report["summary"]["repeatability_observed"] and report["summary"]["reference_checks_passed"]
    return 0 if passed else 1


if __name__ == "__main__":
    raise SystemExit(main())
