#!/usr/bin/env python3
"""Red-first driver: one reverted product mutation per cell.

Apply exactly one product mutation (refusing unless the anchor occurs exactly
once in the PRODUCT region), run the cells, record which failed and where, then
restore base+cells and verify the product region BY BLOB OID.
"""
import json
import pathlib
import re
import subprocess
import sys

HOME = pathlib.Path.home()
FILE = HOME / "spt-core-hertz-linux/crates/spt-daemon/src/bootstrap_firewall/linux.rs"
BASE = pathlib.Path("/tmp/linux.rs.fold")
CELLS = HOME / "cells.rs"
BASE_OID = "5c8e9d089726c258c4a33bc04bf9a624433c3a88"
MARKER = "\n#[cfg(test)]\nmod tests {"
FILTER = "test(/^bootstrap_firewall::linux::tests::/)"
MUTATIONS = json.loads((HOME / "mutations.json").read_text())
ONLY = set(sys.argv[1:])


def split(text):
    index = text.index(MARKER)
    return text[:index], text[index:]


def oid(data):
    return subprocess.run(["git", "hash-object", "--stdin"], input=data,
                          capture_output=True, text=True, check=True).stdout.strip()


def restore():
    FILE.write_text(BASE.read_text() + CELLS.read_text())
    seen = oid(split(FILE.read_text())[0])
    if seen != BASE_OID:
        sys.exit(f"FATAL: product region is {seen}, not {BASE_OID}")
    return seen


report = []
restore()
for label, cell, old, new in MUTATIONS:
    if ONLY and label not in ONLY:
        continue
    product, tests = split(FILE.read_text())
    count = product.count(old)
    if count != 1:
        report.append({"cell": cell, "mutation": label,
                       "error": f"anchor occurs {count} times in the product region; refusing"})
        continue
    FILE.write_text(product.replace(old, new) + tests)
    name = f"red-{label}"
    subprocess.run(["bash", str(HOME / "lane_run.sh"), name, FILTER], check=False)
    code = (HOME / "lane" / f"{name}.exit").read_text().strip()
    log = (HOME / "lane" / f"{name}.log").read_text()
    report.append({
        "cell": cell, "mutation": label, "old": old, "new": new,
        "producer_exit": code,
        "failed": sorted(set(re.findall(r"FAIL \[[^\]]*\] spt-daemon (\S+)", log))),
        "red_lines": sorted(set(re.findall(r"panicked at crates\S+linux\.rs:(\d+:\d+)", log))),
        "summary": [l.strip() for l in log.splitlines() if "tests run:" in l][-1:],
        "message": sorted(set(re.findall(r"panicked at [^\n]*\n *([^\n]+)", log)))[:2],
        "compile_errors": sorted(set(re.findall(r"^error(?:\[[^\]]+\])?: .*", log, re.M)))[:3],
        "restored_oid": None,
    })
    report[-1]["restored_oid"] = restore()

(HOME / "lane" / "red-report.json").write_text(json.dumps(report, indent=1))
for entry in report:
    print(entry.get("mutation"), "| exit", entry.get("producer_exit"),
          "|", entry.get("summary"), "|", entry.get("failed"),
          "| red", entry.get("red_lines"), "| oid", (entry.get("restored_oid") or "?")[:8],
          "|", entry.get("error", ""))
