"""WS /v1/realtime — low-latency streaming transcription.

Auth: Bearer token via the Authorization header, or a ?token= query parameter
for clients that cannot set WS headers. The token is checked before the
handshake is accepted so an unauthenticated peer never streams audio.
"""
from __future__ import annotations

import hmac

from fastapi import APIRouter, Query, WebSocket
from loguru import logger

from ..realtime import EVT_ERROR, RealtimeSession

router = APIRouter()


def _token_ok(websocket: WebSocket, query_token: str) -> bool:
    configured = websocket.app.state.config.api_key
    header = websocket.headers.get("authorization", "")
    scheme, _, header_token = header.partition(" ")
    token = header_token.strip() if scheme.lower() == "bearer" else query_token
    return bool(token) and hmac.compare_digest(token, configured)


@router.websocket("/v1/realtime")
async def realtime(
    websocket: WebSocket,
    language: str = Query(""),
    token: str = Query(""),
) -> None:
    if not _token_ok(websocket, token):
        # Reject before accept: 1008 = policy violation.
        await websocket.close(code=1008)
        return

    engine = websocket.app.state.engine
    if not engine.is_ready:
        await websocket.accept()
        import json
        await websocket.send_text(json.dumps(
            {"type": EVT_ERROR, "error": {"message": "Engine not ready"}}))
        await websocket.close(code=1013)  # try again later
        return

    await websocket.accept()
    session = RealtimeSession(engine, language.strip() or None)
    try:
        # NOTE: do NOT hold engine.admit() for the whole session — that would
        # let one idle live connection starve every other client. Admission is
        # acquired per inference inside the session instead.
        await session.run(websocket)
    except Exception as e:  # noqa: BLE001
        logger.warning("Realtime session ended with error: {}", e)
    finally:
        try:
            await websocket.close()
        except Exception:  # noqa: BLE001
            pass
