from __future__ import annotations

from collections.abc import Awaitable, Callable

from fastapi.responses import StreamingResponse


def build_sse_response(
    queue,
    *,
    encoder: Callable[[object], str],
    unsubscribe: Callable[[], Awaitable[None]],
    heartbeat_seconds: int = 10,
    stop_on_event: str | None = None,
) -> StreamingResponse:
    async def event_stream():
        import asyncio

        try:
            while True:
                try:
                    event = await asyncio.wait_for(queue.get(), timeout=heartbeat_seconds)
                    yield encoder(event)
                    if stop_on_event and getattr(event, "name", None) == stop_on_event:
                        break
                except asyncio.TimeoutError:
                    yield ": keepalive\n\n"
        finally:
            await unsubscribe()

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