"""ASGI config for Mnemosyne.

Serves the FastMCP server at /mcp (streamable HTTP) and /mcp/sse (SSE) plus a
/mcp/health endpoint. The Django ASGI app is also mounted at the root for any
other ASGI consumers — but the WSGI server (Gunicorn) is still the primary
serving path for Django views.

Run separately from the Django WSGI server:
    uvicorn mnemosyne.asgi:app --host 0.0.0.0 --port 8001 --workers 1
"""

import os
from contextlib import asynccontextmanager

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mnemosyne.settings")

import django  # noqa: E402

django.setup()

from django.core.asgi import get_asgi_application  # noqa: E402
from starlette.applications import Starlette  # noqa: E402
from starlette.responses import JSONResponse, RedirectResponse  # noqa: E402
from starlette.routing import Mount, Route  # noqa: E402

from mcp_server.server import mcp  # noqa: E402

application = get_asgi_application()  # Django ASGI app (kept for compatibility)

mcp_http_app = mcp.http_app(path="/", transport="streamable-http")
mcp_sse_app = mcp.http_app(path="/", transport="sse")


async def health(request):
    return JSONResponse({"status": "ok"})


async def mcp_redirect(request):
    """Bare /mcp → /mcp/ — MCP clients that omit the trailing slash hit
    Starlette's Mount which only matches /mcp/* paths, falling through to
    Django and returning 404. A 307 preserves the POST body."""
    return RedirectResponse(url="/mcp/", status_code=307)


@asynccontextmanager
async def lifespan(app):
    async with mcp_http_app.lifespan(app), mcp_sse_app.lifespan(app):
        yield


app = Starlette(
    routes=[
        Route("/mcp/health", health),
        Route("/mcp", mcp_redirect, methods=["GET", "POST"]),
        Mount("/mcp/sse", app=mcp_sse_app),
        Mount("/mcp", app=mcp_http_app),
        Mount("/", app=application),
    ],
    lifespan=lifespan,
)
