#!/usr/bin/env python3
import hashlib
import json
import re
import sys
from pathlib import Path

PROJECT = Path(__file__).resolve().parents[1]
WORD_RE = re.compile(r"[^\W_]+(?:['’-][^\W_]+)*", re.UNICODE)
ALLOWED = {"Ngôn tình học đường / thanh xuân", "Hào môn / tổng tài / liên hôn", "Cưới trước yêu sau / hôn ước từ bé", "Thanh mai trúc mã / nuôi từ bé", "Trà xanh / bạch nguyệt quang / người thứ ba", "Thiên kim thật–giả / gia đình phản diện / trở về", "Yếu tố high-concept"}

def load(rel):
    return json.loads((PROJECT / rel).read_text(encoding="utf-8"))

def sha(path):
    h = hashlib.sha256()
    with path.open("rb") as f:
        for block in iter(lambda: f.read(8 * 1024 * 1024), b""):
            h.update(block)
    return h.hexdigest()

def main():
    brief = load("script/story-brief.json")
    outline = load("script/story-outline.json")
    ledger = load("script/continuity-ledger.json")
    fmap = load("script/family-causal-map.json")
    baseline = load("script/authority-baseline.json")
    chapters = [PROJECT / "story/chapters" / f"chapter-{i:02d}.txt" for i in range(1, 11)]
    missing = [str(p) for p in chapters if not p.is_file()]
    if missing:
        print(json.dumps({"verified": False, "issues": ["missing:" + x for x in missing]}, ensure_ascii=False)); return 1
    texts = [p.read_text(encoding="utf-8").rstrip("\n") for p in chapters]
    joined = "\n\n".join(texts) + "\n"
    spoken = (PROJECT / "story/spoken-narration.txt").read_text(encoding="utf-8")
    canon = (PROJECT / "story/story-canon.txt").read_text(encoding="utf-8")
    words = len(WORD_RE.findall(spoken))
    family = brief.get("primary_story_family")
    auth_files = ["script/story-brief.json", "script/story-outline.json", "script/continuity-ledger.json", "script/identity-registry.json", "script/reveal-ledger.json", "script/family-causal-map.json", "script/workflow-copy-authority.json"]
    current = {rel: sha(PROJECT / rel) for rel in auth_files}
    checks = {
        "family_closed_taxonomy": family in ALLOWED,
        "family_exact_binding": family == fmap.get("primary_story_family") == outline.get("family") == ledger.get("family"),
        "family_causal_gate": fmap.get("verified") is True or fmap.get("status") == "prelock",
        "brief_locked": brief.get("verified") is True and brief.get("lock_state") == "BRIEF_LOCK",
        "baseline_project": baseline.get("project_id") == "016" and baseline.get("status") == "locked",
        "baseline_authority_hashes": all(baseline.get("authority_hashes", {}).get(k) == v for k, v in current.items()),
        "exact_join": spoken == joined,
        "canon_byte_identical": canon == spoken,
        "word_range": int(brief["length"]["min_words"]) <= words <= int(brief["length"]["max_words"]),
        "duration_range": 40 <= words / 231 <= 60,
        "chapter_count": len(chapters) == 10,
        "reveal_ledger_consistent": "chapter-02" in ledger["reveal_boundaries"]["R2"],
    }
    result = {"verified": all(checks.values()), "project_id": "016", "family": family, "word_count": words, "duration_minutes_at_231_wpm": round(words / 231, 3), "checks": checks, "hashes": {"spoken": sha(PROJECT / "story/spoken-narration.txt"), "canon": sha(PROJECT / "story/story-canon.txt")}}
    print(json.dumps(result, ensure_ascii=False))
    return 0 if result["verified"] else 1

if __name__ == "__main__":
    sys.exit(main())
