"""
Tests for Ollama embedding provider.
"""

from unittest.mock import Mock, patch
import requests

from src.local_deep_research.embeddings.providers.implementations.ollama import (
    OllamaEmbeddingsProvider,
)


class TestOllamaEmbeddingsProviderMetadata:
    """Tests for OllamaEmbeddingsProvider class metadata."""

    def test_provider_name(self):
        """Provider name is 'Ollama'."""
        assert OllamaEmbeddingsProvider.provider_name == "Ollama"

    def test_provider_key(self):
        """Provider key is 'OLLAMA'."""
        assert OllamaEmbeddingsProvider.provider_key == "OLLAMA"

    def test_requires_api_key_false(self):
        """Does not require API key."""
        assert OllamaEmbeddingsProvider.requires_api_key is False

    def test_supports_local_true(self):
        """Supports local execution."""
        assert OllamaEmbeddingsProvider.supports_local is True

    def test_default_model(self):
        """Has a default embedding model."""
        assert OllamaEmbeddingsProvider.default_model == "nomic-embed-text"


class TestOllamaEmbeddingsIsAvailable:
    """Tests for is_available method."""

    def test_available_when_server_responds(self):
        """Returns True when Ollama server responds."""
        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.get_ollama_base_url"
        ) as mock_get_url:
            mock_get_url.return_value = "http://localhost:11434"

            with patch("requests.get") as mock_get:
                mock_response = Mock()
                mock_response.status_code = 200
                mock_get.return_value = mock_response

                result = OllamaEmbeddingsProvider.is_available()
                assert result is True

    def test_not_available_when_server_error(self):
        """Returns False when server returns error."""
        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.get_ollama_base_url"
        ) as mock_get_url:
            mock_get_url.return_value = "http://localhost:11434"

            with patch("requests.get") as mock_get:
                mock_response = Mock()
                mock_response.status_code = 500
                mock_get.return_value = mock_response

                result = OllamaEmbeddingsProvider.is_available()
                assert result is False

    def test_not_available_when_connection_fails(self):
        """Returns False when connection fails."""
        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.get_ollama_base_url"
        ) as mock_get_url:
            mock_get_url.return_value = "http://localhost:11434"

            with patch("requests.get") as mock_get:
                mock_get.side_effect = requests.exceptions.ConnectionError()

                result = OllamaEmbeddingsProvider.is_available()
                assert result is False

    def test_not_available_when_timeout(self):
        """Returns False when request times out."""
        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.get_ollama_base_url"
        ) as mock_get_url:
            mock_get_url.return_value = "http://localhost:11434"

            with patch("requests.get") as mock_get:
                mock_get.side_effect = requests.exceptions.Timeout()

                result = OllamaEmbeddingsProvider.is_available()
                assert result is False


class TestOllamaEmbeddingsCreate:
    """Tests for create_embeddings method."""

    def test_create_with_default_model(self):
        """Creates embeddings with default model."""
        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.get_setting_from_snapshot"
        ) as mock_get_setting:
            mock_get_setting.return_value = "nomic-embed-text"

            with patch(
                "src.local_deep_research.embeddings.providers.implementations.ollama.get_ollama_base_url"
            ) as mock_get_url:
                mock_get_url.return_value = "http://localhost:11434"

                with patch(
                    "src.local_deep_research.embeddings.providers.implementations.ollama.OllamaEmbeddings"
                ) as mock_ollama:
                    mock_instance = Mock()
                    mock_ollama.return_value = mock_instance

                    result = OllamaEmbeddingsProvider.create_embeddings()

                    assert result is mock_instance
                    mock_ollama.assert_called_once()
                    call_kwargs = mock_ollama.call_args[1]
                    assert call_kwargs["model"] == "nomic-embed-text"

    def test_create_with_custom_model(self):
        """Creates embeddings with custom model."""
        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.get_ollama_base_url"
        ) as mock_get_url:
            mock_get_url.return_value = "http://localhost:11434"

            with patch(
                "src.local_deep_research.embeddings.providers.implementations.ollama.OllamaEmbeddings"
            ) as mock_ollama:
                mock_instance = Mock()
                mock_ollama.return_value = mock_instance

                OllamaEmbeddingsProvider.create_embeddings(
                    model="mxbai-embed-large"
                )

                call_kwargs = mock_ollama.call_args[1]
                assert call_kwargs["model"] == "mxbai-embed-large"

    def test_create_with_custom_base_url(self):
        """Creates embeddings with custom base URL."""
        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.OllamaEmbeddings"
        ) as mock_ollama:
            mock_instance = Mock()
            mock_ollama.return_value = mock_instance

            OllamaEmbeddingsProvider.create_embeddings(
                model="nomic-embed-text",
                base_url="http://custom:8080",
            )

            call_kwargs = mock_ollama.call_args[1]
            assert call_kwargs["base_url"] == "http://custom:8080"

    def test_create_uses_settings_snapshot(self):
        """Uses settings snapshot when provided."""
        mock_settings = {"embeddings.ollama.model": "custom-model"}

        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.get_setting_from_snapshot"
        ) as mock_get_setting:
            mock_get_setting.return_value = "custom-model"

            with patch(
                "src.local_deep_research.embeddings.providers.implementations.ollama.get_ollama_base_url"
            ) as mock_get_url:
                mock_get_url.return_value = "http://localhost:11434"

                with patch(
                    "src.local_deep_research.embeddings.providers.implementations.ollama.OllamaEmbeddings"
                ):
                    OllamaEmbeddingsProvider.create_embeddings(
                        settings_snapshot=mock_settings
                    )

                    # Verify get_setting_from_snapshot was called with settings
                    mock_get_setting.assert_called()


class TestOllamaEmbeddingsGetAvailableModels:
    """Tests for get_available_models method."""

    def test_get_available_models_calls_fetch(
        self, mock_ollama_models_response
    ):
        """Calls fetch_ollama_models to get models."""
        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.get_ollama_base_url"
        ) as mock_get_url:
            mock_get_url.return_value = "http://localhost:11434"

            with patch(
                "src.local_deep_research.utilities.llm_utils.fetch_ollama_models"
            ) as mock_fetch:
                mock_fetch.return_value = [
                    {
                        "value": "nomic-embed-text:latest",
                        "label": "nomic-embed-text",
                    },
                    {"value": "all-minilm:latest", "label": "all-minilm"},
                ]

                result = OllamaEmbeddingsProvider.get_available_models()

                assert isinstance(result, list)
                assert len(result) == 2

    def test_get_available_models_returns_list(self):
        """Returns a list of model dictionaries."""
        with patch(
            "src.local_deep_research.embeddings.providers.implementations.ollama.get_ollama_base_url"
        ) as mock_get_url:
            mock_get_url.return_value = "http://localhost:11434"

            with patch(
                "src.local_deep_research.utilities.llm_utils.fetch_ollama_models"
            ) as mock_fetch:
                mock_fetch.return_value = [
                    {"value": "model1", "label": "Model 1"},
                ]

                result = OllamaEmbeddingsProvider.get_available_models()

                assert isinstance(result, list)
                if len(result) > 0:
                    assert "value" in result[0]
                    assert "label" in result[0]


class TestOllamaEmbeddingsProviderInfo:
    """Tests for get_provider_info method."""

    def test_provider_info_structure(self):
        """get_provider_info returns expected structure."""
        info = OllamaEmbeddingsProvider.get_provider_info()

        assert "name" in info
        assert "key" in info
        assert "requires_api_key" in info
        assert "supports_local" in info
        assert "default_model" in info

        assert info["name"] == "Ollama"
        assert info["key"] == "OLLAMA"
        assert info["requires_api_key"] is False
        assert info["supports_local"] is True


class TestOllamaEmbeddingsValidateConfig:
    """Tests for validate_config method."""

    def test_validate_config_when_available(self):
        """validate_config returns True when available."""
        with patch.object(
            OllamaEmbeddingsProvider, "is_available", return_value=True
        ):
            is_valid, error = OllamaEmbeddingsProvider.validate_config()
            assert is_valid is True
            assert error is None

    def test_validate_config_when_not_available(self):
        """validate_config returns False when not available."""
        with patch.object(
            OllamaEmbeddingsProvider, "is_available", return_value=False
        ):
            is_valid, error = OllamaEmbeddingsProvider.validate_config()
            assert is_valid is False
            assert error is not None
            assert "not available" in error
