"""Deep coverage tests for security/__init__.py.

The __init__.py conditionally imports several optional components:
- PathValidator (requires werkzeug)
- FileUploadValidator (requires pdfplumber)

Tests cover:
- All required imports are present
- Conditional flag values
- __all__ completeness
- Individual security re-exports callable/usable
"""

MODULE = "local_deep_research.security"


class TestRequiredImportsAlwaysPresent:
    """These symbols must always be importable regardless of optional deps."""

    def test_data_sanitizer_present(self):
        from local_deep_research.security import DataSanitizer

        assert DataSanitizer is not None

    def test_sanitize_data_present(self):
        from local_deep_research.security import sanitize_data

        assert callable(sanitize_data)

    def test_redact_data_present(self):
        from local_deep_research.security import redact_data

        assert callable(redact_data)

    def test_filter_research_metadata_present(self):
        from local_deep_research.security import filter_research_metadata

        assert callable(filter_research_metadata)

    def test_safe_get_present(self):
        from local_deep_research.security import safe_get

        assert callable(safe_get)

    def test_safe_post_present(self):
        from local_deep_research.security import safe_post

        assert callable(safe_post)

    def test_validate_url_present(self):
        from local_deep_research.security import validate_url

        assert callable(validate_url)

    def test_is_ip_blocked_present(self):
        from local_deep_research.security import is_ip_blocked

        assert callable(is_ip_blocked)

    def test_password_validator_present(self):
        from local_deep_research.security import PasswordValidator

        assert PasswordValidator is not None

    def test_account_lockout_manager_present(self):
        from local_deep_research.security import AccountLockoutManager

        assert AccountLockoutManager is not None

    def test_get_account_lockout_manager_present(self):
        from local_deep_research.security import get_account_lockout_manager

        assert callable(get_account_lockout_manager)

    def test_sanitize_for_log_present(self):
        from local_deep_research.security import sanitize_for_log

        assert callable(sanitize_for_log)

    def test_strip_control_chars_present(self):
        from local_deep_research.security import strip_control_chars

        assert callable(strip_control_chars)

    def test_get_safe_module_class_present(self):
        from local_deep_research.security import get_safe_module_class

        assert callable(get_safe_module_class)

    def test_module_not_allowed_error_present(self):
        from local_deep_research.security import ModuleNotAllowedError

        assert issubclass(ModuleNotAllowedError, Exception)

    def test_allowed_modules_present(self):
        from local_deep_research.security import ALLOWED_MODULES

        assert isinstance(ALLOWED_MODULES, (set, frozenset, dict, list))

    def test_security_headers_present(self):
        from local_deep_research.security import SecurityHeaders

        assert SecurityHeaders is not None

    def test_url_validator_present(self):
        from local_deep_research.security import URLValidator

        assert URLValidator is not None

    def test_safe_session_present(self):
        from local_deep_research.security import SafeSession

        assert SafeSession is not None

    def test_get_safe_url_present(self):
        from local_deep_research.security import get_safe_url

        assert callable(get_safe_url)

    def test_strip_settings_snapshot_present(self):
        from local_deep_research.security import strip_settings_snapshot

        assert callable(strip_settings_snapshot)

    def test_get_security_default_present(self):
        from local_deep_research.security import get_security_default

        assert callable(get_security_default)

    def test_notification_url_validator_present(self):
        from local_deep_research.security import NotificationURLValidator

        assert NotificationURLValidator is not None

    def test_notification_url_validation_error_present(self):
        from local_deep_research.security import NotificationURLValidationError

        assert issubclass(NotificationURLValidationError, Exception)


class TestConditionalFlags:
    def test_has_path_validator_flag_is_bool(self):
        import local_deep_research.security as sec

        assert isinstance(sec._has_path_validator, bool)

    def test_has_file_upload_validator_flag_is_bool(self):
        import local_deep_research.security as sec

        assert isinstance(sec._has_file_upload_validator, bool)

    def test_path_validator_is_class_or_none(self):
        from local_deep_research.security import PathValidator

        assert PathValidator is None or isinstance(PathValidator, type)

    def test_file_upload_validator_is_class_or_none(self):
        from local_deep_research.security import FileUploadValidator

        assert FileUploadValidator is None or isinstance(
            FileUploadValidator, type
        )

    def test_path_validator_flag_consistent_with_object(self):
        import local_deep_research.security as sec

        if sec._has_path_validator:
            assert sec.PathValidator is not None
        else:
            assert sec.PathValidator is None


class TestDunderAll:
    def test_all_is_list(self):
        import local_deep_research.security as sec

        assert isinstance(sec.__all__, list)

    def test_all_contains_key_symbols(self):
        import local_deep_research.security as sec

        must_have = {
            "DataSanitizer",
            "sanitize_data",
            "safe_get",
            "safe_post",
            "validate_url",
            "PasswordValidator",
            "AccountLockoutManager",
            "sanitize_for_log",
            "PathValidator",
            "SecurityHeaders",
            "URLValidator",
        }
        for sym in must_have:
            assert sym in sec.__all__, f"{sym} missing from __all__"

    def test_all_symbols_defined_as_attributes(self):
        """Every symbol in __all__ must be defined as an attribute (may be None)."""
        import local_deep_research.security as sec

        for name in sec.__all__:
            assert hasattr(sec, name), f"{name} in __all__ but not defined"

    def test_no_duplicates_in_all(self):
        import local_deep_research.security as sec

        assert len(sec.__all__) == len(set(sec.__all__))
