#!/usr/bin/env python3
"""Verify bundled CARBON demo fixtures stay safe, reproducible, and selectable."""

from __future__ import annotations

import hashlib
import json
import subprocess
import tempfile
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "runtime" / "carbon" / "scripts" / "carbon_demo.py"
FIXTURES = ROOT / "runtime" / "carbon" / "demo-fixtures"
MANIFEST = FIXTURES / "manifest.json"
SKILL = ROOT / "skills" / "carbon-demo" / "SKILL.md"
SERVER = ROOT / "server" / "index.js"


def digest_tree(directory: Path) -> str:
    digest = hashlib.sha256()
    for path in sorted(item for item in directory.rglob("*") if item.is_file()):
        digest.update(path.relative_to(directory).as_posix().encode("utf-8"))
        digest.update(b"\0")
        digest.update(path.read_bytes())
        digest.update(b"\0")
    return digest.hexdigest()


def run(*args: str, expected: int = 0) -> dict[str, object]:
    result = subprocess.run(
        ["python3", str(SCRIPT), *args],
        check=False,
        capture_output=True,
        text=True,
    )
    assert result.returncode == expected, result.stderr or result.stdout
    if expected:
        return {"error": result.stderr.strip() or result.stdout.strip()}
    return json.loads(result.stdout)


def main() -> int:
    assert SCRIPT.is_file()
    assert MANIFEST.is_file()
    manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
    assert manifest["defaultFixture"] == "web-static"
    assert [fixture["id"] for fixture in manifest["fixtures"]] == [
        "web-static",
        "web-app",
        "api-server",
        "eval-runner",
        "large-project",
    ]
    assert {profile["id"] for profile in manifest["testProfiles"]} == {
        "without-existing-tests",
        "with-existing-tests",
    }
    for fixture in manifest["fixtures"]:
        fixture_root = FIXTURES / fixture["id"]
        assert fixture_root.is_dir(), fixture_root
        assert fixture["testPaths"], f"{fixture['id']} must declare the paths stripped for the clean profile"

    listed = run("list")
    assert listed["defaultFixture"] == "web-static"
    assert len(listed["fixtures"]) == 5
    assert {profile["id"] for profile in listed["testProfiles"]} == {
        "without-existing-tests",
        "with-existing-tests",
    }

    source_digest = digest_tree(FIXTURES)
    with tempfile.TemporaryDirectory(prefix="carbon-demo-fixture-contract-") as temporary:
        workspace = Path(temporary) / "workspace"
        workspace.mkdir()
        workspace = workspace.resolve()

        static_copy = run("create", "--root", str(workspace))
        static_root = Path(static_copy["destination"])
        assert static_root.parent == workspace
        assert static_root.name == "carbon-demo-web-static"
        assert static_copy["fixture"]["id"] == "web-static"
        assert static_copy["testProfile"] == "without-existing-tests"
        assert (static_root / "index.html").is_file()
        assert not (static_root / "tests").exists()
        descriptor = json.loads((static_root / ".carbon-demo.json").read_text(encoding="utf-8"))
        assert descriptor["fixture"]["id"] == "web-static"
        assert descriptor["testProfile"] == "without-existing-tests"
        assert "/carbon " in static_copy["next"]["carbon"]

        api_copy = run(
            "create",
            "--root", str(workspace),
            "--fixture", "api-server",
            "--test-profile", "with-existing-tests",
            "--destination", "api-with-tests",
        )
        api_root = Path(api_copy["destination"])
        assert (api_root / "src" / "server.js").is_file()
        assert (api_root / "test" / "integration.test.js").is_file()
        assert (api_root / "test" / "manual-api-boundaries.md").is_file()

        rejected_existing = run(
            "create", "--root", str(workspace), "--destination", "api-with-tests", expected=2
        )
        assert "already exists" in rejected_existing["error"]
        rejected_escape = run(
            "create", "--root", str(workspace), "--destination", "../escape", expected=2
        )
        assert "subdirectory" in rejected_escape["error"]

    assert digest_tree(FIXTURES) == source_digest, "demo provisioning changed a bundled source fixture"

    skill = SKILL.read_text(encoding="utf-8")
    for phrase in (
        "carbon_demo action=list",
        "carbon_demo action=create",
        "without-existing-tests",
        "with-existing-tests",
        "Run the main `/carbon` First Look",
    ):
        assert phrase in skill, f"demo skill is missing {phrase!r}"
    server = SERVER.read_text(encoding="utf-8")
    for phrase in ('name: "carbon_demo"', 'case "carbon_demo"', 'name: "carbon_demo", skill: "carbon-demo"'):
        assert phrase in server, f"server does not expose demo capability: {phrase!r}"

    print("PASS: five immutable bundled demo fixtures support safe clean-slate and existing-test copies, MCP discovery, and a from-scratch CARBON handoff.")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
