"""
Moteur de reconnaissance vocale utilisant Vosk
"""

import json
import logging
from pathlib import Path
from typing import Optional

try:
    import vosk
except ImportError:
    logging.error("Module vosk non installé. Installer avec: pip install vosk")
    raise


class VoskEngine:
    """Moteur ASR basé sur Vosk pour la reconnaissance vocale française."""

    # Mapping des langues vers les modèles
    MODEL_MAPPING = {
        "fr": "vosk-model-fr-0.22-lgraph",
        "en": "vosk-model-en-us-0.22-lgraph",
    }

    def __init__(self, lang: str = "fr", sample_rate: int = 16000) -> None:
        self.logger = logging.getLogger(__name__)
        self.lang = lang
        self.sample_rate = sample_rate
        self.model: Optional[vosk.Model] = None
        self.recognizer: Optional[vosk.KaldiRecognizer] = None

    async def initialize(self) -> None:
        """Initialise le moteur Vosk avec le modèle approprié."""
        model_path = self._get_model_path()

        if not model_path.exists():
            raise FileNotFoundError(
                f"Modèle Vosk non trouvé: {model_path}\n"
                f"Téléchargez-le depuis: https://alphacephei.com/vosk/models"
            )

        self.logger.info(f"Chargement du modèle Vosk: {model_path}")

        # Initialiser le modèle
        self.model = vosk.Model(str(model_path))
        self.recognizer = vosk.KaldiRecognizer(self.model, self.sample_rate)

        # Configurer la reconnaissance
        self.recognizer.SetWords(True)
        self.recognizer.SetPartialWords(True)

        self.logger.info("Moteur Vosk initialisé")

    def _get_model_path(self) -> Path:
        """Retourne le chemin vers le modèle Vosk."""
        model_name = self.MODEL_MAPPING.get(self.lang, self.MODEL_MAPPING["fr"])

        # Rechercher dans plusieurs emplacements possibles
        search_paths = [
            Path("/opt/Skull/models") / model_name,
            Path("./models") / model_name,
            Path(f"~/.cache/vosk/{model_name}").expanduser(),
            Path(f"/tmp/{model_name}"),
        ]

        for path in search_paths:
            if path.exists():
                return path

        # Retourner le chemin par défaut pour l'erreur
        return search_paths[0]

    def reset(self) -> None:
        """Remet à zéro le recognizer pour une nouvelle session."""
        if self.recognizer:
            self.recognizer = vosk.KaldiRecognizer(self.model, self.sample_rate)
            self.recognizer.SetWords(True)
            self.recognizer.SetPartialWords(True)

    def process_audio(self, audio_data: bytes) -> Optional[str]:
        """
        Traite un chunk audio et retourne le texte partiel si disponible.

        Args:
            audio_data: Données audio PCM 16-bit mono

        Returns:
            Texte partiel ou None
        """
        if not self.recognizer:
            return None

        if self.recognizer.AcceptWaveform(audio_data):
            result = json.loads(self.recognizer.Result())
            return result.get("text", "").strip()

        return None

    def get_partial_result(self) -> str:
        """Retourne le résultat partiel actuel."""
        if not self.recognizer:
            return ""

        result = json.loads(self.recognizer.PartialResult())
        return result.get("partial", "").strip()

    def get_final_result(self) -> str:
        """Retourne le résultat final de la reconnaissance."""
        if not self.recognizer:
            return ""

        result = json.loads(self.recognizer.FinalResult())
        return result.get("text", "").strip()

    async def cleanup(self) -> None:
        """Nettoie les ressources utilisées."""
        self.logger.info("Nettoyage du moteur Vosk")
        self.recognizer = None
        self.model = None

    def is_ready(self) -> bool:
        """Vérifie si le moteur est prêt à traiter l'audio."""
        return self.model is not None and self.recognizer is not None
