"""
Tests unitaires pour le moteur Vosk
"""

import pytest
from unittest.mock import Mock, patch, MagicMock
from pathlib import Path
import json

from asr.vosk_engine import VoskEngine


class TestVoskEngine:
    """Tests pour le moteur de reconnaissance Vosk."""

    @pytest.fixture
    def mock_vosk_model(self):
        """Mock du modèle Vosk."""
        return Mock()

    @pytest.fixture
    def mock_vosk_recognizer(self):
        """Mock du recognizer Vosk."""
        recognizer = Mock()
        recognizer.AcceptWaveform.return_value = True
        recognizer.Result.return_value = json.dumps({"text": "bonjour skull"})
        recognizer.PartialResult.return_value = json.dumps({"partial": "bonjour"})
        recognizer.FinalResult.return_value = json.dumps({"text": "bonjour skull"})
        recognizer.SetWords = Mock()
        recognizer.SetPartialWords = Mock()
        return recognizer

    def test_model_path_resolution(self):
        """Test la résolution du chemin vers le modèle."""
        engine = VoskEngine("fr", 16000)

        with patch.object(Path, "exists", return_value=True):
            model_path = engine._get_model_path()
            assert "vosk-model-fr" in str(model_path)

    @pytest.mark.asyncio
    async def test_engine_initialization(self, mock_vosk_model, mock_vosk_recognizer):
        """Test l'initialisation du moteur."""
        engine = VoskEngine("fr", 16000)

        with patch("asr.vosk_engine.vosk") as mock_vosk:
            with patch.object(engine, "_get_model_path") as mock_path:
                mock_path.return_value = Path("/tmp/test-model")
                mock_path.return_value.exists = Mock(return_value=True)

                mock_vosk.Model.return_value = mock_vosk_model
                mock_vosk.KaldiRecognizer.return_value = mock_vosk_recognizer

                await engine.initialize()

                assert engine.model == mock_vosk_model
                assert engine.recognizer == mock_vosk_recognizer
                mock_vosk_recognizer.SetWords.assert_called_once_with(True)
                mock_vosk_recognizer.SetPartialWords.assert_called_once_with(True)

    def test_audio_processing(self, mock_vosk_recognizer):
        """Test le traitement des données audio."""
        engine = VoskEngine("fr", 16000)
        engine.recognizer = mock_vosk_recognizer

        # Test avec résultat disponible
        audio_data = b"\x00\x00" * 1024
        result = engine.process_audio(audio_data)

        mock_vosk_recognizer.AcceptWaveform.assert_called_once_with(audio_data)
        assert result == "bonjour skull"

    def test_partial_result(self, mock_vosk_recognizer):
        """Test la récupération du résultat partiel."""
        engine = VoskEngine("fr", 16000)
        engine.recognizer = mock_vosk_recognizer

        result = engine.get_partial_result()
        assert result == "bonjour"

    def test_final_result(self, mock_vosk_recognizer):
        """Test la récupération du résultat final."""
        engine = VoskEngine("fr", 16000)
        engine.recognizer = mock_vosk_recognizer

        result = engine.get_final_result()
        assert result == "bonjour skull"

    def test_reset(self, mock_vosk_model, mock_vosk_recognizer):
        """Test la remise à zéro du recognizer."""
        engine = VoskEngine("fr", 16000)
        engine.model = mock_vosk_model
        engine.recognizer = Mock()

        with patch("asr.vosk_engine.vosk") as mock_vosk:
            mock_vosk.KaldiRecognizer.return_value = mock_vosk_recognizer

            engine.reset()

            mock_vosk.KaldiRecognizer.assert_called_once_with(mock_vosk_model, 16000)

    def test_is_ready(self):
        """Test la vérification de l'état du moteur."""
        engine = VoskEngine("fr", 16000)

        # Moteur non initialisé
        assert engine.is_ready() is False

        # Moteur initialisé
        engine.model = Mock()
        engine.recognizer = Mock()
        assert engine.is_ready() is True

    @pytest.mark.asyncio
    async def test_cleanup(self):
        """Test le nettoyage des ressources."""
        engine = VoskEngine("fr", 16000)
        engine.model = Mock()
        engine.recognizer = Mock()

        await engine.cleanup()

        assert engine.model is None
        assert engine.recognizer is None
