"""
ABOS AI Worker – FastAPI Application Entry Point
==================================================
Constructs and configures the FastAPI application:
  - Registers the CORS middleware (frontend-facing endpoints need this).
  - Mounts the API router.
  - Starts a periodic background task to evict expired documents.
  - Exposes /health and /info meta-endpoints.
"""

from __future__ import annotations

import asyncio
import logging
import logging.config

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse

from app.config import settings
from app.routes import router
from app.email_analyzer import email_router
from app.meeting_analyzer import meeting_router
from app.project_ai import project_ai_router
from app.project_plan import project_plan_router
from app.email_ai import email_ai_router
from app.mcp_tools import mcp_server
from app.store import document_store



# ---------------------------------------------------------------------------
# Logging setup
# ---------------------------------------------------------------------------
logging.basicConfig(
    level=logging.DEBUG if settings.debug else logging.INFO,
    format="%(asctime)s [%(levelname)s] %(name)s – %(message)s",
    datefmt="%Y-%m-%dT%H:%M:%S",
)
logger = logging.getLogger(__name__)


# ---------------------------------------------------------------------------
# Periodic store cleanup
# ---------------------------------------------------------------------------

async def _periodic_store_cleanup(interval_seconds: int = 300) -> None:
    """Background coroutine that purges expired documents every *interval_seconds*."""
    while True:
        await asyncio.sleep(interval_seconds)
        try:
            purged = await document_store.purge_expired()
            if purged:
                logger.info("Store cleanup: purged %d expired document(s).", purged)
        except Exception as exc:  # noqa: BLE001
            logger.error("Store cleanup failed: %s", exc)


# ---------------------------------------------------------------------------
# Lifespan (replaces deprecated @app.on_event)
# ---------------------------------------------------------------------------

from contextlib import asynccontextmanager  # noqa: E402 (after stdlib imports)


@asynccontextmanager
async def lifespan(app: FastAPI):  # type: ignore[type-arg]
    """Start background cleanup task on startup; cancel it on shutdown.

    Also enters the MCP server's session-manager context (mcp_server.session_manager.run()).
    FastAPI does NOT automatically run a mounted sub-app's own lifespan (see the /mcp Mount
    below) — without this, every MCP tool call would fail with "Task group is not
    initialized. Make sure to use run()." the moment it hit the streamable-HTTP transport.
    """
    cleanup_task = asyncio.create_task(_periodic_store_cleanup(interval_seconds=300))
    logger.info(
        "🚀  %s v%s starting up…", settings.app_name, settings.app_version
    )
    try:
        async with mcp_server.session_manager.run():
            yield
    finally:
        cleanup_task.cancel()
        try:
            await cleanup_task
        except asyncio.CancelledError:
            pass
        logger.info("🛑  %s shut down cleanly.", settings.app_name)


# ---------------------------------------------------------------------------
# Application factory
# ---------------------------------------------------------------------------

app = FastAPI(
    title=settings.app_name,
    version=settings.app_version,
    description=(
        "Stateless AI Worker microservice for the ABOS Micro ERP platform. "
        "Handles PDF ingestion, LLM-based data extraction via OpenRouter, "
        "Human-in-the-Loop verification, and outbound webhook delivery to "
        "the Spring Boot backend."
    ),
    docs_url="/docs",
    redoc_url="/redoc",
    lifespan=lifespan,
)

# ---------------------------------------------------------------------------
# CORS Middleware
# ---------------------------------------------------------------------------
# Allow the React frontend to call the frontend-facing endpoints.
# In production, replace cors_origins in config.py / .env with the
# exact origin of your deployed React app.
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origins,
    allow_credentials=True,
    allow_methods=["GET", "POST", "OPTIONS"],
    allow_headers=["*"],
)

# ---------------------------------------------------------------------------
# Mount API routers
# ---------------------------------------------------------------------------
app.include_router(router, prefix="")
app.include_router(email_router, prefix="")
app.include_router(meeting_router, prefix="")
app.include_router(project_ai_router, prefix="")
app.include_router(project_plan_router, prefix="")
app.include_router(email_ai_router, prefix="")

# ---------------------------------------------------------------------------
# Mount the MCP tool-calling server
# ---------------------------------------------------------------------------
# Reachable at POST /mcp/mcp (Streamable HTTP transport — see app/mcp_tools.py for the
# tool definitions, auth model, and why the path nests under itself: FastMCP mounts its
# own "/mcp" route inside the Starlette app it returns).
app.mount("/mcp", mcp_server.streamable_http_app())



