#!/usr/bin/env python3
"""Self-realize praxis-stack white-paper architecture on this machine.

Cross-OS (Windows / macOS / Linux) and cross-harness (claude / codex / grok / all).
Tier 0 = skills only (valid). Tier 1 = optional HTTP backend stub on :8080.

  py -3 realize.py --harness all --tier 0
  python3 realize.py --harness grok --tier 1 --backend-dir ./praxis-backend
"""
from __future__ import annotations

import argparse
import json
import os
import platform
import shutil
import ssl
import sys
import tempfile
import urllib.request
import zipfile
from datetime import datetime, timezone
from pathlib import Path

DEFAULT_PACKAGE_URL = "https://praxis-stack.pages.dev/pkg/praxis-stack-skills.zip"
DEFAULT_STUB_URL = "https://praxis-stack.pages.dev/scripts/backend_stub.py"
SKILL_NAMES = ("megapraxis", "metamegapraxis", "praxis-local-realize")

HARNESS_ROOTS = {
    "claude": Path.home() / ".claude" / "skills",
    "codex": Path.home() / ".codex" / "skills",
    "grok": Path.home() / ".grok" / "skills",
}


def os_token() -> str:
    s = platform.system().lower()
    if s.startswith("darwin"):
        return "darwin"
    if s.startswith("windows"):
        return "windows"
    if s.startswith("linux"):
        return "linux"
    return s or "unknown"


def py_cmd_hint() -> str:
    return "py -3" if os.name == "nt" else "python3"


def find_package_skills(source: Path | None) -> Path | None:
    """Return directory that contains megapraxis/SKILL.md."""
    candidates: list[Path] = []
    if source:
        candidates.append(source)
    here = Path(__file__).resolve()
    candidates.extend(
        [
            here.parents[1],  # skill root …/praxis-local-realize
            here.parents[2] / "praxis" / "skills" if len(here.parents) > 2 else here,
            Path.cwd() / "praxis" / "skills",
            Path.cwd() / "praxis-stack" / "praxis" / "skills",
            Path.cwd() / ".praxis-realize" / "pkg" / "praxis" / "skills",
        ]
    )
    # package root layout: <root>/praxis/skills
    for c in list(candidates):
        if c is None:
            continue
        if (c / "megapraxis" / "SKILL.md").is_file():
            return c
        if (c / "praxis" / "skills" / "megapraxis" / "SKILL.md").is_file():
            return c / "praxis" / "skills"
        if (c / "skills" / "megapraxis" / "SKILL.md").is_file():
            return c / "skills"
    # live install sibling
    live = Path.home() / ".claude" / "skills"
    if (live / "megapraxis" / "SKILL.md").is_file():
        return live
    return None


def download(url: str, dest: Path) -> None:
    dest.parent.mkdir(parents=True, exist_ok=True)
    ctx = ssl.create_default_context()
    req = urllib.request.Request(url, headers={"User-Agent": "praxis-local-realize/1.5"})
    with urllib.request.urlopen(req, context=ctx, timeout=120) as resp:
        dest.write_bytes(resp.read())


def acquire_package(package_url: str, work: Path) -> Path:
    zpath = work / "praxis-stack-skills.zip"
    print(f"fetch {package_url}")
    download(package_url, zpath)
    # SPA fallback guard: zip magic
    magic = zpath.read_bytes()[:4]
    if magic != b"PK\x03\x04":
        raise SystemExit(
            f"download is not a zip (got magic={magic!r}); possible SPA fallback or network filter"
        )
    out = work / "pkg"
    if out.exists():
        shutil.rmtree(out)
    out.mkdir(parents=True)
    with zipfile.ZipFile(zpath, "r") as zf:
        zf.extractall(out)
    skills = find_package_skills(out)
    if not skills:
        raise SystemExit(f"package unpacked but skills not found under {out}")
    return skills


def install_skill(src_skill: Path, dest_root: Path, force: bool) -> str:
    name = src_skill.name
    dest = dest_root / name
    if not (src_skill / "SKILL.md").is_file():
        return f"SKIP {name} (no SKILL.md)"
    dest_root.mkdir(parents=True, exist_ok=True)
    try:
        if src_skill.resolve() == dest.resolve():
            return f"SKIP {name} (source is destination)"
    except OSError:
        pass
    if dest.exists() and not force:
        return f"SKIP {name} (exists at {dest}; use --force)"
    # Always stage via temp so live-root --force never rmtree's its own source
    # (skills_root == harness root). inv msa-20260718 K=2: code-reviewer + code-explorer.
    with tempfile.TemporaryDirectory(prefix="praxis-skill-") as td:
        tmp = Path(td) / name
        shutil.copytree(src_skill, tmp)
        if dest.exists():
            shutil.rmtree(dest)
        shutil.copytree(tmp, dest)
    return f"INSTALL {name} -> {dest}"


def install_from_skills_root(skills_root: Path, harnesses: list[str], force: bool) -> list[str]:
    actions = []
    for h in harnesses:
        root = HARNESS_ROOTS[h]
        for name in SKILL_NAMES:
            src = skills_root / name
            if not src.is_dir():
                # allow package without praxis-local-realize yet
                if name == "praxis-local-realize":
                    # install this running skill tree if we are it
                    self_skill = Path(__file__).resolve().parents[1]
                    if (self_skill / "SKILL.md").is_file() and self_skill.name == "praxis-local-realize":
                        actions.append(install_skill(self_skill, root, force))
                    continue
                actions.append(f"MISS {name} under {skills_root}")
                continue
            actions.append(install_skill(src, root, force))
    return actions


def read_package_version(skills_root: Path) -> str:
    for base in (skills_root.parent.parent, skills_root.parent, skills_root):
        man = base / "MANIFEST.json"
        if man.is_file():
            try:
                return json.loads(man.read_text(encoding="utf-8")).get("version", "unknown")
            except Exception:
                pass
    return "unknown"


def verify(harnesses: list[str], tier: int, backend_dir: Path | None) -> dict:
    results = {"skills": {}, "backend": None, "pass": True}
    for h in harnesses:
        root = HARNESS_ROOTS[h]
        results["skills"][h] = {}
        for name in ("megapraxis", "metamegapraxis"):
            p = root / name / "SKILL.md"
            ok = p.is_file() and p.stat().st_size > 1024
            results["skills"][h][name] = {
                "path": str(p),
                "ok": ok,
                "bytes": p.stat().st_size if p.is_file() else 0,
            }
            if not ok:
                results["pass"] = False
    if tier >= 1:
        health = probe_health()
        results["backend"] = health
        if not health.get("ok"):
            results["pass"] = False
        if backend_dir and not (backend_dir / "server.py").is_file():
            results["pass"] = False
            results["backend"] = {
                **(results["backend"] or {}),
                "server_py": False,
                "backend_dir": str(backend_dir),
            }
    return results


def probe_health(url: str = "http://127.0.0.1:8080/api/health") -> dict:
    try:
        req = urllib.request.Request(url, headers={"User-Agent": "praxis-local-realize/1.5"})
        with urllib.request.urlopen(req, timeout=3) as resp:
            body = resp.read().decode("utf-8", errors="replace")
            data = json.loads(body) if body.strip().startswith("{") else {}
            ok = resp.status == 200 and (
                data.get("status") in ("healthy", "ok", "up") or "healthy" in body.lower()
            )
            return {"ok": ok, "status_code": resp.status, "body": data or body[:200]}
    except Exception as e:
        return {"ok": False, "error": str(e)}


def scaffold_backend(backend_dir: Path, stub_url: str, force: bool) -> list[str]:
    actions = []
    backend_dir.mkdir(parents=True, exist_ok=True)
    server = backend_dir / "server.py"
    # prefer sibling stub in same scripts dir
    local_stub = Path(__file__).resolve().parent / "backend_stub.py"
    if local_stub.is_file():
        if server.exists() and not force:
            actions.append(f"SKIP server.py exists at {server}")
        else:
            shutil.copy(local_stub, server)
            actions.append(f"WRITE {server} (from local backend_stub.py)")
    else:
        if server.exists() and not force:
            actions.append(f"SKIP server.py exists at {server}")
        else:
            download(stub_url, server)
            actions.append(f"WRITE {server} (from {stub_url})")

    venv = backend_dir / ".venv"
    if not venv.exists():
        import subprocess

        subprocess.run([sys.executable, "-m", "venv", str(venv)], check=True)
        actions.append(f"VENV {venv}")
    else:
        actions.append(f"SKIP venv exists {venv}")

    actions.append(
        f"START hint: {py_cmd_hint()} equivalent → "
        + (
            str(venv / "Scripts" / "python.exe")
            if os.name == "nt"
            else str(venv / "bin" / "python")
        )
        + f" {server}   # listens 127.0.0.1:8080"
    )
    return actions


def write_cert(
    path: Path,
    *,
    verdict: str,
    harnesses: list[str],
    tier: int,
    version: str,
    actions: list[str],
    verify_result: dict,
    residuals: list[str],
) -> dict:
    now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
    day = datetime.now(timezone.utc).strftime("%Y%m%d")
    name = (
        f"SwarmInvocation::inv-mmgp-{day}-local-realize"
        f"::source=praxis-local-realize"
        f"::class=local-whitepaper-realize"
        f"::verdict={verdict}"
        f"::os={os_token()}"
        f"::harnesses={','.join(harnesses)}"
        f"::tier={tier}"
        f"::package_version={version}"
        f"::backend={'stub:8080' if tier >= 1 else 'none'}"
    )
    cert = {
        "schema": "praxis-stack.local-realize/v1",
        "generated_at": now,
        "swarm_invocation": {
            "name": name,
            "verdict": verdict,
            "coordinator": "praxis-local-realize",
        },
        "os": os_token(),
        "python": sys.version.split()[0],
        "harnesses": harnesses,
        "tier": tier,
        "package_version": version,
        "actions": actions,
        "verify": verify_result,
        "residuals": residuals,
        "whitepaper": "https://praxis-stack.pages.dev/whitepaper",
        "playbook": "https://praxis-stack.pages.dev/onboard-local.md",
    }
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(json.dumps(cert, indent=2) + "\n", encoding="utf-8", newline="\n")
    return cert


def main() -> int:
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument(
        "--harness",
        choices=["claude", "codex", "grok", "all"],
        default="claude",
        help="target skill root(s)",
    )
    ap.add_argument("--tier", type=int, choices=[0, 1], default=0)
    ap.add_argument("--backend-dir", type=Path, default=Path("praxis-backend"))
    ap.add_argument("--force", action="store_true")
    ap.add_argument("--verify-only", action="store_true")
    ap.add_argument("--source-dir", type=Path, default=None, help="existing package skills root")
    ap.add_argument("--package-url", default=DEFAULT_PACKAGE_URL)
    ap.add_argument("--stub-url", default=DEFAULT_STUB_URL)
    ap.add_argument(
        "--work-dir",
        type=Path,
        default=Path.cwd() / ".praxis-realize",
        help="download/unpack + cert directory",
    )
    ap.add_argument("--start-backend", action="store_true", help="spawn stub server (tier 1)")
    args = ap.parse_args()

    harnesses = list(HARNESS_ROOTS) if args.harness == "all" else [args.harness]
    actions: list[str] = []
    residuals: list[str] = [
        "Tier 2 GraphDoc/MCP not realized by this script (optional; BACKEND.md)",
        "Harness plugin registry load may require app restart (trap #2)",
        "HTTP stub alone does not flip megapraxis _via: graph_ without MCP",
    ]

    if args.verify_only:
        vr = verify(harnesses, args.tier, args.backend_dir if args.tier >= 1 else None)
        verdict = "converged-modulo-harness" if vr["pass"] else "INCOMPLETE"
        cert_path = args.work_dir / "local-realize.cert.json"
        cert = write_cert(
            cert_path,
            verdict=verdict,
            harnesses=harnesses,
            tier=args.tier,
            version="unknown",
            actions=["verify-only"],
            verify_result=vr,
            residuals=residuals,
        )
        print(json.dumps({"verdict": verdict, "cert": str(cert_path), "verify": vr}, indent=2))
        print(cert["swarm_invocation"]["name"])
        return 0 if vr["pass"] else 2

    skills_root = find_package_skills(args.source_dir)
    if not skills_root:
        work = args.work_dir
        work.mkdir(parents=True, exist_ok=True)
        skills_root = acquire_package(args.package_url, work)
        actions.append(f"ACQUIRE package -> {skills_root}")
    else:
        actions.append(f"USE skills_root {skills_root}")

    version = read_package_version(skills_root)
    actions.extend(install_from_skills_root(skills_root, harnesses, args.force))

    if args.tier >= 1:
        actions.extend(scaffold_backend(args.backend_dir, args.stub_url, args.force))
        if args.start_backend:
            import subprocess

            venv_py = (
                args.backend_dir / ".venv" / "Scripts" / "python.exe"
                if os.name == "nt"
                else args.backend_dir / ".venv" / "bin" / "python"
            )
            server = args.backend_dir / "server.py"
            # detach-ish: user can Ctrl+C parent; document residual if spawn fails
            try:
                subprocess.Popen(
                    [str(venv_py if venv_py.is_file() else sys.executable), str(server)],
                    cwd=str(args.backend_dir),
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL,
                )
                actions.append(f"SPAWN {server}")
                import time

                time.sleep(0.6)
            except Exception as e:
                actions.append(f"SPAWN_FAIL {e}")
                residuals.append(f"backend spawn failed: {e}")

    vr = verify(harnesses, args.tier, args.backend_dir if args.tier >= 1 else None)
    if vr["pass"]:
        verdict = "converged-modulo-harness"
    else:
        verdict = "INCOMPLETE"
        residuals.append("one or more verify probes failed — see verify block")

    cert_path = args.work_dir / "local-realize.cert.json"
    cert = write_cert(
        cert_path,
        verdict=verdict,
        harnesses=harnesses,
        tier=args.tier,
        version=version,
        actions=actions,
        verify_result=vr,
        residuals=residuals,
    )

    print("**praxis-local-realize** · realize · os=" + os_token())
    for a in actions:
        print("  -", a)
    print("verify:", json.dumps(vr, indent=2))
    print("verdict:", verdict, "· tier=", args.tier, "· package=", version)
    print("cert:", cert_path)
    print(cert["swarm_invocation"]["name"])
    print("next: run megapraxis in your harness; metamegapraxis only if auditing")
    print("_via: filesystem_")
    return 0 if vr["pass"] else 2


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