"""
Tests for the check-env-vars pre-commit hook.

Ensures the hook enforces centralized configuration through SettingsManager
instead of direct os.environ access, which prevents hardcoded secrets and
ensures consistent config management.
"""

import ast
import sys
from importlib import import_module
from pathlib import Path


HOOKS_DIR = Path(__file__).parent.parent.parent / ".pre-commit-hooks"
sys.path.insert(0, str(HOOKS_DIR))

hook_module = import_module("check-env-vars")
EnvVarChecker = hook_module.EnvVarChecker


def _check_code(
    code: str, filename: str = "src/local_deep_research/module.py"
) -> list:
    """Parse code and run the env var checker."""
    tree = ast.parse(code)
    checker = EnvVarChecker(filename)
    checker.visit(tree)
    return checker.errors


class TestDetectsDirectEnvAccess:
    """Ensures os.environ usage is flagged in application code."""

    def test_detects_os_environ_get(self):
        code = 'import os\nval = os.environ.get("LDR_SECRET_KEY")\n'
        errors = _check_code(code)
        assert len(errors) >= 1
        assert any("SettingsManager" in e[1] for e in errors)

    def test_detects_os_environ_bracket(self):
        code = 'import os\nval = os.environ["LDR_DATA_DIR"]\n'
        errors = _check_code(code)
        assert len(errors) >= 1

    def test_detects_os_getenv(self):
        code = 'import os\nval = os.getenv("LDR_API_KEY")\n'
        errors = _check_code(code)
        assert len(errors) >= 1

    def test_detects_from_os_import_environ(self):
        code = "from os import environ\n"
        errors = _check_code(code)
        assert len(errors) >= 1

    def test_detects_environ_alias(self):
        code = "import os\nenv = os.environ\n"
        errors = _check_code(code)
        assert len(errors) >= 1

    def test_detects_in_environ_check(self):
        code = 'import os\nif "LDR_KEY" in os.environ:\n    pass\n'
        errors = _check_code(code)
        assert len(errors) >= 1


class TestAllowsSystemVars:
    """Ensures standard system env vars are not flagged."""

    def test_allows_path(self):
        code = 'import os\npath = os.environ.get("PATH")\n'
        errors = _check_code(code)
        assert len(errors) == 0

    def test_allows_home(self):
        code = 'import os\nhome = os.environ.get("HOME")\n'
        errors = _check_code(code)
        assert len(errors) == 0

    def test_allows_ci(self):
        code = 'import os\nis_ci = os.environ.get("CI")\n'
        errors = _check_code(code)
        assert len(errors) == 0

    def test_allows_pytest_current_test(self):
        code = 'import os\ntest = os.environ.get("PYTEST_CURRENT_TEST")\n'
        errors = _check_code(code)
        assert len(errors) == 0


class TestAllowsExemptFiles:
    """Ensures settings/config/test files are exempt."""

    def test_allows_settings_files(self):
        code = 'import os\nval = os.environ.get("LDR_KEY")\n'
        errors = _check_code(code, filename="src/settings/manager.py")
        assert len(errors) == 0

    def test_allows_config_files(self):
        code = 'import os\nval = os.environ.get("LDR_KEY")\n'
        errors = _check_code(code, filename="src/config/paths.py")
        assert len(errors) == 0

    def test_allows_test_files(self):
        code = 'import os\nval = os.environ.get("LDR_KEY")\n'
        errors = _check_code(code, filename="tests/test_something.py")
        assert len(errors) == 0

    def test_allows_migration_files(self):
        code = 'import os\nval = os.environ.get("LDR_KEY")\n'
        errors = _check_code(code, filename="migrations/env.py")
        assert len(errors) == 0


class TestAllowsSafePatterns:
    """Ensures normal code without env access is not flagged."""

    def test_allows_normal_code(self):
        code = """
def process_data(data):
    return data.upper()
"""
        errors = _check_code(code)
        assert len(errors) == 0

    def test_allows_settings_manager_usage(self):
        code = """
from settings.manager import SettingsManager
settings = SettingsManager()
val = settings.get_setting("my_key")
"""
        errors = _check_code(code)
        assert len(errors) == 0
