#!/usr/bin/env python3
"""Layer 1 of the install-confidence ladder: clean-room boot smoke.

Simulates a fresh-machine install *without* a second machine. It:

1. Stages the app bundle exactly as Xcode does, via
   ``scripts/copy_backend_bundle.sh`` into a throwaway temp dir.
2. Launches a child Python whose working directory is that staged bundle, with
   a throwaway ``$HOME`` and the repo root kept OFF ``sys.path``. So if a
   first-party module was never bundled, the import fails here — just like it
   would on a clean machine — instead of silently resolving to the repo copy.
3. Builds the real FastAPI app (``mugi_backend._build_app``) and asserts the
   route graph wired up (e.g. ``/setup/status`` is present) to prove the whole
   import chain succeeded.

Building ``_build_app`` imports every route module, so a missing bundled file
surfaces as a real traceback you can read — the diagnostic that was missing. We
deliberately do NOT fire a live request: that triggers the app's startup hooks
(first-run/network work under a fresh ``$HOME``) which can block and is out of
scope for a *bundle completeness* smoke.

Usage:
    python scripts/clean_room_boot_check.py [--keep]

Exit code 0 + "CLEANROOM_OK" on success; non-zero with the child's traceback on
failure. Third-party deps resolve from the current interpreter's environment
(the same interpreter you invoke this with); only first-party completeness is
isolated.
"""

from __future__ import annotations

import argparse
import os
import shutil
import subprocess
import sys
import tempfile
import textwrap

REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BUNDLE_SCRIPT = os.path.join(REPO_ROOT, "scripts", "copy_backend_bundle.sh")

# Runs inside the staged bundle dir with a clean sys.path. Mirrors the supported
# TestClient construction used across tests/test_mlx_status_route.py et al.
_CHILD_PROGRAM = textwrap.dedent(
    """
    import os, sys
    os.environ.setdefault("MUGI_SKIP_BACKEND_BOOTSTRAP", "1")

    from queue import Queue
    from activity_bus import ActivityBus
    from backend.event_buses import ChatEventBus
    from live_view_events import LiveViewEventBus
    import mugi_backend

    # Prove we imported the STAGED bundle, not the dev repo. cwd is the staged
    # Backend dir; if mugi_backend resolved elsewhere, isolation failed and the
    # smoke would be meaningless.
    here = os.path.realpath(os.getcwd())
    mod = os.path.realpath(mugi_backend.__file__)
    assert mod.startswith(here), f"isolation leak: imported {mod} not under {here}"

    class _Delegate:
        def __init__(self):
            self._main_thread_queue = Queue()
            self._live_view_event_bus = LiveViewEventBus()
            self._activity_bus = ActivityBus()
            self._http_port = 8342
            self._plugin_manager = None
            self._plugin_route_mount_errors = {}
            self._mesh_manager = None

    # Building the app imports every route module (the real completeness proof).
    app = mugi_backend._build_app(_Delegate(), ChatEventBus(), "<html></html>", "tok")

    paths = {getattr(r, "path", None) for r in app.routes}
    for required in ("/setup/status", "/preferences/mlx/status"):
        assert required in paths, f"route not wired after clean-room build: {required}"

    print("CLEANROOM_OK", mod)
    """
).strip()


def _stage_bundle(dest: str) -> None:
    subprocess.run(["bash", BUNDLE_SCRIPT, REPO_ROOT, dest], check=True)


def run_clean_room_boot(*, keep: bool = False) -> int:
    if not os.path.isfile(BUNDLE_SCRIPT):
        print(f"FAIL: bundle script not found: {BUNDLE_SCRIPT}", file=sys.stderr)
        return 2

    tmp = tempfile.mkdtemp(prefix="mugi_cleanroom_")
    dest = os.path.join(tmp, "Backend")
    home = os.path.join(tmp, "home")
    os.makedirs(home, exist_ok=True)
    try:
        print(f"[clean-room] staging bundle -> {dest}")
        _stage_bundle(dest)

        # Child env: fresh HOME, repo kept off the path, no user site-packages.
        env = dict(os.environ)
        env["HOME"] = home
        env["MUGI_SKIP_BACKEND_BOOTSTRAP"] = "1"
        env["PYTHONNOUSERSITE"] = "1"
        env.pop("PYTHONPATH", None)

        print("[clean-room] building staged backend app (route-graph import)")
        proc = subprocess.run(
            [sys.executable, "-c", _CHILD_PROGRAM],
            cwd=dest,
            env=env,
            capture_output=True,
            text=True,
            timeout=300,
        )
        if proc.stdout.strip():
            print(proc.stdout.rstrip())
        if proc.returncode != 0 or "CLEANROOM_OK" not in proc.stdout:
            print("FAIL: clean-room boot did not succeed.", file=sys.stderr)
            if proc.stderr.strip():
                print("--- child stderr ---", file=sys.stderr)
                print(proc.stderr.rstrip(), file=sys.stderr)
            return 1
        print("PASS: staged bundle imports cleanly and wires its route graph.")
        return 0
    finally:
        if keep:
            print(f"[clean-room] kept staging dir: {tmp}")
        else:
            shutil.rmtree(tmp, ignore_errors=True)


def main() -> int:
    parser = argparse.ArgumentParser(description="Clean-room bundle boot smoke.")
    parser.add_argument(
        "--keep",
        action="store_true",
        help="keep the temp staging dir for inspection",
    )
    args = parser.parse_args()
    return run_clean_room_boot(keep=args.keep)


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