"""Extended tests for search_system_factory.py - covering _get_setting helper,
strategy creation edge cases, and unknown strategy fallback."""

from unittest.mock import Mock, patch


class TestGetSettingHelper:
    """Tests for _get_setting utility function."""

    def test_returns_default_when_no_snapshot(self):
        """Should return default when settings_snapshot is None."""
        from local_deep_research.search_system_factory import _get_setting

        result = _get_setting(None, "key", "default_value")
        assert result == "default_value"

    def test_returns_default_when_empty_snapshot(self):
        """Should return default when settings_snapshot is empty dict."""
        from local_deep_research.search_system_factory import _get_setting

        result = _get_setting({}, "key", "default_value")
        assert result == "default_value"

    def test_returns_default_when_key_missing(self):
        """Should return default when key is not in snapshot."""
        from local_deep_research.search_system_factory import _get_setting

        result = _get_setting({"other_key": "value"}, "key", "default_value")
        assert result == "default_value"

    def test_extracts_value_from_dict(self):
        """Should extract value from dict-wrapped setting."""
        from local_deep_research.search_system_factory import _get_setting

        snapshot = {"key": {"value": 42, "ui_element": "number"}}
        result = _get_setting(snapshot, "key", 0)
        assert result == 42

    def test_returns_direct_value(self):
        """Should return direct (non-dict) value."""
        from local_deep_research.search_system_factory import _get_setting

        snapshot = {"key": "direct_string"}
        result = _get_setting(snapshot, "key", "default")
        assert result == "direct_string"

    def test_returns_dict_without_value_key_as_is(self):
        """Dict without 'value' key should be returned as-is."""
        from local_deep_research.search_system_factory import _get_setting

        snapshot = {"key": {"other": "data"}}
        result = _get_setting(snapshot, "key", "default")
        assert result == {"other": "data"}

    def test_handles_boolean_values(self):
        """Should handle boolean values in settings."""
        from local_deep_research.search_system_factory import _get_setting

        snapshot = {"key": {"value": True}}
        result = _get_setting(snapshot, "key", False)
        assert result is True

    def test_handles_none_value_in_dict(self):
        """Should handle None as value in dict-wrapped setting."""
        from local_deep_research.search_system_factory import _get_setting

        snapshot = {"key": {"value": None}}
        result = _get_setting(snapshot, "key", "default")
        assert result is None

    def test_handles_zero_value(self):
        """Should handle 0 value correctly (not confuse with None)."""
        from local_deep_research.search_system_factory import _get_setting

        snapshot = {"key": {"value": 0}}
        result = _get_setting(snapshot, "key", 5)
        assert result == 0

    def test_handles_empty_string_value(self):
        """Should handle empty string value."""
        from local_deep_research.search_system_factory import _get_setting

        snapshot = {"key": {"value": ""}}
        result = _get_setting(snapshot, "key", "default")
        assert result == ""


class TestCreateStrategyNames:
    """Tests for strategy name handling in create_strategy."""

    def test_source_based_variants(self):
        """All source-based name variants should create SourceBasedSearchStrategy."""
        from local_deep_research.search_system_factory import create_strategy

        variants = ["source-based", "source_based", "source_based_search"]

        for variant in variants:
            strategy = create_strategy(
                strategy_name=variant,
                model=Mock(),
                search=Mock(),
            )
            assert type(strategy).__name__ == "SourceBasedSearchStrategy", (
                f"Variant '{variant}' did not create SourceBasedSearchStrategy"
            )

    def test_iterdrag_creates_correct_strategy(self):
        """iterdrag name should create IterDRAGStrategy."""
        from local_deep_research.search_system_factory import create_strategy

        strategy = create_strategy(
            strategy_name="iterdrag",
            model=Mock(),
            search=Mock(),
        )
        assert type(strategy).__name__ == "IterDRAGStrategy"

    def test_rapid_creates_correct_strategy(self):
        """rapid name should create RapidSearchStrategy."""
        from local_deep_research.search_system_factory import create_strategy

        strategy = create_strategy(
            strategy_name="rapid",
            model=Mock(),
            search=Mock(),
        )
        assert type(strategy).__name__ == "RapidSearchStrategy"

    def test_parallel_creates_correct_strategy(self):
        """parallel name should create ParallelSearchStrategy."""
        from local_deep_research.search_system_factory import create_strategy

        strategy = create_strategy(
            strategy_name="parallel",
            model=Mock(),
            search=Mock(),
        )
        assert type(strategy).__name__ == "ParallelSearchStrategy"

    def test_standard_creates_correct_strategy(self):
        """standard name should create StandardSearchStrategy."""
        from local_deep_research.search_system_factory import create_strategy

        settings = {
            "search.iterations": {"value": 3},
            "search.questions_per_iteration": {"value": 3},
            "general.knowledge_accumulation_context_limit": {"value": 50000},
        }

        with patch(
            "local_deep_research.citation_handlers.standard_citation_handler.StandardCitationHandler"
        ):
            strategy = create_strategy(
                strategy_name="standard",
                model=Mock(),
                search=Mock(),
                settings_snapshot=settings,
            )
        assert type(strategy).__name__ == "StandardSearchStrategy"


class TestCreateStrategyUnknown:
    """Tests for unknown strategy name handling."""

    def test_unknown_strategy_falls_back_to_source_based(self):
        """Unknown strategy name should fall back to SourceBasedSearchStrategy."""
        from local_deep_research.search_system_factory import create_strategy

        strategy = create_strategy(
            strategy_name="nonexistent_strategy_xyz",
            model=Mock(),
            search=Mock(),
        )
        assert type(strategy).__name__ == "SourceBasedSearchStrategy"

    def test_empty_string_strategy_falls_back(self):
        """Empty string strategy should fall back to source-based."""
        from local_deep_research.search_system_factory import create_strategy

        strategy = create_strategy(
            strategy_name="",
            model=Mock(),
            search=Mock(),
        )
        assert type(strategy).__name__ == "SourceBasedSearchStrategy"


class TestCreateStrategyKwargsPassthrough:
    """Tests for kwargs passthrough to strategies."""

    def test_source_based_receives_kwargs(self):
        """Source-based strategy should receive kwargs."""
        from local_deep_research.search_system_factory import create_strategy

        strategy = create_strategy(
            strategy_name="source-based",
            model=Mock(),
            search=Mock(),
            include_text_content=False,
            use_cross_engine_filter=False,
            use_atomic_facts=True,
        )

        assert strategy.include_text_content is False
        assert strategy.use_cross_engine_filter is False

    def test_iterative_strategy_receives_iteration_settings(self):
        """Iterative strategy should receive iteration settings from kwargs."""
        from local_deep_research.search_system_factory import create_strategy

        strategy = create_strategy(
            strategy_name="iterative",
            model=Mock(),
            search=Mock(),
            max_iterations=15,
            questions_per_iteration=5,
            confidence_threshold=0.85,
        )

        assert strategy.max_iterations == 15
        assert strategy.confidence_threshold == 0.85


class TestCreateStrategySettingsSnapshot:
    """Tests for settings snapshot integration in create_strategy."""

    def test_all_links_initialized_when_none(self):
        """all_links_of_system should be initialized to empty list when None."""
        from local_deep_research.search_system_factory import create_strategy

        strategy = create_strategy(
            strategy_name="rapid",
            model=Mock(),
            search=Mock(),
            all_links_of_system=None,
        )

        assert strategy.all_links_of_system == []

    def test_all_links_passed_through(self):
        """Provided all_links_of_system should be passed to strategy."""
        from local_deep_research.search_system_factory import create_strategy

        existing_links = [{"url": "http://example.com", "title": "Test"}]

        strategy = create_strategy(
            strategy_name="rapid",
            model=Mock(),
            search=Mock(),
            all_links_of_system=existing_links,
        )

        assert strategy.all_links_of_system is existing_links

    def test_settings_snapshot_passed_to_strategy(self):
        """Settings snapshot should be passed to strategy."""
        from local_deep_research.search_system_factory import create_strategy

        settings = {"some.setting": "value"}

        strategy = create_strategy(
            strategy_name="source-based",
            model=Mock(),
            search=Mock(),
            settings_snapshot=settings,
        )

        assert strategy.settings_snapshot is settings


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

    def test_focused_iteration_reads_settings(self):
        """Focused iteration should read settings from snapshot."""
        from local_deep_research.search_system_factory import create_strategy

        settings = {
            "focused_iteration.adaptive_questions": {"value": 1},
            "focused_iteration.knowledge_summary_limit": {"value": 5},
            "focused_iteration.snippet_truncate": {"value": 100},
        }

        strategy = create_strategy(
            strategy_name="focused-iteration",
            model=Mock(),
            search=Mock(),
            settings_snapshot=settings,
        )

        assert strategy.enable_adaptive_questions is True
        assert strategy.knowledge_summary_limit == 5
        assert strategy.knowledge_snippet_truncate == 100

    def test_focused_iteration_zero_converts_to_none(self):
        """Knowledge limit of 0 should be converted to None (unlimited)."""
        from local_deep_research.search_system_factory import create_strategy

        settings = {
            "focused_iteration.knowledge_summary_limit": {"value": 0},
            "focused_iteration.snippet_truncate": {"value": 0},
        }

        strategy = create_strategy(
            strategy_name="focused-iteration",
            model=Mock(),
            search=Mock(),
            settings_snapshot=settings,
        )

        assert strategy.knowledge_summary_limit is None
        assert strategy.knowledge_snippet_truncate is None

    def test_focused_iteration_name_variants(self):
        """Both focused-iteration name variants should work."""
        from local_deep_research.search_system_factory import create_strategy

        for variant in ["focused-iteration", "focused_iteration"]:
            strategy = create_strategy(
                strategy_name=variant,
                model=Mock(),
                search=Mock(),
            )
            assert type(strategy).__name__ == "FocusedIterationStrategy"


class TestCreateStrategyCaseInsensitivity:
    """Tests for case handling in strategy names."""

    def test_lowercase_matching(self):
        """Strategy names should be matched case-insensitively."""
        from local_deep_research.search_system_factory import create_strategy

        # The function calls .lower() on strategy_name
        strategy = create_strategy(
            strategy_name="RAPID",
            model=Mock(),
            search=Mock(),
        )
        assert type(strategy).__name__ == "RapidSearchStrategy"

    def test_mixed_case_matching(self):
        """Mixed case strategy names should work."""
        from local_deep_research.search_system_factory import create_strategy

        strategy = create_strategy(
            strategy_name="Source-Based",
            model=Mock(),
            search=Mock(),
        )
        assert type(strategy).__name__ == "SourceBasedSearchStrategy"
