"""Czekanie na element kolejki bez blokowania event loopu."""

from __future__ import annotations

import asyncio
import queue
from typing import TypeVar

T = TypeVar("T")

# Kolejkę promptów wypełnia wątek transkrypcji, a what_next jest korutyną serwera
# MCP. Blokujące queue.get zamroziłoby event loop na czas oczekiwania: transport
# nie odpowiadałby, a samo wywołanie stałoby się nieprzerywalne — przy limicie
# liczonym w minutach to znaczy martwy serwer do restartu. Dlatego odpytujemy
# kolejkę krótkimi krokami i oddajemy sterowanie loopowi między nimi.
POLL_INTERVAL_S = 0.2


async def wait_for_item(
    source: queue.Queue[T],
    timeout: float,
    poll_interval_s: float = POLL_INTERVAL_S,
) -> T:
    """Zwraca pierwszy element kolejki; po `timeout` sekundach rzuca `queue.Empty`.

    Element zdejmujemy wyłącznie wtedy, gdy zaraz go zwrócimy. Oczekiwanie bywa
    anulowane (host zerwał wywołanie narzędzia), a zabranie promptu, na który
    nikt już nie czeka, to zgubiona wypowiedź użytkownika.
    """
    loop = asyncio.get_running_loop()
    deadline = loop.time() + timeout

    while True:
        try:
            return source.get_nowait()
        except queue.Empty:
            remaining = deadline - loop.time()
            if remaining <= 0:
                raise

        await asyncio.sleep(min(poll_interval_s, remaining))
