"""
Tests for the GoogleTranslationProvider.
"""

import pytest
from unittest.mock import patch, MagicMock

from services.providers.google_provider import (
    GoogleTranslationProvider,
    get_google_provider,
)
from services.providers.schemas import TranslationRequest, TranslationResponse


class TestGoogleTranslationProvider:
    """Tests for GoogleTranslationProvider."""

    @pytest.fixture
    def provider(self):
        """Create a Google provider instance."""
        return GoogleTranslationProvider(use_cache=False)

    @pytest.fixture
    def provider_with_cache(self):
        """Create a Google provider with caching enabled."""
        return GoogleTranslationProvider(use_cache=True)

    def test_get_name(self, provider):
        """Test provider name."""
        assert provider.get_name() == "google"

    def test_is_available(self, provider):
        """Test availability check."""
        result = provider.is_available()
        assert isinstance(result, bool)

    def test_translate_text_empty(self, provider):
        """Test translating empty text."""
        request = TranslationRequest(text="", target_language="fr")
        response = provider.translate_text(request)

        assert response.translated_text == ""
        assert response.provider_name == "google"
        assert response.from_cache is False

    def test_translate_text_whitespace(self, provider):
        """Test translating whitespace-only text."""
        request = TranslationRequest(text="   ", target_language="fr")
        response = provider.translate_text(request)

        assert response.translated_text == "   "

    @patch(
        "services.providers.google_provider.GoogleTranslationProvider._get_translator"
    )
    def test_translate_text_success(self, mock_get_translator, provider):
        """Test successful translation."""
        mock_translator = MagicMock()
        mock_translator.translate.return_value = "Bonjour"
        mock_get_translator.return_value = mock_translator

        request = TranslationRequest(text="Hello", target_language="fr")
        response = provider.translate_text(request)

        assert response.translated_text == "Bonjour"
        assert response.provider_name == "google"
        assert response.from_cache is False

    @patch(
        "services.providers.google_provider.GoogleTranslationProvider._get_translator"
    )
    def test_translate_text_with_source_language(self, mock_get_translator, provider):
        """Test translation with explicit source language."""
        mock_translator = MagicMock()
        mock_translator.translate.return_value = "Bonjour"
        mock_get_translator.return_value = mock_translator

        request = TranslationRequest(
            text="Hello", target_language="fr", source_language="en"
        )
        response = provider.translate_text(request)

        mock_get_translator.assert_called_once_with("en", "fr")
        assert response.translated_text == "Bonjour"

    @patch(
        "services.providers.google_provider.GoogleTranslationProvider._get_translator"
    )
    def test_translate_text_error_fallback(self, mock_get_translator, provider):
        """Test that translation errors return original text and structured error (Story 2.2)."""
        mock_get_translator.side_effect = Exception("API Error")

        request = TranslationRequest(text="Hello", target_language="fr")
        response = provider.translate_text(request)

        assert response.translated_text == "Hello"
        assert response.provider_name == "google"
        assert response.error is not None
        assert response.error_code is not None

    def test_translate_batch_empty(self, provider):
        """Test batch translation with empty list."""
        responses = provider.translate_batch([])
        assert responses == []

    @patch.object(GoogleTranslationProvider, "translate_text")
    def test_translate_batch(self, mock_translate, provider):
        """Test batch translation."""
        mock_translate.side_effect = [
            TranslationResponse(translated_text="Bonjour", provider_name="google"),
            TranslationResponse(translated_text="Monde", provider_name="google"),
        ]

        requests = [
            TranslationRequest(text="Hello", target_language="fr"),
            TranslationRequest(text="World", target_language="fr"),
        ]
        responses = provider.translate_batch(requests)

        assert len(responses) == 2
        assert responses[0].translated_text == "Bonjour"
        assert responses[1].translated_text == "Monde"

    def test_health_check(self, provider):
        """Test health check."""
        status = provider.health_check()

        assert status.name == "google"
        assert isinstance(status.available, bool)
        assert status.latency_ms is not None

    def test_get_google_provider_singleton(self):
        """Test that get_google_provider returns same instance."""
        provider1 = get_google_provider()
        provider2 = get_google_provider()

        assert provider1 is provider2


class TestGoogleProviderCaching:
    """Tests for Google provider caching functionality."""

    @pytest.fixture
    def mock_cache(self):
        """Create a mock cache."""
        cache = MagicMock()
        cache.get.return_value = None
        return cache

    def test_cache_hit(self, mock_cache):
        """Test that cache hits return cached result."""
        mock_cache.get.return_value = "Cached Translation"

        provider = GoogleTranslationProvider(use_cache=True)
        provider._cache = mock_cache

        request = TranslationRequest(text="Hello", target_language="fr")
        response = provider.translate_text(request)

        assert response.translated_text == "Cached Translation"
        assert response.from_cache is True

    @patch(
        "services.providers.google_provider.GoogleTranslationProvider._get_translator"
    )
    def test_cache_set_on_miss(self, mock_get_translator, mock_cache):
        """Test that translations are cached on miss."""
        mock_translator = MagicMock()
        mock_translator.translate.return_value = "Bonjour"
        mock_get_translator.return_value = mock_translator

        provider = GoogleTranslationProvider(use_cache=True)
        provider._cache = mock_cache

        request = TranslationRequest(text="Hello", target_language="fr")
        provider.translate_text(request)

        mock_cache.set.assert_called_once_with(
            "Hello", "fr", "auto", "google", "Bonjour"
        )
