"""Audit saved pagination responses; no network requests. Python 3 standard library.
Input is normalized capture metadata, not raw HTTP or an API response.
Run: python audit-pagination.py pagination-sample.json new-output-directory
"""
import csv, json, sys
from pathlib import Path
bundle = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
pages = {}
for page in bundle["pages"]:
    if page["url"] in pages: raise ValueError("duplicate saved page URL")
    pages[page["url"]] = page
url = bundle["start_url"]
visited, ids, rows, ledger, columns = set(), set(), [], [], []
while url is not None:
    if url in visited: raise ValueError("pagination loop: " + url)
    if url not in pages: raise ValueError("missing saved next page: " + url)
    page = pages[url]
    if page["status"] != 200: raise ValueError("unsuccessful page: " + url)
    records = page["records"]
    if not isinstance(records, list): raise ValueError("records must be an array")
    for row in records:
        if not isinstance(row, dict) or not isinstance(row.get("id"), str):
            raise ValueError("every record needs a string id")
        if row["id"] in ids: raise ValueError("duplicate record id: " + row["id"])
        ids.add(row["id"])
        for key in row:
            if key not in columns: columns.append(key)
        rows.append(row)
    ledger.append({"url":url, "records":len(records), "next_url":page["next_url"]})
    visited.add(url)
    url = page["next_url"]
if visited != set(pages): raise ValueError("unreachable saved pages")
out = Path(sys.argv[2]); out.mkdir(exist_ok=False)
def cell(value):
    if value is None: return ""
    if isinstance(value, (dict, list, bool)): return json.dumps(value, ensure_ascii=False)
    return str(value)
with (out/"records.csv").open("w",encoding="utf-8",newline="") as handle:
    writer=csv.writer(handle); writer.writerow(columns)
    writer.writerows([[cell(row.get(key)) for key in columns] for row in rows])
report={"pages":len(ledger),"received_records":len(rows),"unique_ids":len(ids),
        "columns":columns,"ended_without_next":True,"page_ledger":ledger,
        "scope":"saved chain only; not a snapshot or permission completeness guarantee"}
(out/"manifest.json").write_text(json.dumps(report,indent=2)+"\n",encoding="utf-8")
print(json.dumps(report))
