"""
Extended tests for environment registry convenience functions.

Tests cover:
- get_env_setting function
- is_test_mode function
- is_ci_environment function
- is_github_actions function
- is_rate_limiting_enabled function
"""

import os
import pytest

from local_deep_research.settings.env_registry import (
    registry,
    get_env_setting,
    is_test_mode,
    is_ci_environment,
    is_github_actions,
    is_rate_limiting_enabled,
)


class TestGetEnvSettingFunction:
    """Tests for get_env_setting convenience function."""

    @pytest.fixture(autouse=True)
    def clean_env(self):
        """Clean environment before each test."""
        original_env = {
            k: v
            for k, v in os.environ.items()
            if k.startswith("LDR_")
            or k in ["CI", "TESTING", "GITHUB_ACTIONS", "DISABLE_RATE_LIMITING"]
        }
        for key in list(os.environ.keys()):
            if key.startswith("LDR_") or key in [
                "CI",
                "TESTING",
                "GITHUB_ACTIONS",
                "DISABLE_RATE_LIMITING",
            ]:
                os.environ.pop(key, None)
        yield
        for key in list(os.environ.keys()):
            if key.startswith("LDR_") or key in [
                "CI",
                "TESTING",
                "GITHUB_ACTIONS",
                "DISABLE_RATE_LIMITING",
            ]:
                os.environ.pop(key, None)
        for key, value in original_env.items():
            os.environ[key] = value

    def test_get_env_setting_returns_value(self):
        """Test that get_env_setting returns the correct value."""
        os.environ["LDR_TESTING_TEST_MODE"] = "true"

        result = get_env_setting("testing.test_mode")

        assert result is True

    def test_get_env_setting_returns_default_when_not_set(self):
        """Test that get_env_setting returns default when key not set."""
        result = get_env_setting("testing.test_mode", default=True)

        # The setting has a default of False in the definition
        # But if env var not set, it should use the setting's default
        assert result is False  # Setting's default is False

    def test_get_env_setting_unknown_key_returns_default(self):
        """Test that get_env_setting returns default for unknown keys."""
        result = get_env_setting("unknown.key", default="fallback")

        assert result == "fallback"


class TestIsTestModeFunction:
    """Tests for is_test_mode convenience function."""

    @pytest.fixture(autouse=True)
    def clean_env(self):
        """Clean environment before each test."""
        original_env = {
            k: v for k, v in os.environ.items() if k.startswith("LDR_")
        }
        for key in list(os.environ.keys()):
            if key.startswith("LDR_"):
                os.environ.pop(key, None)
        yield
        for key in list(os.environ.keys()):
            if key.startswith("LDR_"):
                os.environ.pop(key, None)
        for key, value in original_env.items():
            os.environ[key] = value

    def test_is_test_mode_returns_true_when_set(self):
        """Test is_test_mode returns True when LDR_TESTING_TEST_MODE=true."""
        os.environ["LDR_TESTING_TEST_MODE"] = "true"

        assert is_test_mode() is True

    def test_is_test_mode_returns_false_when_not_set(self):
        """Test is_test_mode returns False when not set."""
        assert is_test_mode() is False

    def test_is_test_mode_returns_false_when_false(self):
        """Test is_test_mode returns False when set to false."""
        os.environ["LDR_TESTING_TEST_MODE"] = "false"

        assert is_test_mode() is False


class TestIsCiEnvironmentFunction:
    """Tests for is_ci_environment convenience function."""

    @pytest.fixture(autouse=True)
    def clean_env(self):
        """Clean environment before each test."""
        original_env = {
            k: v for k, v in os.environ.items() if k in ["CI", "GITHUB_ACTIONS"]
        }
        for key in ["CI", "GITHUB_ACTIONS"]:
            os.environ.pop(key, None)
        yield
        for key in ["CI", "GITHUB_ACTIONS"]:
            os.environ.pop(key, None)
        for key, value in original_env.items():
            os.environ[key] = value

    def test_is_ci_environment_github_actions(self):
        """Test is_ci_environment returns True when CI=true."""
        os.environ["CI"] = "true"

        assert is_ci_environment() is True

    def test_is_ci_environment_ci_variable_true(self):
        """Test is_ci_environment returns True for CI=true."""
        os.environ["CI"] = "true"

        assert is_ci_environment() is True

    def test_is_ci_environment_ci_variable_1(self):
        """Test is_ci_environment returns True for CI=1."""
        os.environ["CI"] = "1"

        assert is_ci_environment() is True

    def test_is_ci_environment_ci_variable_yes(self):
        """Test is_ci_environment returns True for CI=yes."""
        os.environ["CI"] = "yes"

        assert is_ci_environment() is True

    def test_is_ci_environment_returns_false_when_not_set(self):
        """Test is_ci_environment returns False when CI not set."""
        assert is_ci_environment() is False

    def test_is_ci_environment_returns_false_when_false(self):
        """Test is_ci_environment returns False when CI=false."""
        os.environ["CI"] = "false"

        assert is_ci_environment() is False


class TestIsGithubActionsFunction:
    """Tests for is_github_actions convenience function."""

    @pytest.fixture(autouse=True)
    def clean_env(self):
        """Clean environment before each test."""
        original_env = {
            k: v for k, v in os.environ.items() if k == "GITHUB_ACTIONS"
        }
        os.environ.pop("GITHUB_ACTIONS", None)
        yield
        os.environ.pop("GITHUB_ACTIONS", None)
        for key, value in original_env.items():
            os.environ[key] = value

    def test_is_github_actions_detection_true(self):
        """Test is_github_actions returns True when GITHUB_ACTIONS=true."""
        os.environ["GITHUB_ACTIONS"] = "true"

        assert is_github_actions() is True

    def test_is_github_actions_detection_1(self):
        """Test is_github_actions returns True when GITHUB_ACTIONS=1."""
        os.environ["GITHUB_ACTIONS"] = "1"

        assert is_github_actions() is True

    def test_is_github_actions_detection_yes(self):
        """Test is_github_actions returns True when GITHUB_ACTIONS=yes."""
        os.environ["GITHUB_ACTIONS"] = "yes"

        assert is_github_actions() is True

    def test_is_github_actions_returns_false_when_not_set(self):
        """Test is_github_actions returns False when not set."""
        assert is_github_actions() is False

    def test_is_github_actions_returns_false_when_false(self):
        """Test is_github_actions returns False when GITHUB_ACTIONS=false."""
        os.environ["GITHUB_ACTIONS"] = "false"

        assert is_github_actions() is False


class TestIsRateLimitingEnabledFunction:
    """Tests for is_rate_limiting_enabled convenience function."""

    @pytest.fixture(autouse=True)
    def clean_env(self):
        """Clean environment before each test."""
        env_vars = ("DISABLE_RATE_LIMITING", "LDR_DISABLE_RATE_LIMITING")
        original_env = {k: os.environ[k] for k in env_vars if k in os.environ}
        for k in env_vars:
            os.environ.pop(k, None)
        # Reset the module-level deprecation-warning flag so tests asserting
        # warning behavior get a fresh state per case.
        from local_deep_research.settings.env_registry import (
            _reset_legacy_warning_flag_for_tests,
        )

        _reset_legacy_warning_flag_for_tests()
        yield
        for k in env_vars:
            os.environ.pop(k, None)
        for key, value in original_env.items():
            os.environ[key] = value
        _reset_legacy_warning_flag_for_tests()

    def test_is_rate_limiting_enabled_default(self):
        """Test is_rate_limiting_enabled returns True by default."""
        assert is_rate_limiting_enabled() is True

    def test_is_rate_limiting_enabled_disabled_true(self):
        """Legacy DISABLE_RATE_LIMITING=true still disables rate limiting."""
        os.environ["DISABLE_RATE_LIMITING"] = "true"
        assert is_rate_limiting_enabled() is False

    def test_is_rate_limiting_enabled_disabled_1(self):
        """Legacy DISABLE_RATE_LIMITING=1 still disables rate limiting."""
        os.environ["DISABLE_RATE_LIMITING"] = "1"
        assert is_rate_limiting_enabled() is False

    def test_is_rate_limiting_enabled_disabled_yes(self):
        """Legacy DISABLE_RATE_LIMITING=yes still disables rate limiting."""
        os.environ["DISABLE_RATE_LIMITING"] = "yes"
        assert is_rate_limiting_enabled() is False

    def test_is_rate_limiting_enabled_with_false_flag(self):
        """Legacy DISABLE_RATE_LIMITING=false leaves rate limiting enabled."""
        os.environ["DISABLE_RATE_LIMITING"] = "false"
        assert is_rate_limiting_enabled() is True

    def test_canonical_ldr_disable_true(self):
        """LDR_DISABLE_RATE_LIMITING=true disables rate limiting."""
        os.environ["LDR_DISABLE_RATE_LIMITING"] = "true"
        assert is_rate_limiting_enabled() is False

    def test_canonical_ldr_disable_1(self):
        """LDR_DISABLE_RATE_LIMITING=1 disables rate limiting."""
        os.environ["LDR_DISABLE_RATE_LIMITING"] = "1"
        assert is_rate_limiting_enabled() is False

    def test_canonical_ldr_disable_yes(self):
        """LDR_DISABLE_RATE_LIMITING=yes disables rate limiting."""
        os.environ["LDR_DISABLE_RATE_LIMITING"] = "yes"
        assert is_rate_limiting_enabled() is False

    def test_canonical_ldr_disable_false(self):
        """LDR_DISABLE_RATE_LIMITING=false leaves rate limiting enabled."""
        os.environ["LDR_DISABLE_RATE_LIMITING"] = "false"
        assert is_rate_limiting_enabled() is True

    def test_canonical_wins_when_both_set_with_conflicting_values(self):
        """When both forms are set with conflicting values, canonical wins.

        canonical=false → enabled=True even though legacy=true would disable.
        """
        os.environ["LDR_DISABLE_RATE_LIMITING"] = "false"
        os.environ["DISABLE_RATE_LIMITING"] = "true"
        assert is_rate_limiting_enabled() is True

    def test_canonical_wins_when_both_disable(self):
        """Both set to disable: canonical short-circuits, no legacy warning."""
        os.environ["LDR_DISABLE_RATE_LIMITING"] = "true"
        os.environ["DISABLE_RATE_LIMITING"] = "true"
        assert is_rate_limiting_enabled() is False


class TestRegistryGlobalInstance:
    """Tests for the global registry instance."""

    def test_registry_has_testing_category(self):
        """Test that registry has testing category registered."""
        settings = registry.get_category_settings("testing")

        assert len(settings) >= 1
        keys = [s.key for s in settings]
        assert "testing.test_mode" in keys

    def test_registry_has_bootstrap_category(self):
        """Test that registry has bootstrap category registered."""
        settings = registry.get_category_settings("bootstrap")

        assert len(settings) >= 7
        keys = [s.key for s in settings]
        assert "bootstrap.encryption_key" in keys
        assert "bootstrap.data_dir" in keys

    def test_registry_has_db_config_category(self):
        """Test that registry has db_config category registered."""
        settings = registry.get_category_settings("db_config")

        assert len(settings) >= 5
        keys = [s.key for s in settings]
        assert "db_config.cache_size_mb" in keys
        assert "db_config.journal_mode" in keys

    def test_registry_get_bootstrap_vars(self):
        """Test that get_bootstrap_vars returns bootstrap and db_config vars."""
        bootstrap_vars = registry.get_bootstrap_vars()

        # Should include both bootstrap and db_config
        assert "LDR_BOOTSTRAP_ENCRYPTION_KEY" in bootstrap_vars
        assert "LDR_DB_CONFIG_CACHE_SIZE_MB" in bootstrap_vars

    def test_registry_get_testing_vars(self):
        """Test that get_testing_vars returns testing category vars."""
        testing_vars = registry.get_testing_vars()

        assert "LDR_TESTING_TEST_MODE" in testing_vars
