"""API des Viewers (Phase 2). Lese-Routen über viewer.py, Lauf-Routen über scan_dienst."""
from pathlib import Path

from fastapi import APIRouter, HTTPException

import agents
import database as db
import projekte
import scan_dienst
import viewer

router = APIRouter(prefix="/api")


def _wurzel(name: str) -> Path:
    wurzel = projekte.finde(name)
    if wurzel is None:
        raise HTTPException(404, f"Projekt '{name}' nicht in projekte.txt")
    return wurzel


@router.get("/health")
async def health():
    return {"ok": True}


@router.get("/fs")
async def fs(pfad: str = ""):
    """Ordner-Browser für die Projekt-Auswahl: nur Verzeichnisse, keine versteckten."""
    basis = Path(pfad).expanduser() if pfad else Path.home()
    if not basis.is_dir():
        raise HTTPException(404, f"{basis} ist kein Verzeichnis")
    basis = basis.resolve()
    try:
        kinder = sorted(basis.iterdir(), key=lambda p: p.name.lower())
    except PermissionError:
        raise HTTPException(403, f"kein Zugriff auf {basis}")
    ordner = [{"name": k.name, "pfad": str(k), "hat_planer": (k / ".planer").is_dir()}
              for k in kinder if k.is_dir() and not k.name.startswith(".")]
    eltern = str(basis.parent) if basis.parent != basis else None
    return {"pfad": str(basis), "eltern": eltern, "ordner": ordner}


@router.post("/projekte")
async def projekt_hinzufuegen(body: dict):
    pfad = (body.get("pfad") or "").strip()
    if not pfad:
        raise HTTPException(400, "pfad fehlt")
    try:
        projekte.hinzufuegen(pfad)
    except ValueError as e:
        raise HTTPException(409, str(e))
    return {"ok": True}


@router.delete("/projekte/{name}")
async def projekt_entfernen(name: str):
    lauf = scan_dienst.status(name)
    if lauf and lauf["laeuft"]:
        raise HTTPException(409, "Scan läuft — erst abwarten oder abbrechen")
    try:
        projekte.entfernen(name)
    except ValueError as e:
        raise HTTPException(404, str(e))
    return {"ok": True}


@router.get("/projekte")
async def liste():
    out = []
    for p in projekte.lade():
        eintrag = dict(p)
        if "fehler" not in p:
            wurzel = Path(p["pfad"])
            eintrag["hat_planer"] = (wurzel / ".planer" / "kern.md").is_file()
            staende = {d: s for d, (s, _) in scan_dienst.einheiten_bestand(wurzel).items()}
            eintrag["drift"] = viewer.drift(wurzel, staende)["veraltet"]
            eintrag["letzter_scan_ts"] = await db.letzter_agent_ts(p["name"])
            lauf = scan_dienst.status(p["name"])
            eintrag["scan_laeuft"] = bool(lauf and lauf["laeuft"])
        out.append(eintrag)
    return out


@router.get("/projekte/{name}")
async def projekt(name: str):
    wurzel = _wurzel(name)
    daten = viewer.lade_projekt(wurzel)
    einheiten_kurz = {eid: {"beschreibung": e["beschreibung"]}
                      for eid, e in daten["einheiten"].items()}
    return {
        "name": name,
        "kern": daten["kern"],
        "bereiche": daten["bereiche"],
        "architektur": daten["architektur"],
        "flows": daten["flows"],
        "pruefung": daten["pruefung"],
        "einheiten": einheiten_kurz,
        "doku_ordnung": viewer.doku_ordnung(daten),
        "drift": viewer.drift(wurzel, daten["staende"]),
    }


@router.get("/projekte/{name}/einheit")
async def einheit(name: str, id: str):
    wurzel = _wurzel(name)
    daten = viewer.lade_projekt(wurzel)
    e = daten["einheiten"].get(id)
    if e is None:
        raise HTTPException(404, f"Einheit '{id}' unbekannt")
    quelldatei = id.partition("::")[0]
    veraltet = quelldatei in viewer.drift(wurzel, daten["staende"])["veraltet"]
    code = viewer.code_extrahieren(wurzel, id)
    for anker in e["anker"]:
        zusatz = viewer.code_extrahieren(wurzel, anker)
        if zusatz and zusatz not in code:
            code += ("\n\n" if code else "") + zusatz
    return {**e, "code": code, "veraltet": veraltet}


@router.post("/projekte/{name}/scan")
async def scan_starten(name: str, body: dict):
    wurzel = _wurzel(name)
    art = body.get("art", "scan")
    if art not in ("scan", "rescan"):
        raise HTTPException(400, f"unbekannte Art '{art}'")
    try:
        status = scan_dienst.starte(name, wurzel, art)
    except scan_dienst.VorflugFehler as e:
        raise HTTPException(409, str(e))
    return {"status": status}


@router.get("/projekte/{name}/scan-status")
async def scan_status(name: str):
    _wurzel(name)
    lauf = scan_dienst.status(name)
    if lauf is None:
        return {"laeuft": False, "art": None, "ergebnis": None, "stufen": {}, "agenten": [], "dead": []}
    out = dict(lauf)
    if lauf["laeuft"]:
        out["stufen"] = (await db.kanban_stage_counts(name)).get("scan", {})
        out["agenten"] = agents.active_agents(f"scan-{name}-")
        out["dead"] = [c["card_id"] for c in await db.kanban_dead(name)]
    else:
        out["stufen"] = {}
        out["agenten"] = []
        out["dead"] = (lauf["ergebnis"] or {}).get("dead", [])
    return out
