"""
Tests for web_search_engines/search_engine_base.py

Tests cover:
- BaseSearchEngine class attributes
- AdaptiveWait strategy
- Engine class loading
- Search methods
"""

import pytest
from unittest.mock import Mock


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

    def test_is_public_default(self):
        """Test default is_public attribute."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        assert BaseSearchEngine.is_public is False

    def test_is_generic_default(self):
        """Test default is_generic attribute."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        assert BaseSearchEngine.is_generic is False

    def test_is_scientific_default(self):
        """Test default is_scientific attribute."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        assert BaseSearchEngine.is_scientific is False

    def test_is_local_default(self):
        """Test default is_local attribute."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        assert BaseSearchEngine.is_local is False

    def test_is_news_default(self):
        """Test default is_news attribute."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        assert BaseSearchEngine.is_news is False

    def test_is_code_default(self):
        """Test default is_code attribute."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        assert BaseSearchEngine.is_code is False


class TestAdaptiveWait:
    """Tests for AdaptiveWait class."""

    def test_adaptive_wait_init(self):
        """Test AdaptiveWait initialization."""
        from local_deep_research.web_search_engines.search_engine_base import (
            AdaptiveWait,
        )

        def get_wait():
            return 5.0

        wait = AdaptiveWait(get_wait)
        assert wait.get_wait_func == get_wait

    def test_adaptive_wait_call(self):
        """Test AdaptiveWait __call__ method."""
        from local_deep_research.web_search_engines.search_engine_base import (
            AdaptiveWait,
        )

        def get_wait():
            return 2.5

        wait = AdaptiveWait(get_wait)
        mock_retry_state = Mock()

        result = wait(mock_retry_state)

        assert result == 2.5


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

    def test_load_engine_class_missing_module_path(self):
        """Test loading engine with missing module_path."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        config = {"class_name": "SomeClass"}  # Missing module_path
        success, engine_class, error_msg = BaseSearchEngine._load_engine_class(
            "test_engine", config
        )

        assert success is False
        assert engine_class is None
        assert "Missing module_path" in error_msg

    def test_load_engine_class_missing_class_name(self):
        """Test loading engine with missing class_name."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        config = {"module_path": "some.module"}  # Missing class_name
        success, engine_class, error_msg = BaseSearchEngine._load_engine_class(
            "test_engine", config
        )

        assert success is False
        assert engine_class is None
        assert "Missing" in error_msg

    def test_load_engine_class_success(self):
        """Test successful engine class loading."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        # Use a relative module path (required by the security whitelist)
        config = {
            "module_path": ".search_engine_base",
            "class_name": "BaseSearchEngine",
        }
        success, engine_class, error_msg = BaseSearchEngine._load_engine_class(
            "test_engine", config
        )

        assert success is True
        assert engine_class is BaseSearchEngine
        assert error_msg is None

    def test_load_engine_class_relative_import(self):
        """Test loading with relative import."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        config = {
            "module_path": ".search_engine_base",
            "class_name": "BaseSearchEngine",
        }
        success, engine_class, error_msg = BaseSearchEngine._load_engine_class(
            "test_engine", config
        )

        assert success is True
        assert engine_class is BaseSearchEngine

    def test_load_engine_class_nonexistent_module(self):
        """Test loading with nonexistent module."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

        config = {
            "module_path": "nonexistent.module.path",
            "class_name": "SomeClass",
        }
        success, engine_class, error_msg = BaseSearchEngine._load_engine_class(
            "test_engine", config
        )

        assert success is False
        assert engine_class is None
        assert error_msg is not None


class TestConcreteSearchEngine:
    """Tests using a concrete search engine implementation."""

    @pytest.fixture
    def concrete_engine_class(self):
        """Create a concrete search engine for testing."""
        from local_deep_research.web_search_engines.search_engine_base import (
            BaseSearchEngine,
        )

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

            def __init__(self, **kwargs):
                self.llm = kwargs.get("llm")
                self.max_results = kwargs.get("max_results", 10)

            def _get_previews(self, query, num_results=None, *args, **kwargs):
                return [
                    {"title": "Result 1", "link": "http://example.com/1"},
                    {"title": "Result 2", "link": "http://example.com/2"},
                ]

            def _get_full_content(self, relevant_items):
                return [
                    {
                        "title": r["title"],
                        "link": r["link"],
                        "full_content": "content",
                    }
                    for r in relevant_items
                ]

        return ConcreteSearchEngine

    def test_concrete_engine_class_attributes(self, concrete_engine_class):
        """Test concrete engine class attributes."""
        assert concrete_engine_class.is_public is True
        assert concrete_engine_class.is_generic is True
        assert concrete_engine_class.is_scientific is False

    def test_concrete_engine_init(self, concrete_engine_class):
        """Test concrete engine initialization."""
        engine = concrete_engine_class(max_results=5)
        assert engine.max_results == 5

    def test_concrete_engine_get_previews(self, concrete_engine_class):
        """Test concrete engine _get_previews."""
        engine = concrete_engine_class()
        results = engine._get_previews("test query")

        assert len(results) == 2
        assert results[0]["title"] == "Result 1"

    def test_concrete_engine_get_full_content(self, concrete_engine_class):
        """Test concrete engine _get_full_content."""
        engine = concrete_engine_class()
        items = [{"title": "Test", "link": "http://test.com"}]
        results = engine._get_full_content(items)

        assert len(results) == 1
        assert "full_content" in results[0]
