"""
Tests for config module.
"""

import os
from unittest.mock import patch

import pytest

from config import Settings, get_settings


class TestSettings:
    """Tests for Settings class."""

    def test_default_values(self) -> None:
        """Test default configuration values."""
        settings = Settings()

        assert settings.host == "0.0.0.0"
        assert settings.port == 8001
        assert settings.debug is False
        assert settings.redis_url == "redis://localhost:6379/0"
        assert settings.litellm_timeout == 120
        assert settings.circuit_failure_threshold == 5

    def test_custom_values(self) -> None:
        """Test custom configuration values."""
        settings = Settings(
            host="127.0.0.1",
            port=9000,
            debug=True,
            redis_url="redis://custom:6380/1",
            litellm_timeout=60,
        )

        assert settings.host == "127.0.0.1"
        assert settings.port == 9000
        assert settings.debug is True
        assert settings.redis_url == "redis://custom:6380/1"
        assert settings.litellm_timeout == 60

    def test_port_validation_valid(self) -> None:
        """Test valid port numbers."""
        settings = Settings(port=1)
        assert settings.port == 1

        settings = Settings(port=65535)
        assert settings.port == 65535

        settings = Settings(port=8080)
        assert settings.port == 8080

    def test_port_validation_invalid(self) -> None:
        """Test invalid port numbers."""
        with pytest.raises(ValueError, match="Port must be between"):
            Settings(port=0)

        with pytest.raises(ValueError, match="Port must be between"):
            Settings(port=65536)

        with pytest.raises(ValueError, match="Port must be between"):
            Settings(port=-1)

    def test_ttl_validation_valid(self) -> None:
        """Test valid TTL values."""
        settings = Settings(redis_ttl_hours=1)
        assert settings.redis_ttl_hours == 1

        settings = Settings(redis_ttl_hours=168)  # 1 week
        assert settings.redis_ttl_hours == 168

    def test_ttl_validation_invalid(self) -> None:
        """Test invalid TTL values."""
        with pytest.raises(ValueError, match="Redis TTL must be positive"):
            Settings(redis_ttl_hours=0)

        with pytest.raises(ValueError, match="Redis TTL must be positive"):
            Settings(redis_ttl_hours=-1)

    def test_failure_threshold_validation(self) -> None:
        """Test circuit failure threshold validation."""
        settings = Settings(circuit_failure_threshold=1)
        assert settings.circuit_failure_threshold == 1

        settings = Settings(circuit_failure_threshold=100)
        assert settings.circuit_failure_threshold == 100

        with pytest.raises(ValueError, match="Failure threshold must be between"):
            Settings(circuit_failure_threshold=0)

        with pytest.raises(ValueError, match="Failure threshold must be between"):
            Settings(circuit_failure_threshold=101)

    def test_timeout_validation(self) -> None:
        """Test timeout validation."""
        settings = Settings(litellm_timeout=1)
        assert settings.litellm_timeout == 1

        settings = Settings(litellm_timeout=600)
        assert settings.litellm_timeout == 600

        with pytest.raises(ValueError, match="Timeout must be between"):
            Settings(litellm_timeout=0)

        with pytest.raises(ValueError, match="Timeout must be between"):
            Settings(litellm_timeout=601)

    def test_get_available_providers_none(self) -> None:
        """Test getting available providers with none configured."""
        settings = Settings()
        providers = settings.get_available_providers()
        assert providers == []

    def test_get_available_providers_some(self) -> None:
        """Test getting available providers with some configured."""
        settings = Settings(
            anthropic_api_key="test-key",
            openai_api_key="test-key",
        )
        providers = settings.get_available_providers()

        assert "anthropic" in providers
        assert "openai" in providers
        assert "google" not in providers
        assert len(providers) == 2

    def test_get_available_providers_all(self) -> None:
        """Test getting available providers with all configured."""
        settings = Settings(
            anthropic_api_key="test-key",
            openai_api_key="test-key",
            google_api_key="test-key",
            alibaba_api_key="test-key",
            deepseek_api_key="test-key",
        )
        providers = settings.get_available_providers()

        assert len(providers) == 5
        assert "anthropic" in providers
        assert "openai" in providers
        assert "google" in providers
        assert "alibaba" in providers
        assert "deepseek" in providers

    def test_has_any_provider_false(self) -> None:
        """Test has_any_provider when none configured."""
        settings = Settings()
        assert settings.has_any_provider() is False

    def test_has_any_provider_true(self) -> None:
        """Test has_any_provider when at least one configured."""
        settings = Settings(anthropic_api_key="test-key")
        assert settings.has_any_provider() is True

    def test_deepseek_base_url_counts_as_provider(self) -> None:
        """Test that DeepSeek base URL alone counts as provider."""
        settings = Settings(deepseek_base_url="http://localhost:8000")
        providers = settings.get_available_providers()
        assert "deepseek" in providers


class TestGetSettings:
    """Tests for get_settings function."""

    def test_get_settings_returns_settings(self) -> None:
        """Test that get_settings returns a Settings instance."""
        # Clear the cache first
        get_settings.cache_clear()

        settings = get_settings()
        assert isinstance(settings, Settings)

    def test_get_settings_is_cached(self) -> None:
        """Test that get_settings returns cached instance."""
        get_settings.cache_clear()

        settings1 = get_settings()
        settings2 = get_settings()

        assert settings1 is settings2

    def test_env_var_override(self) -> None:
        """Test that environment variables override defaults."""
        get_settings.cache_clear()

        with patch.dict(
            os.environ,
            {
                "LLM_GATEWAY_HOST": "192.168.1.1",
                "LLM_GATEWAY_PORT": "9999",
                "LLM_GATEWAY_DEBUG": "true",
            },
        ):
            get_settings.cache_clear()
            settings = get_settings()

            assert settings.host == "192.168.1.1"
            assert settings.port == 9999
            assert settings.debug is True
