"""
Tests for LLM provider classes.

Tests cover:
- ProviderInfo class
- ProviderDiscovery class
- OpenAICompatibleProvider base class
- Individual provider implementations
"""

from unittest.mock import Mock

from local_deep_research.llm.providers.base import BaseLLMProvider


class TestProviderInfo:
    """Tests for ProviderInfo class."""

    def test_provider_info_initialization(self):
        """ProviderInfo initializes with provider class."""
        from local_deep_research.llm.providers.auto_discovery import (
            ProviderInfo,
        )

        # Create a mock provider class
        mock_provider = Mock()
        mock_provider.__name__ = "TestProvider"
        mock_provider.provider_name = "Test Provider"
        mock_provider.provider_key = "TEST"
        mock_provider.company_name = "Test Company"
        mock_provider.is_cloud = True
        mock_provider.requires_auth_for_models.return_value = True

        info = ProviderInfo(mock_provider)

        assert info.provider_key == "TEST"
        assert info.provider_name == "Test Provider"
        assert info.company_name == "Test Company"
        assert info.is_cloud is True

    def test_provider_info_defaults(self):
        """ProviderInfo uses defaults for missing attributes."""
        from local_deep_research.llm.providers.auto_discovery import (
            ProviderInfo,
        )

        class MinimalProvider(BaseLLMProvider):
            provider_name = "Minimal"

        info = ProviderInfo(MinimalProvider)

        assert info.provider_name == "Minimal"
        assert info.is_cloud is True

    def test_provider_info_to_dict(self):
        """ProviderInfo converts to dictionary."""
        from local_deep_research.llm.providers.auto_discovery import (
            ProviderInfo,
        )

        mock_provider = Mock()
        mock_provider.__name__ = "TestProvider"
        mock_provider.provider_name = "Test"
        mock_provider.provider_key = "TEST"
        mock_provider.company_name = "Test"
        mock_provider.is_cloud = True
        mock_provider.requires_auth_for_models.return_value = False

        info = ProviderInfo(mock_provider)
        result = info.to_dict()

        assert isinstance(result, dict)
        assert result["value"] == "TEST"
        assert "label" in result
        assert result["is_cloud"] is True

    def test_display_name_local_provider(self):
        """Display name shows local indicator."""
        from local_deep_research.llm.providers.auto_discovery import (
            ProviderInfo,
        )

        mock_provider = Mock()
        mock_provider.__name__ = "LocalProvider"
        mock_provider.provider_name = "Local Provider"
        mock_provider.provider_key = "LOCAL"
        mock_provider.is_cloud = False
        mock_provider.requires_auth_for_models.return_value = False

        info = ProviderInfo(mock_provider)

        assert "Local" in info.display_name


class TestProviderDiscovery:
    """Tests for ProviderDiscovery class."""

    def test_provider_discovery_singleton(self):
        """ProviderDiscovery is a singleton."""
        from local_deep_research.llm.providers.auto_discovery import (
            ProviderDiscovery,
        )

        discovery1 = ProviderDiscovery()
        discovery2 = ProviderDiscovery()

        assert discovery1 is discovery2

    def test_discover_providers_returns_dict(self):
        """discover_providers returns a dictionary."""
        from local_deep_research.llm.providers.auto_discovery import (
            ProviderDiscovery,
        )

        discovery = ProviderDiscovery()
        result = discovery.discover_providers()

        assert isinstance(result, dict)

    def test_discover_providers_finds_implementations(self):
        """discover_providers finds provider implementations."""
        from local_deep_research.llm.providers.auto_discovery import (
            ProviderDiscovery,
        )

        discovery = ProviderDiscovery()
        providers = discovery.discover_providers()

        # Should find at least some providers
        assert len(providers) >= 0

    def test_discover_providers_values_are_provider_info(self):
        """discover_providers returns ProviderInfo values."""
        from local_deep_research.llm.providers.auto_discovery import (
            ProviderDiscovery,
            ProviderInfo,
        )

        discovery = ProviderDiscovery()
        providers = discovery.discover_providers()

        for key, info in providers.items():
            assert isinstance(info, ProviderInfo)

    def test_providers_dict_accessible(self):
        """_providers dict is accessible after discovery."""
        from local_deep_research.llm.providers.auto_discovery import (
            ProviderDiscovery,
        )

        discovery = ProviderDiscovery()
        discovery.discover_providers()

        assert isinstance(discovery._providers, dict)


class TestOpenAICompatibleProvider:
    """Tests for OpenAICompatibleProvider base class."""

    def test_base_provider_attributes(self):
        """Base provider has required attributes."""
        from local_deep_research.llm.providers.openai_base import (
            OpenAICompatibleProvider,
        )

        # Check class-level attributes exist
        assert hasattr(OpenAICompatibleProvider, "provider_name")
        assert hasattr(OpenAICompatibleProvider, "api_key_setting")
        assert hasattr(OpenAICompatibleProvider, "default_base_url")

    def test_base_provider_default_values(self):
        """Base provider has sensible default values."""
        from local_deep_research.llm.providers.openai_base import (
            OpenAICompatibleProvider,
        )

        # Check defaults
        assert OpenAICompatibleProvider.provider_name == "openai_endpoint"
        assert (
            OpenAICompatibleProvider.default_base_url
            == "https://api.openai.com/v1"
        )
        assert OpenAICompatibleProvider.default_model == "gpt-3.5-turbo"

    def test_base_provider_has_create_llm_method(self):
        """Base provider has create_llm classmethod."""
        from local_deep_research.llm.providers.openai_base import (
            OpenAICompatibleProvider,
        )

        assert hasattr(OpenAICompatibleProvider, "create_llm")
        assert callable(OpenAICompatibleProvider.create_llm)


class TestOllamaProvider:
    """Tests for Ollama provider."""

    def test_ollama_provider_attributes(self):
        """Ollama provider has correct attributes."""
        from local_deep_research.llm.providers.implementations.ollama import (
            OllamaProvider,
        )

        assert OllamaProvider.provider_name == "Ollama"
        assert OllamaProvider.is_cloud is False

    def test_ollama_provider_key(self):
        """Ollama provider has correct key."""
        from local_deep_research.llm.providers.implementations.ollama import (
            OllamaProvider,
        )

        assert OllamaProvider.provider_key == "OLLAMA"

    def test_ollama_provider_has_create_llm(self):
        """Ollama provider has create_llm method."""
        from local_deep_research.llm.providers.implementations.ollama import (
            OllamaProvider,
        )

        assert hasattr(OllamaProvider, "create_llm")


class TestAnthropicProvider:
    """Tests for Anthropic provider."""

    def test_anthropic_provider_attributes(self):
        """Anthropic provider has correct attributes."""
        from local_deep_research.llm.providers.implementations.anthropic import (
            AnthropicProvider,
        )

        assert AnthropicProvider.provider_name == "Anthropic"
        assert AnthropicProvider.is_cloud is True

    def test_anthropic_provider_key(self):
        """Anthropic provider has correct key."""
        from local_deep_research.llm.providers.implementations.anthropic import (
            AnthropicProvider,
        )

        assert AnthropicProvider.provider_key == "ANTHROPIC"


class TestOpenAIProvider:
    """Tests for OpenAI provider."""

    def test_openai_provider_attributes(self):
        """OpenAI provider has correct attributes."""
        from local_deep_research.llm.providers.implementations.openai import (
            OpenAIProvider,
        )

        assert OpenAIProvider.provider_name == "OpenAI"
        assert OpenAIProvider.is_cloud is True

    def test_openai_provider_key(self):
        """OpenAI provider has correct key."""
        from local_deep_research.llm.providers.implementations.openai import (
            OpenAIProvider,
        )

        assert OpenAIProvider.provider_key == "OPENAI"


class TestGoogleProvider:
    """Tests for Google provider."""

    def test_google_provider_attributes(self):
        """Google provider has correct attributes."""
        from local_deep_research.llm.providers.implementations.google import (
            GoogleProvider,
        )

        assert "Google" in GoogleProvider.provider_name
        assert GoogleProvider.is_cloud is True

    def test_google_provider_key(self):
        """Google provider has correct key."""
        from local_deep_research.llm.providers.implementations.google import (
            GoogleProvider,
        )

        assert GoogleProvider.provider_key == "GOOGLE"

    def test_google_provider_has_create_llm(self):
        """Google provider has create_llm method."""
        from local_deep_research.llm.providers.implementations.google import (
            GoogleProvider,
        )

        assert hasattr(GoogleProvider, "create_llm")


class TestLMStudioProvider:
    """Tests for LMStudio provider."""

    def test_lmstudio_provider_attributes(self):
        """LMStudio provider has correct attributes."""
        from local_deep_research.llm.providers.implementations.lmstudio import (
            LMStudioProvider,
        )

        assert LMStudioProvider.provider_name == "LM Studio"
        assert LMStudioProvider.is_cloud is False

    def test_lmstudio_provider_key(self):
        """LMStudio provider has correct key."""
        from local_deep_research.llm.providers.implementations.lmstudio import (
            LMStudioProvider,
        )

        assert LMStudioProvider.provider_key == "LMSTUDIO"

    def test_lmstudio_provider_has_create_llm(self):
        """LMStudio provider has create_llm method."""
        from local_deep_research.llm.providers.implementations.lmstudio import (
            LMStudioProvider,
        )

        assert hasattr(LMStudioProvider, "create_llm")


class TestOpenRouterProvider:
    """Tests for OpenRouter provider."""

    def test_openrouter_provider_attributes(self):
        """OpenRouter provider has correct attributes."""
        from local_deep_research.llm.providers.implementations.openrouter import (
            OpenRouterProvider,
        )

        assert OpenRouterProvider.provider_name == "OpenRouter"
        assert OpenRouterProvider.is_cloud is True

    def test_openrouter_provider_key(self):
        """OpenRouter provider has correct key."""
        from local_deep_research.llm.providers.implementations.openrouter import (
            OpenRouterProvider,
        )

        assert OpenRouterProvider.provider_key == "OPENROUTER"


class TestProviderAvailability:
    """Tests for provider availability checking."""

    def test_ollama_availability_check(self):
        """Ollama checks local availability."""
        from local_deep_research.llm.providers.implementations.ollama import (
            OllamaProvider,
        )

        # Should have is_available method
        assert hasattr(OllamaProvider, "is_available")

    def test_cloud_provider_api_key_check(self):
        """Cloud providers check API key availability."""
        from local_deep_research.llm.providers.implementations.openai import (
            OpenAIProvider,
        )

        # Should have is_available method
        assert hasattr(OpenAIProvider, "is_available")
