"""Measure literal file reuse, with and without harness-namespace renaming.

Read-only analysis. Prints JSON to stdout. No comments, whitespace, numbers,
addresses, identifiers outside namespace prefixes, or proof steps are removed.
"""
import argparse
import hashlib
import json
import re
from collections import defaultdict
from pathlib import Path

p = argparse.ArgumentParser()
p.add_argument("root", type=Path)
p.add_argument("library", default="simdjson", nargs="?")
args = p.parse_args()
prefix = args.root / "proofs" / args.library
entries = sorted(d for d in prefix.iterdir() if d.is_dir() and (d / "lib").is_dir())
groups = {"exact": defaultdict(list), "namespace_only": defaultdict(list)}
totals = defaultdict(int)
for entry in entries:
    for path in sorted((entry / "lib").rglob("*.v")):
        raw = path.read_bytes()
        normalized = raw
        for ns in ("OssFuzzTheorems.Proofs.", "OssFuzzTheorems."):
            old = (ns + args.library + "." + entry.name).encode()
            normalized = re.sub(re.escape(old) + rb"(?=\.|[^A-Za-z0-9_]|$)",
                                (ns + args.library + ".ENTRY").encode(), normalized)
        for mode, data in (("exact", raw), ("namespace_only", normalized)):
            digest = hashlib.sha256(data).hexdigest()
            groups[mode][digest].append((entry.name, str(path.relative_to(args.root)), len(data)))
            totals[mode] += len(data)

result = {"library": args.library, "entries": [e.name for e in entries],
          "scope": "all .v files under each lib/; no generated-file exclusions",
          "normalization": "only the current harness's two fully qualified namespace prefixes"}
for mode, buckets in groups.items():
    shared = [g for g in buckets.values() if len({r[0] for r in g}) >= 2]
    all_files = sum(len(g) for g in buckets.values())
    shared_bytes = sum(sum(r[2] for r in g) for g in shared)
    # Only deduplicate groups present in multiple entry points, not local-only groups.
    savings = sum(sum(r[2] for r in g) - g[0][2] for g in shared)
    result[mode] = {"files": all_files, "bytes": totals[mode],
                    "cross_entry_groups": len(shared),
                    "files_in_cross_entry_groups": sum(len(g) for g in shared),
                    "bytes_in_cross_entry_groups": shared_bytes,
                    "bytes_in_cross_entry_groups_percent": round(100*shared_bytes/totals[mode], 4),
                    "cross_entry_dedup_savings_bytes": savings,
                    "cross_entry_dedup_savings_percent": round(100*savings/totals[mode], 4),
                    "largest_shared_groups": [
                       {"bytes_per_file": g[0][2], "entries": sorted({r[0] for r in g}),
                        "paths": [r[1] for r in g]}
                       for g in sorted(shared, key=lambda g: sum(r[2] for r in g), reverse=True)[:5]]}
print(json.dumps(result, ensure_ascii=False, indent=2))
