"""Compare three native failure policies with one worker slot."""

import argparse
import json
import os
import subprocess
import shutil
import sys
from pathlib import Path

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--chio", type=Path, default=Path("chio"))
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
args.chio = Path(shutil.which(str(args.chio)) or str(args.chio)).resolve(strict=True)
os.umask(0o077)
root = args.output.resolve()
root.mkdir(mode=0o700)
here = Path(__file__).resolve().parent
reports = {}
for policy in ["stop", "continue_independent", "supervised"]:
    directory = root / policy
    directory.mkdir(mode=0o700)
    (directory / "policy.yaml").write_text(
        """kernel:
  max_capability_ttl: 3600
  delegation_depth_limit: 2
  durable_admission_mode: all
capabilities:
  default:
    tools:
      - server: chio-ipc
        tool: '*'
        operations: [invoke, delegate]
        ttl: 3600
      - server: chio-process
        tool: '*'
        operations: [invoke, delegate]
        ttl: 3600
"""
    )
    config = {
        "schema": "chio.process.host.v1",
        "policy": str(directory / "policy.yaml"),
        "mailboxes": [{"id": "jobs"}],
        "limits": {"max_processes": 5, "max_depth": 2, "max_calls": 32},
    }

    def worker(process, mode, depends=None):
        return {
            "process": process,
            "command": [sys.executable, str(here / "supervision-worker.py")],
            "cwd": str(here),
            "input": {"mode": mode},
            "depends_on": depends or [],
            "max_attempts": 1,
            "max_suspensions": 4,
            "timeout_seconds": 30,
        }

    plan = {
        "schema": "chio.process.run.v1",
        "max_parallel": 1,
        "failure_policy": policy,
    }
    if policy == "supervised":
        config.update(
            supervised_children=True,
            spawn_templates=[
                {
                    "id": "reader",
                    "tools": [{"server_id": "chio-ipc", "tool_name": "send_jobs"}],
                    "max_budget_share_bps": 3000,
                }
            ],
        )
        plan["workers"] = [worker("root", "parent")]
        template = worker("unused", "fail")
        template.pop("process")
        template.pop("depends_on")
        plan["templates"] = [{"id": "reader", **template}]
    else:
        config["children"] = [
            {
                "id": role,
                "parent": "root",
                "budget_share_bps": 3000,
                "tools": [{"server_id": "chio-ipc", "tool_name": "send_jobs"}],
            }
            for role in ["producer", "consumer", "inventory"]
        ]
        plan["workers"] = [
            worker("producer", "fail"),
            worker("consumer", "pass", ["producer"]),
            worker("inventory", "pass"),
        ]
    for name, value in [("host.json", config), ("plan.json", plan)]:
        (directory / name).write_text(json.dumps(value))
    subprocess.run(
        [
            str(args.chio),
            "process",
            "init",
            "--state",
            str(directory / "host"),
            "--config",
            str(directory / "host.json"),
        ],
        check=True,
        capture_output=True,
    )
    command = [
        str(args.chio),
        "process",
        "run",
        "--state",
        str(directory / "host"),
        "--plan",
        str(directory / "plan.json"),
    ]
    result = subprocess.run(command, text=True, capture_output=True, timeout=120)
    report = json.loads(result.stdout)
    assert report["complete"] == (policy == "supervised"), result.stderr
    if policy == "continue_independent":
        workers = {worker["process"]: worker for worker in report["workers"]}
        assert workers["consumer"]["outcome"] == "dependency_failed"
        assert workers["consumer"]["attempts"] == 0
        assert workers["inventory"]["state"] == "completed"
    if policy == "supervised":
        assert report["handled_failures"] and not report["unhandled_failures"]
        replay = subprocess.run(command, text=True, capture_output=True, timeout=120)
        assert json.loads(replay.stdout) == report
    reports[policy] = report
(root / "reports.json").write_text(json.dumps(reports, indent=2) + "\n")
print(json.dumps(reports, indent=2))
