from unittest.mock import MagicMock, patch

import pytest

from app.services.translate import TranslateService


class TestTranslateService:
    """Test Google Translate service functionality"""

    @pytest.fixture
    def translate_service(self):
        """Create translate service with mocked client"""
        with patch('app.services.translate.translate.Client') as mock_client:
            service = TranslateService()
            service.client = MagicMock()
            return service

    @pytest.fixture
    def sample_vtt(self):
        """Sample VTT content for testing"""
        return """WEBVTT

00:00:01.000 --> 00:00:03.000
Hello everyone

00:00:04.000 --> 00:00:06.000
Welcome to our tutorial

00:00:07.000 --> 00:00:09.000
Let's get started
"""

    @pytest.mark.asyncio
    async def test_translate_vtt_success(self, translate_service, sample_vtt):
        """Test successful VTT translation"""
        # Mock translation results
        translate_service.client.translate.return_value = [
            {"translatedText": "Hola a todos"},
            {"translatedText": "Bienvenidos a nuestro tutorial"},
            {"translatedText": "Empecemos"}
        ]
        
        result = await translate_service.translate_vtt(sample_vtt, "es")
        
        # Verify structure is preserved
        assert "WEBVTT" in result
        assert "00:00:01.000 --> 00:00:03.000" in result
        assert "00:00:04.000 --> 00:00:06.000" in result
        assert "00:00:07.000 --> 00:00:09.000" in result
        
        # Verify translation content
        assert "Hola a todos" in result
        assert "Bienvenidos a nuestro tutorial" in result
        assert "Empecemos" in result

    @pytest.mark.asyncio
    async def test_translate_vtt_single_result(self, translate_service, sample_vtt):
        """Test VTT translation with single result format"""
        # Some Google Translate responses return single dict instead of list
        translate_service.client.translate.return_value = {
            "translatedText": "Hola a todos"
        }
        
        # Create VTT with single cue
        single_cue_vtt = """WEBVTT

00:00:01.000 --> 00:00:03.000
Hello everyone
"""
        
        result = await translate_service.translate_vtt(single_cue_vtt, "es")
        
        assert "Hola a todos" in result
        assert "00:00:01.000 --> 00:00:03.000" in result

    @pytest.mark.asyncio
    async def test_translate_vtt_empty_content(self, translate_service):
        """Test translation of VTT with no cues"""
        empty_vtt = """WEBVTT

"""
        
        result = await translate_service.translate_vtt(empty_vtt, "es")
        
        # Should return original content if no cues to translate
        assert result == empty_vtt

    @pytest.mark.asyncio
    async def test_translate_vtt_no_client(self):
        """Test translation when client is not configured"""
        service = TranslateService()
        service.client = None
        
        with pytest.raises(ValueError, match="Google Translate not configured"):
            await service.translate_vtt("WEBVTT\n", "es")

    @pytest.mark.asyncio
    async def test_translate_vtt_api_error(self, translate_service, sample_vtt):
        """Test handling of Google Translate API errors"""
        translate_service.client.translate.side_effect = Exception("API Error")
        
        with pytest.raises(Exception, match="API Error"):
            await translate_service.translate_vtt(sample_vtt, "es")

    def test_parse_vtt_cues_simple(self, translate_service):
        """Test parsing simple VTT cues"""
        vtt_content = """WEBVTT

00:00:01.000 --> 00:00:03.000
Hello world

00:00:04.000 --> 00:00:06.000
This is a test
"""
        
        cues = translate_service._parse_vtt_cues(vtt_content)
        
        assert len(cues) == 2
        assert cues[0]["start"] == "00:00:01.000"
        assert cues[0]["end"] == "00:00:03.000"
        assert cues[0]["text"] == "Hello world"
        assert cues[1]["text"] == "This is a test"

    def test_parse_vtt_cues_multiline(self, translate_service):
        """Test parsing VTT cues with multi-line text"""
        vtt_content = """WEBVTT

00:00:01.000 --> 00:00:03.000
First line
Second line

00:00:04.000 --> 00:00:06.000
Another cue
"""
        
        cues = translate_service._parse_vtt_cues(vtt_content)
        
        assert len(cues) == 2
        # Note: Current implementation joins lines with space
        assert "First line Second line" in cues[0]["text"]

    def test_parse_vtt_cues_with_notes(self, translate_service):
        """Test parsing VTT with NOTE sections"""
        vtt_content = """WEBVTT

NOTE This is a note section

00:00:01.000 --> 00:00:03.000
Hello world
"""
        
        cues = translate_service._parse_vtt_cues(vtt_content)
        
        assert len(cues) == 1
        assert cues[0]["text"] == "Hello world"

    def test_build_vtt_simple(self, translate_service):
        """Test building VTT from cues"""
        cues = [
            {
                "start": "00:00:01.000",
                "end": "00:00:03.000", 
                "text": "Hola mundo"
            },
            {
                "start": "00:00:04.000",
                "end": "00:00:06.000",
                "text": "Esta es una prueba"
            }
        ]
        
        result = translate_service._build_vtt(cues)
        
        expected = """WEBVTT

00:00:01.000 --> 00:00:03.000
Hola mundo

00:00:04.000 --> 00:00:06.000
Esta es una prueba

"""
        
        assert result == expected

    def test_build_vtt_empty(self, translate_service):
        """Test building VTT from empty cues"""
        cues = []
        
        result = translate_service._build_vtt(cues)
        
        assert result == "WEBVTT\n"

    @pytest.mark.asyncio
    async def test_translate_vtt_preserves_timing(self, translate_service):
        """Test that translation preserves exact timing"""
        original_vtt = """WEBVTT

00:00:01.234 --> 00:00:03.567
Original text

00:00:05.890 --> 00:00:08.123
Another line
"""
        
        translate_service.client.translate.return_value = [
            {"translatedText": "Texto original"},
            {"translatedText": "Otra línea"}
        ]
        
        result = await translate_service.translate_vtt(original_vtt, "es")
        
        # Check that exact timestamps are preserved
        assert "00:00:01.234 --> 00:00:03.567" in result
        assert "00:00:05.890 --> 00:00:08.123" in result
        assert "Texto original" in result
        assert "Otra línea" in result

    def test_service_initialization_with_api_key(self):
        """Test service initialization when API key is configured"""
        with patch('app.services.translate.settings') as mock_settings:
            mock_settings.translate_api_key = "test_api_key"
            
            with patch('app.services.translate.translate.Client') as mock_client:
                service = TranslateService()
                
                mock_client.assert_called_once()
                assert service.client is not None

    def test_service_initialization_without_api_key(self):
        """Test service initialization when API key is not configured"""
        with patch('app.services.translate.settings') as mock_settings:
            mock_settings.translate_api_key = ""
            
            service = TranslateService()
            
            assert service.client is None