"""Voice input MVP for Avatar chat (0.2.0.3+, deps hotfix 0.2.0.5)."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any


@dataclass(frozen=True)
class VoiceInputResult:
    ok: bool
    text: str = ""
    error_key: str | None = None


def voice_dependency_status() -> dict[str, bool]:
    """Report optional speech-to-text dependencies for diagnostics and UI hints."""
    status = {
        "speech_recognition": False,
        "pyaudio": False,
        "microphone": False,
    }
    try:
        import speech_recognition as sr  # type: ignore

        status["speech_recognition"] = True
        try:
            import pyaudio  # type: ignore  # noqa: F401

            status["pyaudio"] = True
        except Exception:
            return status
        try:
            sr.Microphone.list_microphone_names()
            status["microphone"] = True
        except Exception:
            pass
    except Exception:
        pass
    return status


def _missing_voice_error_key(status: dict[str, bool]) -> str:
    if not status.get("speech_recognition"):
        return "avatar.input.voice_deps_missing"
    if not status.get("pyaudio"):
        return "avatar.input.voice_pyaudio_missing"
    if not status.get("microphone"):
        return "avatar.input.voice_capture_failed"
    return "avatar.input.voice_not_configured"


def request_voice_input() -> VoiceInputResult:
    """Capture speech-to-text when configured; otherwise return a stable i18n error key."""
    status = voice_dependency_status()
    if not status["speech_recognition"] or not status["pyaudio"]:
        return VoiceInputResult(ok=False, error_key=_missing_voice_error_key(status))

    import speech_recognition as sr  # type: ignore

    recognizer = sr.Recognizer()
    try:
        with sr.Microphone() as source:
            recognizer.adjust_for_ambient_noise(source, duration=0.3)
            audio = recognizer.listen(source, timeout=8, phrase_time_limit=30)
    except Exception:
        return VoiceInputResult(ok=False, error_key="avatar.input.voice_capture_failed")

    backends: list[Any] = [
        lambda: recognizer.recognize_google(audio, language="ru-RU"),
        lambda: recognizer.recognize_google(audio, language="en-US"),
    ]
    try:
        import pocketsphinx  # type: ignore  # noqa: F401

        backends.insert(0, lambda: recognizer.recognize_sphinx(audio, language="ru-RU"))
    except Exception:
        pass

    for backend in backends:
        try:
            text = str(backend() or "").strip()
            if text:
                return VoiceInputResult(ok=True, text=text)
        except Exception:
            continue
    return VoiceInputResult(ok=False, error_key="avatar.input.voice_not_configured")
