#!/usr/bin/env python3
"""Contract test for CARBON Browser v1 negotiation and evidence ledger."""

from __future__ import annotations

import json
import subprocess
import tempfile
from pathlib import Path


PLUGIN = Path(__file__).resolve().parents[1]
LAUNCHER = PLUGIN / "bin" / "carbon-runtime"
MANIFEST = PLUGIN / "runtime" / "carbon" / "references" / "browser" / "adapter-manifest.example.json"


def run(*args: str, ok: bool = True) -> subprocess.CompletedProcess[str]:
    result = subprocess.run([str(LAUNCHER), "browser", *args], text=True, capture_output=True, check=False)
    if ok and result.returncode:
        raise AssertionError(f"carbon-runtime browser {' '.join(args)} failed:\n{result.stderr}")
    if not ok and not result.returncode:
        raise AssertionError(f"carbon-runtime browser {' '.join(args)} unexpectedly succeeded")
    return result


spec = json.loads(run("contract").stdout)
if spec["protocol"] != "carbon-browser/v1" or "action.click" not in spec["operations"]["actions"]:
    raise AssertionError("machine-readable browser contract is incomplete")

validated = json.loads(run("validate-adapter", "--manifest", str(MANIFEST)).stdout)
if not validated["valid"] or validated["adapter"]["family"] != "host-agent":
    raise AssertionError(f"example adapter did not validate: {validated}")

accepted = json.loads(run(
    "negotiate", "--manifest", str(MANIFEST),
    "--require-operation", "action.click", "--require-evidence", "screenshot",
).stdout)
if not accepted["accepted"] or accepted["missing"]["operations"]:
    raise AssertionError("supported contract requirements were not accepted")

rejected = json.loads(run(
    "negotiate", "--manifest", str(MANIFEST),
    "--require-operation", "record.replay", "--require-evidence", "video",
).stdout)
if rejected["accepted"] or rejected["degradation"] != "blocked-or-explicitly-replan":
    raise AssertionError("missing adapter capabilities were silently accepted")

with tempfile.TemporaryDirectory(prefix="carbon-browser-") as temporary:
    root = Path(temporary)
    initialized = json.loads(run(
        "init", "--root", str(root), "--manifest", str(MANIFEST),
        "--target", "https://example.test", "--require-operation", "page.open",
        "--require-evidence", "screenshot",
    ).stdout)
    session_dir = Path(initialized["sessionDir"])
    sid = initialized["session"]["sessionId"]
    result_path = root / "result.json"
    result_path.write_text(json.dumps({
        "protocol": "carbon-browser/v1",
        "requestId": "REQ-0001",
        "sessionId": sid,
        "adapter": {"id": "host-agent.local-browser", "version": "1.0.0"},
        "operation": "page.open",
        "status": "succeeded",
        "actual": "Loaded with Bearer abcdefghijklmnopqrstuvwxyz123",
        "startedAt": "2026-08-01T18:00:00Z",
        "finishedAt": "2026-08-01T18:00:02Z",
        "before": {"url": "about:blank"},
        "after": {"url": "https://example.test", "password": "private"},
        "evidence": [{"kind": "screenshot", "handle": "evidence/home.png"}],
        "unavailableEvidence": ["video"],
    }), encoding="utf-8")
    recorded = json.loads(run("record", "--session-dir", str(session_dir), "--result", str(result_path)).stdout)
    if not recorded["recorded"] or recorded["summary"]["operationCounts"]["succeeded"] != 1:
        raise AssertionError("valid operation was not recorded")
    ledger = (session_dir / "operations.jsonl").read_text(encoding="utf-8")
    if "abcdefghijklmnopqrstuvwxyz123" in ledger or "private" in ledger:
        raise AssertionError("browser operation ledger retained a secret")
    summary = json.loads(run("summary", "--session-dir", str(session_dir)).stdout)
    if summary["operations"] != 1 or len(summary["ledgerSha256"]) != 64:
        raise AssertionError("browser session summary is incomplete")

    bad = root / "bad.json"
    bad.write_text(json.dumps({"protocol": "carbon-browser/v1", "sessionId": sid}), encoding="utf-8")
    failure = run("record", "--session-dir", str(session_dir), "--result", str(bad), ok=False)
    if "Invalid CARBON Browser result" not in failure.stderr:
        raise AssertionError("invalid operation envelope did not fail closed")

print("PASS: carbon-browser/v1 contract, adapter negotiation, explicit capability gaps, redaction, and durable operation ledger verified.")
