"""SSE (Server-Sent Events) adapter — streaming at /mcp/sse.

Provides event streaming for long-running tool operations like BLCE
analysis, E2E assessment, and Wright pipeline generation.
"""

from __future__ import annotations

import json
import logging
from typing import Any

from fastapi import APIRouter, Depends, Request
from fastapi.responses import StreamingResponse

from ..context import RequestContext
from ..registry import ToolRegistry

logger = logging.getLogger(__name__)

router = APIRouter(tags=["SSE Streaming"])

_registry: ToolRegistry | None = None
_tenant_registry: Any = None


def init_sse(registry: ToolRegistry, tenant_registry: Any = None) -> None:
    """Wire the shared ToolRegistry into this adapter."""
    global _registry, _tenant_registry
    _registry = registry
    _tenant_registry = tenant_registry


async def _get_sse_context(request: Request) -> RequestContext:
    """Build RequestContext for SSE requests."""
    from ..middleware.auth import get_request_context
    return await get_request_context(request, _tenant_registry, protocol="sse")


@router.get("/mcp/sse")
async def sse_handler(
    tool: str,
    request: Request,
    context: RequestContext = Depends(_get_sse_context),
) -> StreamingResponse:
    """Stream tool execution results as Server-Sent Events.

    Query params:
        tool: Tool name to execute (required).
        All other query params are passed as tool arguments.

    Event format:
        data: {"result": "...", "tool": "...", "request_id": "..."}
        data: {"done": true}
    """
    # Collect tool params from remaining query params
    params: dict[str, Any] = {}
    for key, value in request.query_params.items():
        if key not in ("tool", "api_key", "tenant_id"):
            params[key] = value

    async def event_stream():
        try:
            async for chunk in _registry.stream(tool, params, context):
                payload = json.dumps(chunk, default=str)
                yield f"data: {payload}\n\n"
        except Exception as exc:
            error_payload = json.dumps({"error": str(exc), "done": True})
            yield f"data: {error_payload}\n\n"

    return StreamingResponse(
        event_stream(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "X-Accel-Buffering": "no",
        },
    )


@router.post("/mcp/sse")
async def sse_post_handler(
    request: Request,
    context: RequestContext = Depends(_get_sse_context),
) -> StreamingResponse:
    """Stream tool execution via POST body.

    Body: {"tool": "tool_name", "params": {...}}
    """
    try:
        body = await request.json()
    except Exception:
        body = {}

    tool = body.get("tool", "")
    params = body.get("params", {})

    if not tool:
        async def error_stream():
            yield f"data: {json.dumps({'error': 'Missing tool name', 'done': True})}\n\n"
        return StreamingResponse(error_stream(), media_type="text/event-stream")

    async def event_stream():
        try:
            async for chunk in _registry.stream(tool, params, context):
                payload = json.dumps(chunk, default=str)
                yield f"data: {payload}\n\n"
        except Exception as exc:
            error_payload = json.dumps({"error": str(exc), "done": True})
            yield f"data: {error_payload}\n\n"

    return StreamingResponse(
        event_stream(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "X-Accel-Buffering": "no",
        },
    )
