"""
Tests for BaseSearchEngine.
"""

from src.local_deep_research.web_search_engines.search_engine_base import (
    BaseSearchEngine,
)


class TestBaseSearchEngineClassAttributes:
    """Tests for BaseSearchEngine class attributes."""

    def test_is_public_default_false(self):
        """is_public defaults to False for safety."""
        assert BaseSearchEngine.is_public is False

    def test_is_generic_default_false(self):
        """is_generic defaults to False."""
        assert BaseSearchEngine.is_generic is False

    def test_is_scientific_default_false(self):
        """is_scientific defaults to False."""
        assert BaseSearchEngine.is_scientific is False

    def test_is_local_default_false(self):
        """is_local defaults to False."""
        assert BaseSearchEngine.is_local is False

    def test_is_news_default_false(self):
        """is_news defaults to False."""
        assert BaseSearchEngine.is_news is False

    def test_is_code_default_false(self):
        """is_code defaults to False."""
        assert BaseSearchEngine.is_code is False


class TestLoadEngineClass:
    """Tests for _load_engine_class method."""

    def test_load_engine_class_missing_module_path(self):
        """Returns error when module_path is missing."""
        config = {"class_name": "TestEngine"}
        success, engine_class, error = BaseSearchEngine._load_engine_class(
            "test", config
        )
        assert success is False
        assert engine_class is None
        assert "module_path" in error

    def test_load_engine_class_missing_class_name(self):
        """Returns error when class_name is missing."""
        config = {"module_path": ".engines.test"}
        success, engine_class, error = BaseSearchEngine._load_engine_class(
            "test", config
        )
        assert success is False
        assert engine_class is None
        assert "class_name" in error

    def test_load_engine_class_import_error(self):
        """Returns error when import fails."""
        config = {
            "module_path": ".engines.nonexistent_module",
            "class_name": "NonexistentEngine",
        }
        success, engine_class, error = BaseSearchEngine._load_engine_class(
            "test", config
        )
        assert success is False
        assert engine_class is None
        assert "Could not load" in error

    def test_load_engine_class_success(self):
        """Successfully loads engine class."""
        config = {
            "module_path": ".engines.search_engine_wikipedia",
            "class_name": "WikipediaSearchEngine",
        }
        success, engine_class, error = BaseSearchEngine._load_engine_class(
            "wikipedia", config
        )
        assert success is True
        assert engine_class is not None
        assert error is None


class TestCheckApiKeyAvailability:
    """Tests for _check_api_key_availability method."""

    def test_api_key_not_required(self):
        """Returns True when API key not required."""
        config = {"requires_api_key": False}
        result = BaseSearchEngine._check_api_key_availability("test", config)
        assert result is True

    def test_api_key_required_and_provided(self):
        """Returns True when API key required and provided."""
        config = {
            "requires_api_key": True,
            "api_key": "valid-api-key-12345",
        }
        result = BaseSearchEngine._check_api_key_availability("test", config)
        assert result is True

    def test_api_key_required_but_empty(self):
        """Returns False when API key required but empty."""
        config = {
            "requires_api_key": True,
            "api_key": "",
        }
        result = BaseSearchEngine._check_api_key_availability("test", config)
        assert result is False

    def test_api_key_required_but_none(self):
        """Returns False when API key required but None."""
        config = {
            "requires_api_key": True,
            "api_key": "None",
        }
        result = BaseSearchEngine._check_api_key_availability("test", config)
        assert result is False

    def test_api_key_placeholder_rejected(self):
        """Returns False for placeholder API keys."""
        placeholders = [
            "PLACEHOLDER",
            "YOUR_API_KEY_HERE",
            "BRAVE_API_KEY",
            "YOUR_GOOGLE_API_KEY",
            "null",
        ]

        for placeholder in placeholders:
            config = {
                "requires_api_key": True,
                "api_key": placeholder,
            }
            result = BaseSearchEngine._check_api_key_availability(
                "test", config
            )
            assert result is False, f"Should reject placeholder: {placeholder}"


class TestBaseSearchEngineSubclassing:
    """Tests for subclassing BaseSearchEngine."""

    def test_subclass_can_override_attributes(self):
        """Subclass can override class attributes."""

        class PublicSearchEngine(BaseSearchEngine):
            is_public = True
            is_generic = True

            def run(self, query):
                return []

        assert PublicSearchEngine.is_public is True
        assert PublicSearchEngine.is_generic is True

    def test_subclass_scientific_engine(self):
        """Subclass can be marked as scientific."""

        class ScientificEngine(BaseSearchEngine):
            is_scientific = True
            is_public = True

            def run(self, query):
                return []

        assert ScientificEngine.is_scientific is True
        assert ScientificEngine.is_public is True

    def test_subclass_local_engine(self):
        """Subclass can be marked as local."""

        class LocalEngine(BaseSearchEngine):
            is_local = True
            is_public = False

            def run(self, query):
                return []

        assert LocalEngine.is_local is True
        assert LocalEngine.is_public is False

    def test_subclass_news_engine(self):
        """Subclass can be marked as news engine."""

        class NewsEngine(BaseSearchEngine):
            is_news = True
            is_public = True

            def run(self, query):
                return []

        assert NewsEngine.is_news is True

    def test_subclass_code_engine(self):
        """Subclass can be marked as code engine."""

        class CodeEngine(BaseSearchEngine):
            is_code = True
            is_public = True

            def run(self, query):
                return []

        assert CodeEngine.is_code is True


class TestSearchResultValidation:
    """Tests for search result validation."""

    def test_result_structure(self, mock_search_results):
        """Search results have expected structure."""
        for result in mock_search_results:
            assert "title" in result
            assert "link" in result
            assert "snippet" in result
            assert "source" in result

    def test_result_link_is_url(self, mock_search_results):
        """Result links are valid URLs."""
        for result in mock_search_results:
            link = result["link"]
            assert link.startswith("http://") or link.startswith("https://")

    def test_result_title_not_empty(self, mock_search_results):
        """Result titles are not empty."""
        for result in mock_search_results:
            assert len(result["title"]) > 0
