from datetime import date
from hashlib import sha256
import json
from pathlib import Path
import sys

root = Path(__file__).parent.resolve()
key = sys.argv[1]
as_of = date.fromisoformat(sys.argv[2]) if len(sys.argv) > 2 else date.today()


def load(path):
    value = json.loads(path.read_text(encoding="utf-8"))
    if not isinstance(value, dict):
        raise SystemExit(f"FAIL: {path} must contain a JSON object")
    return value


def local(relative):
    path = (root / relative).resolve()
    if not path.is_relative_to(root) or not path.is_file():
        raise SystemExit(f"FAIL: unsafe or missing path: {relative}")
    return path


def day(record, field):
    try:
        return date.fromisoformat(record[field])
    except (KeyError, TypeError, ValueError):
        raise SystemExit(f"FAIL: {record.get('id')}: {field} must be YYYY-MM-DD")


records = {}
for record_path in sorted((root / "records").glob("*.json")):
    record = load(record_path)
    record_id = record.get("id")
    if not isinstance(record_id, str) or not record_id or record_id in records:
        raise SystemExit("FAIL: every record needs a unique non-empty id")
    record["_path"] = record_path.resolve()
    records[record_id] = record

for record_id, record in records.items():
    if record.get("status") not in {"current", "superseded"}:
        raise SystemExit(f"FAIL: {record_id}: invalid status")
    source = local(record.get("durable_source", ""))
    if sha256(source.read_bytes()).hexdigest() != record.get("source_sha256"):
        raise SystemExit(f"FAIL: {record_id}: durable source hash changed")
    if day(record, "review_on") >= day(record, "expires_on"):
        raise SystemExit(f"FAIL: {record_id}: review_on must precede expires_on")

    replacement = record.get("superseded_by")
    predecessor = record.get("supersedes")
    if record["status"] == "superseded":
        if replacement == record_id:
            raise SystemExit(f"FAIL: {record_id}: superseded_by cannot be a self-link")
        if replacement not in records:
            raise SystemExit(f"FAIL: {record_id}: superseded_by does not resolve")
    elif replacement is not None:
        raise SystemExit(f"FAIL: {record_id}: current record cannot declare superseded_by")
    if predecessor is not None:
        if predecessor == record_id:
            raise SystemExit(f"FAIL: {record_id}: supersedes cannot be a self-link")
        if predecessor not in records:
            raise SystemExit(f"FAIL: {record_id}: supersedes does not resolve")

for start_id in records:
    seen = set()
    cursor = start_id
    while records[cursor]["status"] == "superseded":
        if cursor in seen:
            raise SystemExit(f"FAIL: {start_id}: supersession cycle detected")
        seen.add(cursor)
        cursor = records[cursor]["superseded_by"]

for record_id, record in records.items():
    if record["status"] == "superseded":
        replacement_id = record["superseded_by"]
        if records[replacement_id].get("supersedes") != record_id:
            raise SystemExit(
                f"FAIL: {record_id} -> {replacement_id}: reverse link does not agree"
            )
    predecessor_id = record.get("supersedes")
    if predecessor_id is not None:
        predecessor = records[predecessor_id]
        if predecessor["status"] != "superseded":
            raise SystemExit(f"FAIL: {record_id}: supersedes must identify a superseded record")
        if predecessor.get("superseded_by") != record_id:
            raise SystemExit(
                f"FAIL: {record_id} -> {predecessor_id}: forward link does not agree"
            )

index = load(local("index.json"))
entry = next((item for item in index["entries"] if item["key"] == key), None)
if entry is None:
    raise SystemExit(f"FAIL: no pointer matches {key}")
record_path = local(entry["target"])
if sha256(record_path.read_bytes()).hexdigest() != entry["record_sha256"]:
    raise SystemExit("FAIL: record hash changed")
record = records.get(entry["record_id"])
if record is None or record_path != record["_path"] or record["status"] != "current":
    raise SystemExit("FAIL: pointer does not resolve to the current record")
review_on = day(record, "review_on")
expires_on = day(record, "expires_on")
if as_of >= expires_on:
    raise SystemExit(f"FAIL: record expired on {expires_on}")
if as_of >= review_on:
    raise SystemExit(f"FAIL: review due on {review_on}")

source = local(record["durable_source"])
instruction = next(
    line.strip() for line in source.read_text(encoding="utf-8").splitlines()
    if line.strip() and not line.lstrip().startswith("#")
)
print(f"PASS key={key}")
print("PASS supersession links are reciprocal, non-self, and acyclic")
print(f"source={record['durable_source']}")
print(f"instruction={instruction}")
print(f"verified={record['last_verified']}")
print(f"review_on={record['review_on']}")
print(f"expires_on={record['expires_on']}")
