"""Config Base 单元测试"""

from __future__ import annotations

import pytest

from packages.config.base import (
    SharedSettings,
    get_cached_settings,
    get_shared_settings,
    reload_settings_cache,
)


class TestSharedSettingsDefaults:
    """SharedSettings 默认值测试"""

    @pytest.fixture(autouse=True)
    def clean_env(self, monkeypatch):
        """清除所有可能影响的环境变量，确保测的是代码默认值"""
        env_vars = [
            "ENVIRONMENT",
            "DEBUG",
            "AUTO_CREATE_SCHEMA",
            "DATABASE_URL",
            "DATABASE_POOL_SIZE",
            "DATABASE_MAX_OVERFLOW",
            "DATABASE_POOL_TIMEOUT",
            "DATABASE_POOL_RECYCLE",
            "REDIS_URL",
            "CELERY_BROKER_URL",
            "CELERY_RESULT_BACKEND",
            "OSS_ENDPOINT",
            "OSS_ACCESS_KEY_ID",
            "OSS_ACCESS_KEY_SECRET",
            "OSS_BUCKET_NAME",
            "OSS_DIRECT_UPLOAD_MAX_MB",
            "OSS_DIRECT_UPLOAD_EXPIRE_SECONDS",
            "COSYVOICE_API_KEY",
            "COSYVOICE_BASE_URL",
            "COSYVOICE_MODEL",
            "COSYVOICE_VOICE",
            "COSYVOICE_SAMPLE_RATE",
            "COSYVOICE_FORMAT",
            "COSYVOICE_CLONE_MODEL",
            "DOUBAO_API_KEY",
            "DOUBAO_MODEL",
            "DOUBAO_BASE_URL",
            "DOUBAO_TIMEOUT",
            "DOUBAO_MAX_RETRIES",
        ]
        for var in env_vars:
            monkeypatch.delenv(var, raising=False)
        reload_settings_cache()
        yield
        reload_settings_cache()

    def _make_settings(self):
        """构造不读 env 文件的纯净 settings"""
        return SharedSettings(_env_file="/dev/null")

    def test_default_environment(self):
        """默认环境为 development"""
        s = self._make_settings()
        assert s.environment == "development"

    def test_default_debug(self):
        """默认开启 debug"""
        s = self._make_settings()
        assert s.debug is True

    def test_default_database_config(self):
        """数据库默认配置"""
        s = self._make_settings()
        assert "postgresql" in s.database_url
        assert s.database_pool_size == 20
        assert s.database_max_overflow == 10
        assert s.database_pool_timeout == 30
        assert s.database_pool_recycle == 3600

    def test_default_redis_config(self):
        """Redis 默认配置"""
        s = self._make_settings()
        assert s.redis_url.startswith("redis://")

    def test_default_celery_config(self):
        """Celery 默认配置"""
        s = self._make_settings()
        assert s.celery_broker_url.startswith("redis://")
        assert s.celery_result_backend.startswith("redis://")

    def test_default_oss_config(self):
        """OSS 默认配置"""
        s = self._make_settings()
        assert s.oss_endpoint.endswith("aliyuncs.com")
        assert s.oss_bucket_name == "xiaoxia-autocut"
        assert s.oss_direct_upload_max_mb == 2000
        assert s.oss_direct_upload_expire_seconds == 900

    def test_default_cosyvoice_config(self):
        """CosyVoice 默认配置"""
        s = self._make_settings()
        assert s.cosyvoice_model == "cosyvoice-v3-flash"
        assert s.cosyvoice_sample_rate == 22050
        assert s.cosyvoice_format == "mp3"
        assert s.cosyvoice_clone_model == "voice-enrollment"

    def test_default_doubao_config(self):
        """豆包默认配置"""
        s = self._make_settings()
        assert s.doubao_timeout == 30
        assert s.doubao_max_retries == 2
        assert "volces.com" in s.doubao_base_url

    def test_default_empty_api_keys(self):
        """API Key 默认空字符串"""
        s = self._make_settings()
        assert s.oss_access_key_id == ""
        assert s.oss_access_key_secret == ""
        assert s.cosyvoice_api_key == ""
        assert s.doubao_api_key == ""

    def test_auto_create_schema_default(self):
        """auto_create_schema 默认 False"""
        s = self._make_settings()
        assert s.auto_create_schema is False


class TestSettingsSingleton:
    """单例管理测试"""

    def setup_method(self):
        """每个测试前清空缓存"""
        reload_settings_cache()

    def teardown_method(self):
        """每个测试后清空缓存"""
        reload_settings_cache()

    def test_get_cached_settings_same_instance(self):
        """同一类两次调用返回同一实例"""
        s1 = get_cached_settings(SharedSettings)
        s2 = get_cached_settings(SharedSettings)
        assert s1 is s2

    def test_get_shared_settings_returns_shared_settings(self):
        """get_shared_settings 返回 SharedSettings 实例"""
        s = get_shared_settings()
        assert isinstance(s, SharedSettings)

    def test_get_shared_settings_singleton(self):
        """get_shared_settings 是单例"""
        s1 = get_shared_settings()
        s2 = get_shared_settings()
        assert s1 is s2

    def test_reload_settings_cache_clears(self):
        """reload 后获取新实例"""
        s1 = get_cached_settings(SharedSettings)
        reload_settings_cache()
        s2 = get_cached_settings(SharedSettings)
        assert s1 is not s2

    def test_custom_cache_key(self):
        """自定义 cache_key 分开缓存"""
        s1 = get_cached_settings(SharedSettings, cache_key="key_a")
        s2 = get_cached_settings(SharedSettings, cache_key="key_b")
        assert s1 is not s2
        # 但值相同
        assert s1.database_url == s2.database_url

    def test_different_classes_separate_cache(self):
        """不同类使用不同缓存"""
        from packages.config.api_settings import APISettings

        shared = get_shared_settings()
        api = get_cached_settings(APISettings)
        assert shared is not api
