#!/usr/bin/env python3
"""Homepage Admin UI — sites toevoegen via browser."""
import os
import re
import subprocess
import threading
from pathlib import Path

from fastapi import FastAPI, HTTPException
from fastapi.responses import FileResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel

APP_ROOT = Path(os.environ.get("HOMEPAGE_DIR", Path(__file__).resolve().parent.parent))
WEBSITES_ADD = APP_ROOT / "websites-add.txt"
HOMELAB_APPS = APP_ROOT.parent
GENERATE = APP_ROOT / "generate-config.py"
DEPLOY = APP_ROOT / "deploy-to-pve.sh"

GROUPS = [
    "Infrastructure",
    "Media & TV",
    "Smart Home",
    "Productivity",
    "Tools & Utils",
    "AI Assistants",
    "Dev & Docs",
    "Web Design",
]

TAB_FOR_GROUP = {
    "Infrastructure": "Ops",
    "Media & TV": "Media",
    "Smart Home": "Home",
    "Productivity": "Work",
    "Tools & Utils": "Ops",
    "AI Assistants": "AI",
    "Dev & Docs": "AI",
    "Web Design": "AI",
}

_apply_lock = threading.Lock()
_apply_status = {"running": False, "ok": None, "log": ""}


class SiteIn(BaseModel):
    group: str
    name: str
    url: str


class SiteOut(BaseModel):
    id: int
    group: str
    name: str
    url: str
    tab: str


def read_sites() -> list[dict]:
    if not WEBSITES_ADD.exists():
        WEBSITES_ADD.write_text(
            "# groep|naam|url\n# Of gebruik de UI op poort 3010\n\n",
            encoding="utf-8",
        )
    rows = []
    for i, raw in enumerate(WEBSITES_ADD.read_text(encoding="utf-8").splitlines()):
        line = raw.strip()
        if not line or line.startswith("#"):
            continue
        parts = [p.strip() for p in line.split("|", 2)]
        if len(parts) != 3:
            continue
        g, n, u = parts
        rows.append(
            {
                "id": len(rows),
                "group": g,
                "name": n,
                "url": u,
                "tab": TAB_FOR_GROUP.get(g, "?"),
            }
        )
    return rows


def write_sites(rows: list[tuple[str, str, str]]) -> None:
    lines = [
        "# Extra websites — beheerd via Homepage Admin UI",
        "# groep|naam|url",
        "",
    ]
    for g, n, u in rows:
        n = n.replace("|", "-")
        lines.append(f"{g}|{n}|{u}")
    lines.append("")
    WEBSITES_ADD.write_text("\n".join(lines), encoding="utf-8")


def run_apply():
    global _apply_status
    with _apply_lock:
        _apply_status = {"running": True, "ok": None, "log": "Start…\n"}
        try:
            gen = subprocess.run(
                ["python3", str(GENERATE)],
                cwd=str(APP_ROOT),
                capture_output=True,
                text=True,
                timeout=120,
            )
            _apply_status["log"] += gen.stdout or ""
            if gen.stderr:
                _apply_status["log"] += gen.stderr
            if gen.returncode != 0:
                _apply_status["ok"] = False
                _apply_status["log"] += "\nFout bij generate-config.py"
                return

            _apply_status["log"] += "\nDeploy naar Proxmox…\n"
            dep = subprocess.run(
                ["/bin/sh", str(DEPLOY)],
                cwd=str(APP_ROOT),
                capture_output=True,
                text=True,
                timeout=300,
                env={**os.environ},
            )
            _apply_status["log"] += dep.stdout or ""
            if dep.stderr:
                _apply_status["log"] += dep.stderr
            _apply_status["ok"] = dep.returncode == 0
            if _apply_status["ok"]:
                _apply_status["log"] += "\n✓ Klaar — refresh Homepage (Ctrl+Shift+R)"
            else:
                _apply_status["log"] += "\n✗ Deploy mislukt"
        except Exception as e:
            _apply_status["ok"] = False
            _apply_status["log"] += f"\nFout: {e}"
        finally:
            _apply_status["running"] = False


app = FastAPI(title="Homepage Admin")
static_dir = Path(__file__).parent / "static"
app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")


@app.get("/", response_class=HTMLResponse)
def index():
    return FileResponse(static_dir / "index.html")


@app.get("/api/groups")
def api_groups():
    return [{"name": g, "tab": TAB_FOR_GROUP.get(g, "")} for g in GROUPS]


@app.get("/api/sites")
def api_sites():
    return read_sites()


@app.post("/api/sites")
def api_add(site: SiteIn):
    if site.group not in GROUPS:
        raise HTTPException(400, f"Onbekende groep: {site.group}")
    name = site.name.strip()
    url = site.url.strip()
    if not name or not url:
        raise HTTPException(400, "Naam en URL zijn verplicht")
    if not re.match(r"^https?://", url, re.I):
        raise HTTPException(400, "URL moet beginnen met http:// of https://")

    rows = [(s["group"], s["name"], s["url"]) for s in read_sites()]
    rows.append((site.group, name, url))
    write_sites(rows)
    return {"ok": True}


@app.delete("/api/sites/{site_id}")
def api_delete(site_id: int):
    sites = read_sites()
    if site_id < 0 or site_id >= len(sites):
        raise HTTPException(404, "Site niet gevonden")
    rows = [(s["group"], s["name"], s["url"]) for i, s in enumerate(sites) if i != site_id]
    write_sites(rows)
    return {"ok": True}


@app.post("/api/apply")
def api_apply():
    if _apply_status.get("running"):
        raise HTTPException(409, "Bezig met toepassen…")
    t = threading.Thread(target=run_apply, daemon=True)
    t.start()
    return {"ok": True, "message": "Gestart"}


@app.get("/api/apply/status")
def api_apply_status():
    return _apply_status


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=3010)
