"""Drive the wire-parity check end-to-end.

1. Boot the FastAPI fixture app via uvicorn on a free port.
2. Poll /openapi.json until the server is up.
3. Run the Rust `drive_kernel` binary (raw kernel calls) against it.
4. Run the Rust `drive_emitted` binary (typed codegen functions) against
   the same server.
5. Tear the server down.

Either non-zero driver exit propagates as the script's exit code.
"""

from __future__ import annotations

import os
import socket
import subprocess
import sys
import time
import urllib.error
import urllib.request
from pathlib import Path


REPO_ROOT = Path(__file__).resolve().parents[2]
AFI_DIR = REPO_ROOT / "tests" / "afi"
RUST_DIR = REPO_ROOT / "tests" / "rust"
BOOT_TIMEOUT_S = 15.0
POLL_INTERVAL_S = 0.25


def pick_free_port() -> int:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(("127.0.0.1", 0))
        return s.getsockname()[1]


def wait_for_server(port: int, timeout_s: float) -> bool:
    deadline = time.monotonic() + timeout_s
    url = f"http://127.0.0.1:{port}/openapi.json"
    while time.monotonic() < deadline:
        try:
            with urllib.request.urlopen(url, timeout=1.0) as resp:
                if resp.status == 200:
                    return True
        except (urllib.error.URLError, ConnectionError, OSError) as e:
            # Surface the kind of failure so a stuck boot doesn't read
            # as "silently waiting"; the loop continues until timeout.
            sys.stderr.write(f"[wire_parity] waiting for server: {type(e).__name__}\n")
        time.sleep(POLL_INTERVAL_S)
    return False


def run_driver(name: str, base_url: str) -> int:
    sys.stdout.write(f"\n=== {name} ===\n")
    sys.stdout.flush()
    return subprocess.run(
        ["cargo", "run", "--quiet", "--bin", name, "--", base_url],
        cwd=RUST_DIR,
    ).returncode


def main() -> int:
    port = pick_free_port()
    base_url = f"http://127.0.0.1:{port}/api/mizan"

    server = subprocess.Popen(
        ["uv", "run", "uvicorn", "fastapi_app:make_app",
         "--factory", "--port", str(port), "--log-level", "warning"],
        cwd=AFI_DIR,
        stdout=subprocess.DEVNULL,
        stderr=subprocess.PIPE,
    )

    try:
        if not wait_for_server(port, BOOT_TIMEOUT_S):
            sys.stderr.write(
                f"[wire_parity] server failed to start within {BOOT_TIMEOUT_S}s\n",
            )
            stderr_tail = server.stderr.read(4096) if server.stderr else b""
            if stderr_tail:
                sys.stderr.write(stderr_tail.decode("utf-8", errors="replace"))
            return 1

        failures = 0
        for driver in ("drive_kernel", "drive_emitted"):
            rc = run_driver(driver, base_url)
            if rc != 0:
                sys.stderr.write(f"[wire_parity] {driver} exited {rc}\n")
                failures += 1

        return 0 if failures == 0 else 1
    finally:
        server.terminate()
        try:
            server.wait(timeout=3)
        except subprocess.TimeoutExpired:
            server.kill()
            server.wait()


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