#!/usr/bin/env python3
"""CHECK — recovery-registry extract (Extract lane, 2026-10-28).

Independent verification: re-derives the registry straight from the source
(recoveries/ + WORK-QUEUE.md), without importing the extractor, and diffs it
against the committed recoveries-registry.tsv. Exits 0 only if every check
passes. (No fallback arms; a failing check produces a nonzero exit.)
"""
import hashlib
import json
import os
import sys

HERE = os.path.dirname(os.path.abspath(__file__))
REPO_ROOT = os.path.abspath(os.path.join(HERE, "..", "..", ".."))
RECOVERIES_DIR = os.path.join(REPO_ROOT, "recoveries")
QUEUE_FILE = os.path.join(REPO_ROOT, "WORK-QUEUE.md")
TSV_FILE = os.path.join(HERE, "recoveries-registry.tsv")
MD_FILE = os.path.join(HERE, "recoveries-registry.md")
MANIFEST_FILE = os.path.join(HERE, "manifest.json")

fails = []
checked = 0


def check(name, cond, detail=""):
    global checked
    checked += 1
    if cond:
        print("PASS", name)
    else:
        print("FAIL", name, detail)
        fails.append(name)


def own_extract():
    """Independent re-implementation of the extraction rules."""
    rows = []
    for dirpath, _d, files in os.walk(RECOVERIES_DIR):
        for name in sorted(files):
            full = os.path.join(dirpath, name)
            if not os.path.isfile(full):
                continue
            rel = os.path.relpath(full, RECOVERIES_DIR)
            h = hashlib.sha256()
            with open(full, "rb") as fh:
                for chunk in iter(lambda: fh.read(1024 * 1024), b""):
                    h.update(chunk)
            with open(QUEUE_FILE, "r", encoding="utf-8") as fh:
                txt = fh.read()
            rows.append({
                "rel_path": rel,
                "size_bytes": os.path.getsize(full),
                "sha256": h.hexdigest(),
                "q_hits": txt.count(rel),
            })
    rows.sort(key=lambda r: r["rel_path"])
    return rows


def read_tsv():
    with open(TSV_FILE, "r", encoding="utf-8") as fh:
        lines = fh.read().splitlines()
    header = lines[0].split("\t")
    assert header == ["path", "size_bytes", "sha256", "mtime_utc", "q_hits"], header
    out = []
    for ln in lines[1:]:
        p, s, h, m, q = ln.split("\t")
        out.append({"path": p, "size_bytes": int(s), "sha256": h,
                    "mtime_utc": m, "q_hits": int(q)})
    return out


def read_manifest():
    with open(MANIFEST_FILE, "r", encoding="utf-8") as fh:
        return json.load(fh)


def read_md():
    with open(MD_FILE, "r", encoding="utf-8") as fh:
        return fh.read()


def main():
    own = own_extract()
    committed = read_tsv()

    # 1) Fresh extraction must equal the committed TSV, row for row.
    ok = len(own) == len(committed)
    if ok:
        for a, b in zip(own, committed):
            if (a["rel_path"], a["size_bytes"], a["sha256"], a["q_hits"]) != (
                    b["path"], b["size_bytes"], b["sha256"], b["q_hits"]):
                ok = False
                break
    check("fresh extraction matches committed TSV (row order + values)",
          ok, "rows=%d committed=%d" % (len(own), len(committed)))

    # 2) Committed MD must contain a table with the same row count.
    md = read_md()
    check("committed MD exists and is non-empty", len(md) > 0)
    check("committed MD header row present",
          "| path | size_bytes | sha256 | mtime_utc | q_hits |" in md)
    data_rows = [ln for ln in md.splitlines() if ln.startswith("| `")]
    check("committed MD data-row count matches TSV",
          len(data_rows) == len(committed),
          "md_data_rows=%d tsv_rows=%d" % (len(data_rows), len(committed)))

    # 3) Manifest totals must agree with a direct directory walk.
    man = read_manifest()
    total = 0
    for dirpath, _d, files in os.walk(RECOVERIES_DIR):
        for name in files:
            total += os.path.getsize(os.path.join(dirpath, name))
    check("manifest.file_count == directory file count",
          man.get("file_count") == len(committed) == len(own))
    check("manifest.total_bytes == direct byte sum",
          man.get("total_bytes") == total, "manifest=%s direct=%d" % (man.get("total_bytes"), total))
    check("manifest.files_with_q_hits == recomputed",
          man.get("files_with_q_hits") == sum(1 for r in own if r["q_hits"] > 0))
    check("manifest.top_referenced == recomputed top 8",
          [r["rel_path"] for r in sorted(own, key=lambda x: -x["q_hits"])[:8]] ==
          [t["path"] for t in man.get("top_referenced", [])])

    print("----")
    if fails:
        print("CHECKS FAILED:", len(fails), fails)
        sys.exit(1)
    print("ALL CHECKS PASSED (%d checks)" % checked)
    sys.exit(0)


if __name__ == "__main__":
    main()
