"""
Behavioral tests for config/llm_config module.

Tests availability checks with snapshots, provider validation,
model/provider name cleaning, fallback model, and provider selection.
"""

import pytest


class TestApiKeyAvailabilityChecks:
    """Tests for is_*_available() functions with settings snapshots.

    These functions check bool(api_key) from the snapshot — the core
    logic is: present and non-empty → True, else → False.
    """

    def test_openai_available_with_api_key(self):
        from local_deep_research.llm.providers.implementations.openai import (
            OpenAIProvider,
        )

        result = OpenAIProvider.is_available(
            settings_snapshot={"llm.openai.api_key": "sk-test"}
        )
        assert result is True

    def test_openai_unavailable_without_api_key(self):
        from local_deep_research.llm.providers.implementations.openai import (
            OpenAIProvider,
        )

        assert (
            OpenAIProvider.is_available(
                settings_snapshot={"search.tool": "searxng"}
            )
            is False
        )

    def test_openai_unavailable_with_empty_api_key(self):
        """Empty string API key is falsy — treated as missing."""
        from local_deep_research.llm.providers.implementations.openai import (
            OpenAIProvider,
        )

        result = OpenAIProvider.is_available(
            settings_snapshot={"llm.openai.api_key": ""}
        )
        assert result is False

    def test_anthropic_available_with_api_key(self):
        from local_deep_research.llm.providers.implementations.anthropic import (
            AnthropicProvider,
        )

        result = AnthropicProvider.is_available(
            settings_snapshot={"llm.anthropic.api_key": "sk-ant-test"}
        )
        assert result is True

    def test_anthropic_unavailable_without_api_key(self):
        from local_deep_research.llm.providers.implementations.anthropic import (
            AnthropicProvider,
        )

        assert (
            AnthropicProvider.is_available(
                settings_snapshot={"search.tool": "searxng"}
            )
            is False
        )

    def test_openai_endpoint_available_with_api_key(self):
        from local_deep_research.llm.providers.implementations.custom_openai_endpoint import (
            CustomOpenAIEndpointProvider,
        )

        result = CustomOpenAIEndpointProvider.is_available(
            settings_snapshot={"llm.openai_endpoint.api_key": "key123"}
        )
        assert result is True

    def test_openai_endpoint_unavailable_without_api_key(self):
        from local_deep_research.llm.providers.implementations.custom_openai_endpoint import (
            CustomOpenAIEndpointProvider,
        )

        assert (
            CustomOpenAIEndpointProvider.is_available(
                settings_snapshot={"search.tool": "searxng"}
            )
            is False
        )


class TestProviderValidation:
    """Tests for provider validation in get_llm()."""

    def test_invalid_provider_raises_value_error(self):
        """get_llm raises ValueError for unknown provider name."""
        from local_deep_research.config.llm_config import get_llm

        with pytest.raises(ValueError, match="Invalid provider"):
            get_llm(
                provider="nonexistent_provider",
                settings_snapshot={"search.tool": "searxng"},
            )

    def test_error_message_lists_valid_providers(self):
        """ValueError message enumerates the auto-discovered providers.

        The valid set is derived from auto-discovery (no hardcoded
        VALID_PROVIDERS), so the error lists every discovered provider.
        """
        from local_deep_research.config.llm_config import get_llm
        from local_deep_research.llm.providers import (
            get_discovered_provider_options,
        )
        from local_deep_research.llm.providers.base import normalize_provider

        with pytest.raises(ValueError) as exc_info:
            get_llm(
                provider="bad_provider",
                settings_snapshot={"search.tool": "searxng"},
            )
        message = str(exc_info.value)
        for option in get_discovered_provider_options():
            assert normalize_provider(option["value"]) in message


class TestModelAndProviderNameCleaning:
    """Tests for model_name and provider name cleaning in get_llm().

    get_llm strips quotes, whitespace, and lowercases the provider name
    before validation.
    """

    def test_quoted_provider_name_cleaned(self):
        """Surrounding quotes are stripped: \"'none'\" → 'none' (valid but unimplemented)."""
        import pytest
        from local_deep_research.config.llm_config import get_llm

        # 'none' is valid but has no implementation, so it raises ValueError
        # The point is the quotes are stripped before validation
        with pytest.raises(ValueError, match="No LLM provider configured"):
            get_llm(
                model_name="x",
                provider="'none'",
                settings_snapshot={"search.tool": "searxng"},
            )

    def test_whitespace_provider_name_cleaned(self):
        """Surrounding whitespace is stripped: '  none  ' → 'none'."""
        import pytest
        from local_deep_research.config.llm_config import get_llm

        with pytest.raises(ValueError, match="No LLM provider configured"):
            get_llm(
                model_name="x",
                provider="  none  ",
                settings_snapshot={"search.tool": "searxng"},
            )

    def test_uppercase_provider_lowercased(self):
        """Provider name is lowercased: 'NONE' → 'none'."""
        import pytest
        from local_deep_research.config.llm_config import get_llm

        with pytest.raises(ValueError, match="No LLM provider configured"):
            get_llm(
                model_name="x",
                provider="NONE",
                settings_snapshot={"search.tool": "searxng"},
            )

    def test_combined_quotes_whitespace_case_cleaning(self):
        """Combined cleaning: \"  'None'  \" → 'none'."""
        import pytest
        from local_deep_research.config.llm_config import get_llm

        with pytest.raises(ValueError, match="No LLM provider configured"):
            get_llm(
                model_name="x",
                provider="  'None'  ",
                settings_snapshot={"search.tool": "searxng"},
            )


class TestGetSelectedLlmProvider:
    """Tests for get_selected_llm_provider() function."""

    def test_returns_lowercase(self):
        """Provider value from snapshot is lowercased."""
        from local_deep_research.config.llm_config import (
            get_selected_llm_provider,
        )

        result = get_selected_llm_provider(
            settings_snapshot={"llm.provider": "OpenAI"}
        )
        assert result == "openai"

    def test_default_is_ollama(self):
        """Default provider is 'ollama' when not specified in snapshot."""
        from local_deep_research.config.llm_config import (
            get_selected_llm_provider,
        )

        result = get_selected_llm_provider(
            settings_snapshot={"search.tool": "searxng"}
        )
        assert result == "ollama"
