#!/usr/bin/env python3
"""Constructed illustration: schema-valid JSON is not a correct task edit.

Not a recreation of any vendor system, not an agent benchmark, and not
evidence of performance improvement. Synthetic records only. No network.
"""

from __future__ import annotations

import json
import platform
import sys
from copy import deepcopy
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

HERE = Path(__file__).resolve().parent
FIXTURE_FILE = HERE / "fixture.json"
RESULT_FILE = HERE / "observed-result.json"

REQUIRED_PROPOSAL_KEYS = ("task_id", "expected_revision", "set")


def utc_now() -> str:
    return datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")


def load_fixture() -> dict[str, Any]:
    return json.loads(FIXTURE_FILE.read_text(encoding="utf-8"))


def fingerprint(tasks: dict[str, Any], log: list[Any]) -> str:
    return json.dumps({"tasks": tasks, "log": log}, sort_keys=True, ensure_ascii=True)


def schema_check(proposal: Any, policy: dict[str, Any]) -> tuple[str, str]:
    if not isinstance(proposal, dict):
        return "fail", "proposal is not an object"
    missing = [key for key in REQUIRED_PROPOSAL_KEYS if key not in proposal]
    if missing:
        return "fail", f"missing keys: {', '.join(missing)}"
    if not isinstance(proposal["task_id"], str) or not proposal["task_id"]:
        return "fail", "task_id must be a non-empty string"
    revision = proposal["expected_revision"]
    if isinstance(revision, bool) or not isinstance(revision, int):
        return "fail", "expected_revision must be an int"
    fields = proposal["set"]
    if not isinstance(fields, dict) or not fields:
        return "fail", "set must be a non-empty object"
    allowed = set(policy["mutable_fields"])
    unknown = [key for key in fields if key not in allowed]
    if unknown:
        return "fail", f"unknown fields: {', '.join(unknown)}"
    if "status" in fields:
        status = fields["status"]
        if status not in policy["allowed_statuses"]:
            return "fail", "status not in allowlist"
    if "title" in fields:
        title = fields["title"]
        if not isinstance(title, str) or not title.strip():
            return "fail", "title must be a non-empty string"
    notice = proposal.get("record_notice")
    if notice is not None:
        if not isinstance(notice, dict):
            return "fail", "record_notice must be an object"
        if not isinstance(notice.get("id"), str) or not notice["id"]:
            return "fail", "record_notice.id must be a non-empty string"
        if not isinstance(notice.get("kind"), str) or not notice["kind"]:
            return "fail", "record_notice.kind must be a non-empty string"
    return "pass", "schema ok"


def policy_check(proposal: dict[str, Any], tasks: dict[str, Any], policy: dict[str, Any]) -> tuple[str, str]:
    task_id = proposal["task_id"]
    task = tasks.get(task_id)
    if task is None:
        return "reject", "unknown task"
    if task["project"] != policy["allowed_project"]:
        return "reject", "outside allowed project"
    if proposal["expected_revision"] != task["revision"]:
        return "reject", (
            f"stale revision (expected {proposal['expected_revision']}, "
            f"current {task['revision']})"
        )
    return "pass", "policy ok"


def apply_update(
    proposal: dict[str, Any],
    tasks: dict[str, Any],
    history: list[dict[str, Any]],
    log: list[dict[str, Any]],
    case_id: str,
) -> str:
    task_id = proposal["task_id"]
    before = deepcopy(tasks[task_id])
    updated = deepcopy(before)
    updated.update(proposal["set"])
    updated["revision"] = before["revision"] + 1
    tasks[task_id] = updated
    history.append({"case_id": case_id, "task_id": task_id, "before": before})
    notice = proposal.get("record_notice")
    if notice:
        log.append(
            {
                "id": notice["id"],
                "kind": notice["kind"],
                "summary": notice.get("summary", ""),
                "recorded_by_case": case_id,
                "dispatched": True,
                "recallable_by_local_restore": False,
            }
        )
        return "yes (task + irreversible notice marker)"
    return "yes"


def revert_last(
    tasks: dict[str, Any],
    history: list[dict[str, Any]],
    log: list[dict[str, Any]],
) -> tuple[str, str, str]:
    if not history:
        return "n/a", "reject: no recorded prior state", "no"
    entry = history.pop()
    tasks[entry["task_id"]] = deepcopy(entry["before"])
    remaining = len(log)
    policy = (
        "pass: restored from history; "
        f"{remaining} irreversible notice marker(s) remain"
    )
    changed = "local restored; external notice not recalled"
    return "n/a", policy, changed


def run_cases(fixture: dict[str, Any]) -> tuple[list[dict[str, Any]], dict[str, Any]]:
    policy = fixture["policy"]
    tasks = deepcopy(fixture["tasks"])
    history: list[dict[str, Any]] = []
    log: list[dict[str, Any]] = []
    rows: list[dict[str, Any]] = []

    for case in fixture["cases"]:
        case_id = case["id"]
        before = fingerprint(tasks, log)

        if case.get("op") == "revert":
            schema, policy_result, changed = revert_last(tasks, history, log)
            after = fingerprint(tasks, log)
            rows.append(
                {
                    "id": case_id,
                    "label": case["label"],
                    "schema": schema,
                    "policy": policy_result,
                    "changed": changed,
                    "mutated": before != after,
                }
            )
            continue

        if "raw" in case:
            try:
                json.loads(case["raw"])
            except json.JSONDecodeError:
                after = fingerprint(tasks, log)
                rows.append(
                    {
                        "id": case_id,
                        "label": case["label"],
                        "schema": "fail",
                        "policy": "skipped",
                        "changed": "no",
                        "mutated": before != after,
                    }
                )
                continue
            proposal = json.loads(case["raw"])
        else:
            proposal = case["proposal"]

        schema, schema_reason = schema_check(proposal, policy)
        if schema != "pass":
            after = fingerprint(tasks, log)
            rows.append(
                {
                    "id": case_id,
                    "label": case["label"],
                    "schema": "fail",
                    "policy": f"skipped ({schema_reason})",
                    "changed": "no",
                    "mutated": before != after,
                }
            )
            continue

        policy_result, policy_reason = policy_check(proposal, tasks, policy)
        if policy_result != "pass":
            after = fingerprint(tasks, log)
            rows.append(
                {
                    "id": case_id,
                    "label": case["label"],
                    "schema": "pass",
                    "policy": f"reject: {policy_reason}",
                    "changed": "no",
                    "mutated": before != after,
                }
            )
            continue

        changed = apply_update(proposal, tasks, history, log, case_id)
        after = fingerprint(tasks, log)
        rows.append(
            {
                "id": case_id,
                "label": case["label"],
                "schema": "pass",
                "policy": "pass",
                "changed": changed,
                "mutated": before != after,
            }
        )

    final_state = {"tasks": tasks, "history": history, "irreversible_log": log}
    return rows, final_state


def assert_final(fixture: dict[str, Any], final_state: dict[str, Any], rows: list[dict[str, Any]]) -> list[str]:
    errors: list[str] = []
    expected_tasks = fixture["tasks"]
    if final_state["tasks"] != expected_tasks:
        errors.append("final tasks must match the fixture after revert")
    if final_state["history"]:
        errors.append("history must be empty after revert")

    log = final_state["irreversible_log"]
    if len(log) != 1:
        errors.append(f"expected one irreversible notice marker, got {len(log)}")
    elif log[0].get("id") != "notice-sidebar-draft":
        errors.append("irreversible marker id mismatch")
    elif log[0].get("dispatched") is not True:
        errors.append("notice must remain marked dispatched")
    elif log[0].get("recallable_by_local_restore") is not False:
        errors.append("notice must not be recallable by local restore")

    by_id = {row["id"]: row for row in rows}
    expected_flags = {
        "a-in-scope-update": True,
        "b-out-of-project": False,
        "c-stale-revision": False,
        "d-malformed": False,
        "e-revert-local": True,
    }
    for case_id, should_mutate in expected_flags.items():
        row = by_id.get(case_id)
        if row is None:
            errors.append(f"missing case {case_id}")
        elif row["mutated"] is not should_mutate:
            errors.append(f"{case_id} mutated={row['mutated']}, expected {should_mutate}")

    if by_id.get("b-out-of-project", {}).get("schema") != "pass":
        errors.append("out-of-project case must be schema-valid")
    if not str(by_id.get("b-out-of-project", {}).get("policy", "")).startswith("reject:"):
        errors.append("out-of-project case must be policy-rejected")
    if by_id.get("d-malformed", {}).get("schema") != "fail":
        errors.append("malformed case must fail schema")
    return errors


def print_table(rows: list[dict[str, Any]]) -> None:
    headers = ("case", "schema", "policy", "changed")
    table = [
        (row["id"], row["schema"], row["policy"], row["changed"])
        for row in rows
    ]
    widths = [len(header) for header in headers]
    for line in table:
        for index, cell in enumerate(line):
            widths[index] = max(widths[index], len(cell))

    def fmt(cells: tuple[str, ...]) -> str:
        return "  ".join(cell.ljust(widths[index]) for index, cell in enumerate(cells))

    print(fmt(headers))
    print("  ".join("-" * width for width in widths))
    for line in table:
        print(fmt(line))


def main() -> int:
    fixture = load_fixture()
    rows, final_state = run_cases(fixture)
    errors = assert_final(fixture, final_state, rows)

    print_table(rows)
    print()
    print("final tasks:", json.dumps(final_state["tasks"], sort_keys=True, ensure_ascii=True))
    print("irreversible_log:", json.dumps(final_state["irreversible_log"], sort_keys=True, ensure_ascii=True))
    print("assertions_passed:", not errors)
    if errors:
        for item in errors:
            print("assertion_error:", item)

    result = {
        "ran_at": utc_now(),
        "python_version": platform.python_version(),
        "command": "python3 demo.py",
        "kind": "constructed_illustration",
        "talk_context": {
            "video_id": "xxfMT-bPEmU",
            "role": "reporting question only; this demo is not a recreation",
        },
        "point": fixture["meta"]["point"],
        "not": fixture["meta"]["not"],
        "cases": [
            {
                "id": row["id"],
                "label": row["label"],
                "schema": row["schema"],
                "policy": row["policy"],
                "changed": row["changed"],
            }
            for row in rows
        ],
        "final_state": {
            "tasks": final_state["tasks"],
            "irreversible_log": final_state["irreversible_log"],
            "history_length": len(final_state["history"]),
        },
        "assertions_passed": not errors,
        "assertion_errors": errors,
        "limits": [
            "Synthetic task records and in-process JSON only.",
            "No network, mail, APIs, or filesystem writes except observed-result.json.",
            "The outbound notice is a local marker; nothing was sent.",
            "Local restore cannot recall a dispatched external side effect.",
            "Not a recreation of the talk's system.",
            "Not an agent benchmark and not evidence of performance improvement.",
            "Five cases only; counts are not a quality score.",
        ],
    }
    RESULT_FILE.write_text(json.dumps(result, indent=2, ensure_ascii=True) + "\n", encoding="utf-8")
    print("wrote:", RESULT_FILE.name)
    return 1 if errors else 0


if __name__ == "__main__":
    sys.exit(main())
