"""fed-web's ``console_launch`` glue — the consumer side of the mgf-uitest-web contract.

The harness (``mgf-uitest-web``) ships its fixtures via a ``pytest11`` entry point, so
installing ``.[dev]`` is all it takes to get ``console``, ``viewport``, ``console_port``
and friends. The one thing the harness cannot know is **how to launch this console** —
that is what this fixture supplies: build a deterministic synthetic federation under
``tmp_path`` and return how to run ``mgf-fed-web`` against it.

Why the specs live here and not in the harness: the console owns its own UI gate. The
harness stays console-free (it is proven against a stdlib static server), and each
console's specs sit next to the code they gate, so a change to fed-web's chrome is
caught by fed-web's own CI.

The synthetic payloads mirror ``tests/conftest.py`` (schema-valid, deterministic —
never dependent on the live repos' mutating state).
"""

from __future__ import annotations

import hashlib
import json
import sys
from pathlib import Path
from typing import Any

import pytest
from mgf.uitest_web import ConsoleLaunch

# --------------------------------------------------------------------------- #
# deterministic synthetic federation (payloads mirror fed-web's conftest)     #
# --------------------------------------------------------------------------- #
_ALPHA_STATUS: dict[str, Any] = {
    "schema_version": "0.1",
    "kind": "status",
    "project": "alpha",
    "summary": {"total": 2, "by_state": {"in_progress": 1, "next": 1}},
    "tasks": [
        {
            "id": "A-1",
            "title": "Wire the spine reader",
            "state": "in_progress",
            "owner": "implementer",
            "risk": "low",
            "impact": "high",
            "effort": "M",
            "eta": "2026-07",
            "stage": "phase-a",
            "started_at": "2026-06-10T00:00:00Z",
            "evidence": "reader returns honest-absence",
        },
        {
            "id": "A-2",
            "title": "Approve the schema freeze",
            "state": "next",
            "owner": "founder",
            "risk": "low",
            "impact": "high",
            "effort": "S",
            "eta": "2026-07",
            "stage": "phase-a",
            "evidence": "founder-only call",
        },
    ],
}
_ALPHA_ROADMAP: dict[str, Any] = {
    "schema_version": "0.1",
    "kind": "roadmap",
    "project": "alpha",
    "final_stage": {"id": "v1", "label": "v1.0"},
    "stages": [
        {
            "id": "phase-a",
            "label": "Phase A — Foundation",
            "state": "in_progress",
            "progress": 0.6,
            "depends_on": [],
            "owner": "implementer",
            "risk": "medium",
            "effort": "L",
            "eta": "2026-07",
            "summary": "spine + dashboard",
        },
        {
            "id": "v1",
            "label": "v1.0",
            "state": "planned",
            "progress": 0.0,
            "depends_on": ["phase-a"],
            "owner": "founder",
            "risk": "low",
            "effort": "S",
            "eta": "2026-Q4",
        },
    ],
}
_BETA_STATUS: dict[str, Any] = {
    "schema_version": "0.1",
    "kind": "status",
    "project": "beta",
    "summary": {"total": 1, "by_state": {"done": 1}},
    "tasks": [
        {
            "id": "B-1",
            "title": "Ship the graph projector",
            "state": "done",
            "owner": "implementer",
            "risk": "low",
            "impact": "medium",
            "effort": "S",
            "eta": "2026-06",
        }
    ],
}
_BETA_ARCH: dict[str, Any] = {
    "schema_version": "0.1",
    "kind": "architecture",
    "project": "beta",
    "mode": "graph",
    "graph": {
        "layers": ["core", "tools"],
        "nodes": [
            {"id": "engine", "label": "core/engine", "layer": "core"},
            {"id": "reader", "label": "core/reader", "layer": "core"},
            {"id": "cli", "label": "tools/cli", "layer": "tools"},
        ],
        "edges": [
            {"from": "cli", "to": "engine", "kind": "depends_on"},
            {"from": "engine", "to": "reader", "kind": "depends_on"},
        ],
    },
}


def _write_project(root: Path, slug: str, kind: str, files: dict[str, dict[str, Any]]) -> None:
    """Write a valid generated/ tree (payloads pre-validated; hashes into manifest)."""
    gen = root / slug / "fed-resources" / "generated"
    gen.mkdir(parents=True)
    manifest_files = []
    for name, payload in files.items():
        raw = (json.dumps(payload, sort_keys=True, indent=2) + "\n").encode("utf-8")
        (gen / name).write_bytes(raw)
        manifest_files.append(
            {
                "path": name,
                "sha256": hashlib.sha256(raw).hexdigest(),
                "schema": f"{payload['kind']}@0.1",
            }
        )
    manifest = {
        "schema_version": "0.1",
        "kind": "manifest",
        "project": {"id": slug, "name": slug, "kind": kind},
        "generated_at": "2026-06-29T00:00:00Z",
        "source_commit": "0" * 40,
        "generator": {"name": "fedres", "version": "0.1.0"},
        "files": manifest_files,
    }
    (gen / "manifest.json").write_text(
        json.dumps(manifest, sort_keys=True, indent=2) + "\n", encoding="utf-8"
    )


def _build_federation(root: Path) -> Path:
    root.mkdir(parents=True, exist_ok=True)
    _write_project(
        root, "alpha", "library", {"status.json": _ALPHA_STATUS, "roadmap.json": _ALPHA_ROADMAP}
    )
    _write_project(
        root, "beta", "standards", {"status.json": _BETA_STATUS, "architecture.json": _BETA_ARCH}
    )
    return root


@pytest.fixture
def console_launch(tmp_path: Path, console_port: int) -> ConsoleLaunch:
    """Consumer glue: build a synthetic federation and launch this console on it.

    Launched as ``sys.executable -m mgf.fed_web`` rather than via a resolved console
    script: it is the interpreter already running the suite, so the console under test
    is always THIS checkout — no PATH lookup, no venv guessing, and nothing to keep in
    sync with a developer's machine layout.
    """
    federation = _build_federation(tmp_path / "federation")
    return ConsoleLaunch(
        command=[
            sys.executable,
            "-m",
            "mgf.fed_web",
            "--host",
            "127.0.0.1",
            "--port",
            str(console_port),
        ],
        env={"MGF_FED_WEB_ROOTS": str(federation)},
        ready_path="/",
        name="mgf-fed-web",
    )
