"""FastAPI application entrypoint."""

import logging
import threading

from fastapi import FastAPI, Request, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from slowapi import Limiter
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware
from slowapi.util import get_remote_address

from app.api.routes.chat import router as chat_router
from app.api.routes.comparative import router as comparative_router
from app.api.routes.graph_routes import router as graph_router
from app.api.routes.health import router as health_router
from app.api.routes.mcp_routes import router as mcp_router
from app.core.config import get_settings
from app.core.database import neo4j_lifespan
from app.services.ai.ghost_worker import get_ghost_worker
from app.services.storage.supabase_client import close_connection_pool
from contextlib import asynccontextmanager
import asyncio

logger = logging.getLogger(__name__)
limiter = Limiter(key_func=get_remote_address, default_limits=["100/minute"])


@asynccontextmanager
async def app_lifespan(app: FastAPI):
    """Manage application lifecycle including DB connections and background workers."""
    ghost_worker = get_ghost_worker()
    worker_task = asyncio.create_task(ghost_worker.run_ghost_worker_loop())
    logger.info(
        "Ghost worker started.",
        extra={
            "app_thread": threading.current_thread().name,
            "worker_task_id": id(worker_task),
        },
    )

    async with neo4j_lifespan(app):
        yield

    logger.info("Shutting down ghost worker...")
    ghost_worker.shutdown_event.set()
    await worker_task
    logger.info("Ghost worker shut down completely.")

    logger.info("Closing PostgreSQL connection pool...")
    close_connection_pool()
    logger.info("PostgreSQL connection pool shutdown complete.")


def _rate_limit_handler(request: Request, exc: RateLimitExceeded) -> JSONResponse:
    """Handle rate limit errors for the API.

    Args:
        request: Incoming request context.
        exc: Raised rate limit exception.

    Returns:
        JSONResponse: Standardized error response.
    """
    logger.info(
        "Rate limit exceeded",
        extra={"path": request.url.path, "error": "rate_limit"},
    )
    return JSONResponse(
        status_code=status.HTTP_429_TOO_MANY_REQUESTS,
        content={
            "error": {
                "code": status.HTTP_429_TOO_MANY_REQUESTS,
                "message": "Rate limit exceeded",
            }
        },
    )


def _internal_exception_handler(request: Request, exc: Exception) -> JSONResponse:
    """Handle uncaught exceptions with JSON-RPC style error response.

    Args:
        request: Incoming request context.
        exc: Raised exception.

    Returns:
        JSONResponse: Standardized error response.
    """
    logger.info(
        "Unhandled exception",
        extra={"path": request.url.path, "error": type(exc).__name__},
    )
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content={
            "error": {
                "code": status.HTTP_500_INTERNAL_SERVER_ERROR,
                "message": "Internal server error",
            }
        },
    )


def create_application() -> FastAPI:
    """Create the FastAPI application instance.

    Returns:
        FastAPI: Configured FastAPI application.
    """
    settings = get_settings()
    application = FastAPI(title=settings.project_name, lifespan=app_lifespan)
    application.state.limiter = limiter
    application.add_exception_handler(RateLimitExceeded, _rate_limit_handler)
    application.add_exception_handler(Exception, _internal_exception_handler)
    application.add_middleware(SlowAPIMiddleware)
    application.add_middleware(
        CORSMiddleware,
        allow_origins=[str(origin) for origin in settings.frontend_urls],
        allow_credentials=True,
        allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
        allow_headers=["Authorization", "Content-Type", "Accept", "Origin", "Cache-Control"],
    )
    application.include_router(health_router)
    application.include_router(graph_router, prefix="/api/graph")
    application.include_router(mcp_router, prefix="/mcp")
    application.include_router(chat_router, prefix="/api")
    application.include_router(comparative_router, prefix="/api")
    return application


app = create_application()
