"""Streamable HTTP transport for MCP.

Exposes one endpoint, ``POST /mcp``, that accepts a JSON-RPC request and
returns a JSON-RPC response. The same bearer token gate as the A2A HTTP
adapter applies when ``A2A_API_KEY`` is set.

Mountable into the existing A2A FastAPI app via :func:`mount_http`, or
serveable standalone via :func:`build_http_app`.
"""
from __future__ import annotations

import os
from typing import Any

from fastapi import APIRouter, FastAPI, Header, HTTPException, Request

from ..agent import A2AAgent
from .server import MCPServer, _PARSE_ERROR, _INVALID_REQUEST, _error


def _check_key(authorization: str | None) -> None:
    api_key = os.environ.get("A2A_API_KEY")
    if api_key is None:
        return
    if not authorization or not authorization.lower().startswith("bearer "):
        raise HTTPException(401, "missing bearer token")
    token = authorization.split(None, 1)[1].strip()
    if token != api_key:
        raise HTTPException(401, "invalid bearer token")


def mount_http(app: FastAPI, agent: A2AAgent, *, prefix: str = "/mcp") -> None:
    """Mount the MCP endpoint onto an existing FastAPI app."""
    server = MCPServer(agent)
    router = APIRouter()

    @router.post(prefix)
    async def mcp_endpoint(
        request: Request,
        authorization: str | None = Header(default=None),
    ) -> Any:
        _check_key(authorization)
        try:
            body = await request.json()
        except Exception as exc:  # noqa: BLE001
            return _error(None, _PARSE_ERROR, f"parse error: {exc}")
        if not isinstance(body, dict):
            return _error(None, _INVALID_REQUEST, "request must be a JSON object")
        response = await server.handle(body)
        # Notifications have no response — MCP says return 202 with empty body.
        if response is None:
            from fastapi import Response
            return Response(status_code=202)
        return response

    @router.get(prefix)
    async def mcp_get_unsupported() -> Any:
        # Streamable HTTP allows GET for server-initiated streams; we don't
        # support that yet, so be explicit rather than 404.
        raise HTTPException(405, "GET not supported; use POST /mcp")

    app.include_router(router)


def build_http_app(agent: A2AAgent) -> FastAPI:
    """Build a minimal FastAPI app exposing only the MCP endpoint."""
    app = FastAPI(title=f"{type(agent).name} (MCP)", version=type(agent).version)
    mount_http(app, agent)
    return app
