#!/usr/bin/env python3
"""Offline XMSE C2 Merkle inclusion proof verifier (stdlib only)."""
from __future__ import annotations

import argparse
import hashlib
import json
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "scripts/lib"))

from xmse_transparency_registry import inclusion_proof, leaf_hash, load_entries, merkle_root  # noqa: E402

LOG = ROOT / "data/ops/media-provenance/transparency-log.jsonl"
ROOT_JSON = ROOT / "data/ops/media-provenance/transparency-merkle.json"


def _pair_hash(left: bytes, right: bytes) -> bytes:
    pair = left + right if left <= right else right + left
    return hashlib.sha256(pair).digest()


def verify_proof(leaf_hex: str, proof: list[dict[str, str]], expected_root: str) -> bool:
    cur = bytes.fromhex(leaf_hex)
    for step in proof:
        sib = bytes.fromhex(step["hash"])
        if step.get("position") == "left":
            cur = _pair_hash(sib, cur)
        else:
            cur = _pair_hash(cur, sib)
    return cur.hex() == expected_root


def main() -> int:
    ap = argparse.ArgumentParser(description="Verify XMSE Merkle inclusion proof (C2)")
    ap.add_argument("--proof", type=Path, help="JSON proof file from inclusion_proof()")
    ap.add_argument("--index", type=int, help="Recompute proof for log index")
    args = ap.parse_args()

    if args.proof:
        doc = json.loads(args.proof.read_text(encoding="utf-8"))
        ok = verify_proof(doc["leaf"], doc.get("proof") or [], doc["root"])
        print(json.dumps({"ok": ok, "root": doc["root"], "index": doc.get("index")}))
        return 0 if ok else 1

    if args.index is not None:
        proof_doc = inclusion_proof(args.index)
        if not proof_doc:
            print(json.dumps({"ok": False, "error": "index_out_of_range", "index": args.index}))
            return 1
        ok = verify_proof(proof_doc["leaf"], proof_doc.get("proof") or [], proof_doc["root"])
        if ROOT_JSON.is_file():
            published = json.loads(ROOT_JSON.read_text(encoding="utf-8"))
            ok = ok and published.get("merkleRoot") == proof_doc["root"]
        print(json.dumps({"ok": ok, "index": args.index, "root": proof_doc["root"], "entryCount": len(load_entries())}))
        return 0 if ok else 1

    if LOG.is_file() and ROOT_JSON.is_file():
        entries = load_entries()
        leaves = [leaf_hash(json.dumps(e, sort_keys=True, ensure_ascii=False)) for e in entries]
        root = merkle_root(leaves)
        published = json.loads(ROOT_JSON.read_text(encoding="utf-8"))
        ok = root == published.get("merkleRoot")
        print(json.dumps({"ok": ok, "entryCount": len(entries), "root": root}))
        return 0 if ok else 1

    print(json.dumps({"ok": False, "error": "no_log_or_proof"}))
    return 1


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