from __future__ import annotations

import logging
import queue
import threading
from pathlib import Path

from lib.user_selection import UserSelectionMismatchError, build_user_selection_block

from .prompt_wait import wait_for_item
from .server import start_server
from .speech_to_text import SpeechToText


# plik audio, xpathy kliknięć, ekran widoczny przy wysyłce, ekrany kliknięć, momenty kliknięć
AudioItem = tuple[Path, "list[str] | str | None", str | None, "list[str] | None", "list[str] | None"]


class NextPromptManager:
    def __init__(self):
        self._audio_queue: queue.Queue[AudioItem] = queue.Queue()
        self._prompt_queue: queue.Queue[str | UserSelectionMismatchError] = queue.Queue()

        self._worker = threading.Thread(target=self._worker_loop, daemon=True)
        self._worker.start()

        self._server_thread = threading.Thread(
            target=start_server,
            args=(self,),
            daemon=True,
        )
        self._server_thread.start()

    def submit_audio(
        self,
        audio_path: Path,
        xpath: list[str] | str | None = None,
        page_hash: str | None = None,
        xpath_hashes: list[str] | None = None,
        xpath_times: list[str] | None = None,
    ) -> None:
        self._audio_queue.put((audio_path, xpath, page_hash, xpath_hashes, xpath_times))

    def next_prompt(self, timeout: float = 270) -> str:
        """Wersja blokująca — dla wołających spoza event loopu (tests/test.py)."""
        return self._unwrap(self._prompt_queue.get(timeout=timeout))

    async def next_prompt_async(self, timeout: float) -> str:
        """Wersja dla what_next: czeka, nie zajmując event loopu serwera MCP."""
        return self._unwrap(await wait_for_item(self._prompt_queue, timeout))

    @staticmethod
    def _unwrap(item: str | UserSelectionMismatchError) -> str:
        if isinstance(item, UserSelectionMismatchError):
            raise item
        return item

    def _worker_loop(self) -> None:
        while True:
            audio_path, xpath, page_hash, xpath_hashes, xpath_times = self._audio_queue.get()
            try:
                result = SpeechToText.process_webm_file(audio_path)
                text = result["fixed_text"]

                try:
                    selection_block = build_user_selection_block(
                        xpath, page_hash, xpath_hashes, xpath_times
                    )
                except UserSelectionMismatchError as e:
                    logging.warning(f"user_selection mismatch: {e}")
                    self._prompt_queue.put(e)
                    continue

                if selection_block:
                    text = f"{text}\n\n{selection_block}"

                self._prompt_queue.put(text)
                logging.info(f"Dodano nowy prompt do kolejki: {text}")
            except Exception as e:
                logging.error(f"Błąd przetwarzania audio {audio_path}: {e}")
            finally:
                SpeechToText._remove_file_quietly(audio_path)


next_prompt_manager = NextPromptManager()