"""Tests for transcriber module."""

from unittest.mock import MagicMock, patch

import numpy as np
import pytest

from voicemqtt.transcriber import Transcriber


class TestTranscriber:
    """Tests for Transcriber class."""
    
    def test_init_default_values(self):
        """Test initialization with default values."""
        transcriber = Transcriber()
        assert transcriber.model_size == "base"
        assert transcriber.device == "auto"
        assert transcriber.compute_type == "default"
        assert transcriber.model is None
    
    def test_init_custom_values(self):
        """Test initialization with custom values."""
        transcriber = Transcriber(
            model_size="small",
            device="cpu",
            compute_type="int8"
        )
        assert transcriber.model_size == "small"
        assert transcriber.device == "cpu"
        assert transcriber.compute_type == "int8"
    
    @patch("voicemqtt.transcriber.WhisperModel")
    def test_load_model(self, mock_whisper):
        """Test model loading."""
        transcriber = Transcriber(model_size="tiny")
        
        # Mock the model
        mock_model = MagicMock()
        mock_whisper.return_value = mock_model
        
        transcriber.load_model()
        
        assert transcriber.model is not None
        mock_whisper.assert_called_once()
    
    def test_load_model_already_loaded(self):
        """Test that load_model doesn't reload if already loaded."""
        transcriber = Transcriber()
        transcriber.model = MagicMock()
        
        with patch("voicemqtt.transcriber.WhisperModel") as mock_whisper:
            transcriber.load_model()
            mock_whisper.assert_not_called()
    
    @patch("voicemqtt.transcriber.WhisperModel")
    def test_transcribe(self, mock_whisper):
        """Test transcription."""
        transcriber = Transcriber()

        # Create mock model and segments
        mock_model = MagicMock()
        mock_segment1 = MagicMock(text="Hello")
        mock_segment2 = MagicMock(text="World")
        mock_info = MagicMock(language="en", language_probability=0.95)

        mock_model.transcribe.return_value = (
            [mock_segment1, mock_segment2],
            mock_info
        )

        mock_whisper.return_value = mock_model

        # Create test audio data
        audio_data = np.random.randn(16000).astype(np.float32)

        result = transcriber.transcribe(audio_data)

        assert result == "Hello World"
        mock_model.transcribe.assert_called_once()
    
    @patch("voicemqtt.transcriber.WhisperModel")
    def test_transcribe_empty_result(self, mock_whisper):
        """Test transcription with no speech."""
        transcriber = Transcriber()
        
        mock_model = MagicMock()
        mock_info = MagicMock(language="en", language_probability=0.95)
        mock_model.transcribe.return_value = ([], mock_info)
        
        mock_whisper.return_value = mock_model
        
        audio_data = np.random.randn(16000).astype(np.float32)
        result = transcriber.transcribe(audio_data)
        
        assert result == ""
    
    def test_transcribe_audio_conversion(self):
        """Test that audio data is properly converted."""
        transcriber = Transcriber()
        transcriber.model = MagicMock()
        transcriber.model.transcribe.return_value = ([], MagicMock())
        
        # Test with int16 data
        audio_data = np.array([1000, -1000, 500], dtype=np.int16)
        transcriber.transcribe(audio_data)
        
        # Verify transcribe was called
        transcriber.model.transcribe.assert_called_once()
        call_args = transcriber.model.transcribe.call_args
        passed_audio = call_args[0][0]
        assert passed_audio.dtype == np.float32
    
    def test_transcribe_stereo_to_mono(self):
        """Test stereo to mono conversion."""
        transcriber = Transcriber()
        transcriber.model = MagicMock()
        transcriber.model.transcribe.return_value = ([], MagicMock())
        
        # Create stereo audio
        audio_data = np.random.randn(16000, 2).astype(np.float32)
        transcriber.transcribe(audio_data)
        
        call_args = transcriber.model.transcribe.call_args
        passed_audio = call_args[0][0]
        assert len(passed_audio.shape) == 1  # Should be mono
