"""FastAPI application entrypoint."""

from pathlib import Path

from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from sqlalchemy import text

from gnexus_creds.api import admin_router
from gnexus_creds.api import router as api_router
from gnexus_creds.config import get_settings
from gnexus_creds.db import SessionLocal
from gnexus_creds.errors import AppError, app_error_handler, validation_error_handler
from gnexus_creds.logging import configure_logging
from gnexus_creds.mcp import router as mcp_router
from gnexus_creds.oauth import router as auth_router
from gnexus_creds.oauth import webhook_router

PROJECT_ROOT = Path(__file__).resolve().parent.parent
FRONTEND_DIST = PROJECT_ROOT / "frontend" / "dist"
UI_KIT_ASSETS = PROJECT_ROOT / "frontend" / "node_modules" / "gnexus-ui-kit" / "dist" / "assets"


def create_app() -> FastAPI:
    configure_logging()
    settings = get_settings()
    app = FastAPI(title=settings.app_name, version="0.1.0")
    app.add_exception_handler(AppError, app_error_handler)
    app.add_exception_handler(RequestValidationError, validation_error_handler)
    app.include_router(auth_router)
    app.include_router(webhook_router)
    app.include_router(api_router)
    app.include_router(admin_router)
    app.include_router(mcp_router)

    @app.get("/health", tags=["system"])
    async def health() -> dict[str, str]:
        return {"status": "ok"}

    @app.get("/ready", tags=["system"])
    async def ready() -> dict[str, str]:
        with SessionLocal() as db:
            db.execute(text("select 1"))
        return {"status": "ok"}

    if FRONTEND_DIST.exists():
        ui_kit_fonts_dir = UI_KIT_ASSETS / "fonts"
        if ui_kit_fonts_dir.exists():
            app.mount("/assets/fonts", StaticFiles(directory=ui_kit_fonts_dir), name="ui-kit-fonts")

        assets_dir = FRONTEND_DIST / "assets"
        if assets_dir.exists():
            app.mount("/assets", StaticFiles(directory=assets_dir), name="assets")

        @app.get("/", include_in_schema=False)
        async def index() -> FileResponse:
            return FileResponse(FRONTEND_DIST / "index.html")

        @app.get("/{path:path}", include_in_schema=False)
        async def spa_fallback(path: str) -> FileResponse:
            if path.startswith(("api/", "auth/", "mcp/", "webhooks/")):
                raise AppError("not_found", "Not found.", status_code=404)
            return FileResponse(FRONTEND_DIST / "index.html")

    return app


app = create_app()
