"""
Tests for search_system_factory.py

Tests cover:
- _get_setting helper function
- create_strategy factory function
- Strategy name normalization
"""

from unittest.mock import Mock, patch


class TestGetSetting:
    """Tests for _get_setting helper function."""

    def test_get_setting_returns_default_for_empty_snapshot(self):
        """Test _get_setting returns default for empty snapshot."""
        from local_deep_research.search_system_factory import _get_setting

        result = _get_setting(None, "test.key", "default")
        assert result == "default"

    def test_get_setting_returns_default_for_missing_key(self):
        """Test _get_setting returns default for missing key."""
        from local_deep_research.search_system_factory import _get_setting

        result = _get_setting({"other.key": "value"}, "test.key", "default")
        assert result == "default"

    def test_get_setting_returns_value_directly(self):
        """Test _get_setting returns value directly if not dict."""
        from local_deep_research.search_system_factory import _get_setting

        result = _get_setting(
            {"test.key": "direct_value"}, "test.key", "default"
        )
        assert result == "direct_value"

    def test_get_setting_extracts_value_from_dict(self):
        """Test _get_setting extracts value from dict structure."""
        from local_deep_research.search_system_factory import _get_setting

        snapshot = {"test.key": {"value": "nested_value", "extra": "ignored"}}
        result = _get_setting(snapshot, "test.key", "default")
        assert result == "nested_value"

    def test_get_setting_handles_integer_value(self):
        """Test _get_setting handles integer values."""
        from local_deep_research.search_system_factory import _get_setting

        result = _get_setting({"iterations": 5}, "iterations", 10)
        assert result == 5

    def test_get_setting_handles_boolean_value(self):
        """Test _get_setting handles boolean values."""
        from local_deep_research.search_system_factory import _get_setting

        result = _get_setting({"enabled": True}, "enabled", False)
        assert result is True


class TestCreateStrategySourceBased:
    """Tests for create_strategy with source-based strategy."""

    def test_create_source_based_strategy(self):
        """Test creating source-based strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.source_based_strategy.SourceBasedSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            result = create_strategy(
                strategy_name="source-based",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()
            assert result == mock_strategy

    def test_create_source_based_with_underscore(self):
        """Test creating source_based strategy (underscore variant)."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.source_based_strategy.SourceBasedSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="source_based",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()

    def test_create_source_based_passes_parameters(self):
        """Test source-based strategy receives correct parameters."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.source_based_strategy.SourceBasedSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="source-based",
                model=mock_model,
                search=mock_search,
                include_text_content=False,
                use_cross_engine_filter=False,
            )

            call_kwargs = mock_strategy_class.call_args[1]
            assert call_kwargs["include_text_content"] is False
            assert call_kwargs["use_cross_engine_filter"] is False


class TestCreateStrategyStandard:
    """Tests for create_strategy with standard strategy."""

    def test_create_standard_strategy(self):
        """Test creating standard strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.standard_strategy.StandardSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="standard",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()


class TestCreateStrategyIterdrag:
    """Tests for create_strategy with iterdrag strategy."""

    def test_create_iterdrag_strategy(self):
        """Test creating iterdrag strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.iterdrag_strategy.IterDRAGStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="iterdrag",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()


class TestCreateStrategyEvidence:
    """Tests for create_strategy with evidence-based strategy."""

    def test_create_evidence_strategy(self):
        """Test creating evidence strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.evidence_based_strategy_v2.EnhancedEvidenceBasedStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="evidence",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()


class TestCreateStrategyConstraint:
    """Tests for create_strategy with constraint-based strategies."""

    def test_create_constrained_strategy(self):
        """Test creating constrained strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.constrained_search_strategy.ConstrainedSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="constrained",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()

    def test_create_parallel_constrained_strategy(self):
        """Test creating parallel-constrained strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.parallel_constrained_strategy.ParallelConstrainedStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="parallel-constrained",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()


class TestCreateStrategyDualConfidence:
    """Tests for create_strategy with dual-confidence strategies."""

    def test_create_dual_confidence_strategy(self):
        """Test creating dual-confidence strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.dual_confidence_strategy.DualConfidenceStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="dual-confidence",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()

    def test_create_concurrent_dual_confidence(self):
        """Test creating concurrent-dual-confidence strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.concurrent_dual_confidence_strategy.ConcurrentDualConfidenceStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="concurrent-dual-confidence",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()


class TestCreateStrategyBrowsecomp:
    """Tests for create_strategy with browsecomp-optimized strategy."""

    def test_create_browsecomp_strategy(self):
        """Test creating browsecomp-optimized strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.browsecomp_optimized_strategy.BrowseCompOptimizedStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="browsecomp",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()


class TestCreateStrategyNews:
    """Tests for create_strategy with news strategy."""

    def test_create_news_strategy(self):
        """Test creating news strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.news_strategy.NewsAggregationStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="news",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()


class TestCreateStrategyFocusedIteration:
    """Tests for create_strategy with focused-iteration strategy."""

    def test_create_focused_iteration_strategy(self):
        """Test creating focused-iteration strategy."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.focused_iteration_strategy.FocusedIterationStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="focused-iteration",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()

    def test_focused_iteration_with_settings(self):
        """Test focused-iteration strategy uses settings."""
        mock_model = Mock()
        mock_search = Mock()
        settings = {
            "focused_iteration.adaptive_questions": 1,
            "focused_iteration.knowledge_summary_limit": 5,
        }

        with patch(
            "local_deep_research.advanced_search_system.strategies.focused_iteration_strategy.FocusedIterationStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="focused-iteration",
                model=mock_model,
                search=mock_search,
                settings_snapshot=settings,
            )

            call_kwargs = mock_strategy_class.call_args[1]
            assert call_kwargs["enable_adaptive_questions"] is True


class TestCreateStrategyCaseInsensitive:
    """Tests for strategy name case insensitivity."""

    def test_strategy_name_lowercase(self):
        """Test strategy name is case-insensitive."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.standard_strategy.StandardSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="STANDARD",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()

    def test_strategy_name_mixed_case(self):
        """Test mixed case strategy name."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.standard_strategy.StandardSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="Standard",
                model=mock_model,
                search=mock_search,
            )

            mock_strategy_class.assert_called_once()


class TestCreateStrategyWithAllLinks:
    """Tests for create_strategy with all_links_of_system parameter."""

    def test_create_strategy_with_empty_links(self):
        """Test create_strategy with empty links."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.standard_strategy.StandardSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="standard",
                model=mock_model,
                search=mock_search,
                all_links_of_system=[],
            )

            call_kwargs = mock_strategy_class.call_args[1]
            assert call_kwargs["all_links_of_system"] == []

    def test_create_strategy_with_existing_links(self):
        """Test create_strategy with existing links."""
        mock_model = Mock()
        mock_search = Mock()
        links = [{"link": "url1"}, {"link": "url2"}]

        with patch(
            "local_deep_research.advanced_search_system.strategies.standard_strategy.StandardSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="standard",
                model=mock_model,
                search=mock_search,
                all_links_of_system=links,
            )

            call_kwargs = mock_strategy_class.call_args[1]
            assert call_kwargs["all_links_of_system"] == links

    def test_create_strategy_none_links_becomes_empty_list(self):
        """Test None links becomes empty list."""
        mock_model = Mock()
        mock_search = Mock()

        with patch(
            "local_deep_research.advanced_search_system.strategies.standard_strategy.StandardSearchStrategy"
        ) as mock_strategy_class:
            mock_strategy = Mock()
            mock_strategy_class.return_value = mock_strategy

            from local_deep_research.search_system_factory import (
                create_strategy,
            )

            create_strategy(
                strategy_name="standard",
                model=mock_model,
                search=mock_search,
                all_links_of_system=None,
            )

            call_kwargs = mock_strategy_class.call_args[1]
            assert call_kwargs["all_links_of_system"] == []
