"""DECNET SWARM Controller — master-side control plane.

Runs as an independent FastAPI/uvicorn process.  Isolated from
``decnet.web.api`` so controller failure cannot cascade to the main API,
ingester, or dashboard (mirrors the existing pattern used by
``decnet api`` with ``start_new_session=True``).

Responsibilities:
* host enrollment (issues CA-signed worker bundles);
* dispatching DecnetConfig shards to worker agents over mTLS;
* active health probes of enrolled workers.

The controller *reuses* the same ``get_repo`` dependency as the main API,
so SwarmHost / DeckyShard state is visible to both processes via the
shared DB.
"""
from __future__ import annotations

from decnet.web import _uvicorn_tls_scope  # noqa: F401  # patches uvicorn on import

from contextlib import asynccontextmanager
from typing import AsyncGenerator

from fastapi import FastAPI
from fastapi.responses import ORJSONResponse

from decnet.logging import get_logger
from decnet.swarm import pki
from decnet.swarm.client import ensure_master_identity
from decnet.web.dependencies import repo
from decnet.web.router.swarm import swarm_router

log = get_logger("swarm_api")


@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    log.info("swarm-controller starting up")
    # Make sure the CA and master client cert exist before we accept any
    # request — enrollment needs them and AgentClient needs them.
    pki.ensure_ca()
    ensure_master_identity()
    await repo.initialize()
    log.info("swarm-controller ready")
    yield
    log.info("swarm-controller shutdown")


app: FastAPI = FastAPI(
    title="DECNET SWARM Controller",
    version="0.1.0",
    lifespan=lifespan,
    default_response_class=ORJSONResponse,
    # No interactive docs: the controller is an internal management plane,
    # not a public surface.  Enable explicitly in dev if needed.
    docs_url=None,
    redoc_url=None,
    openapi_url=None,
)

app.include_router(swarm_router)


@app.get("/health")
async def root_health() -> dict[str, str]:
    """Top-level liveness probe (no DB I/O)."""
    return {"status": "ok", "role": "swarm-controller"}
