import asyncio
from contextlib import asynccontextmanager
from pathlib import Path

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from starlette.routing import Route
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles

from app.api import ingest, servers, shares
from app.db import close_db, init_db
from app.mcp import mcp, mcp_asgi
from app.shares_probe import loop as shares_probe_loop

# Собранный Vue-фронт (panel/frontend/dist) попадает сюда в docker-образе;
# в dev фронт крутится отдельно (vite, proxy /api → localhost:8000)
STATIC_DIR = Path(__file__).resolve().parent.parent / "static"


@asynccontextmanager
async def lifespan(_: FastAPI):
    await init_db()
    # фоновый пробер сетевых хранилищ (share_samples)
    probe_task = asyncio.create_task(shares_probe_loop())
    # lifespan смонтированных sub-app не вызывается — MCP session manager
    # стартуем здесь, иначе /mcp отвечает 500 ("Task group is not initialized")
    async with mcp.session_manager.run():
        yield
    probe_task.cancel()
    await close_db()


app = FastAPI(title="GHard Monitor API", version="0.1.0", lifespan=lifespan)

# В проде фронт раздаётся тем же origin; CORS нужен для vite dev-сервера (этап 3)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(ingest.router)
app.include_router(servers.router)
app.include_router(shares.router)

# MCP для ИИ-агентов (streamable HTTP, stateless) — POST/GET/DELETE /mcp
app.router.routes.append(
    Route("/mcp", mcp_asgi, methods=["GET", "POST", "DELETE"])
)


@app.get("/api/v1/health")
async def health() -> dict:
    return {"status": "ok"}


# --- Статика фронтенда: SPA с fallback на index.html -------------------------

if STATIC_DIR.is_dir():
    assets = STATIC_DIR / "assets"
    if assets.is_dir():
        app.mount("/assets", StaticFiles(directory=assets), name="assets")

    @app.get("/{full_path:path}", include_in_schema=False)
    async def spa(full_path: str) -> FileResponse:
        """Роуты Vue отдаём из dist, всё непонятное — index.html (SPA history)."""
        candidate = STATIC_DIR / full_path
        if full_path and candidate.is_file():
            return FileResponse(candidate)
        return FileResponse(STATIC_DIR / "index.html")