"""
Tests for MetaSearchEngine covering the LLM-based _analyze_query_with_llm path
(lines 259-350) and related branches.

Covers:
- Lines 259-350: Full LLM-based engine selection flow
- Engine info prompt building with config
- Response parsing (content attr vs str)
- SearXNG fallback when not selected by LLM
- No valid engines → reliability fallback
- Exception in LLM invocation → fallback
"""

from unittest.mock import MagicMock, patch


MODULE = "local_deep_research.web_search_engines.engines.meta_search_engine"


def _make_meta_engine(
    available_engines=None,
    llm_response="searxng,wikipedia",
    settings_snapshot=None,
):
    """Create a MetaSearchEngine with mocked internals."""
    from local_deep_research.web_search_engines.engines.meta_search_engine import (
        MetaSearchEngine,
    )

    mock_llm = MagicMock()
    mock_llm.invoke.return_value = MagicMock(content=llm_response)

    with patch.object(
        MetaSearchEngine,
        "_get_available_engines",
        return_value=available_engines or ["searxng", "wikipedia", "brave"],
    ):
        with patch(f"{MODULE}.WikipediaSearchEngine"):
            engine = MetaSearchEngine(
                llm=mock_llm,
                max_results=10,
                settings_snapshot=settings_snapshot or {},
            )

    return engine


class TestAnalyzeQueryLLMPath:
    """Test the LLM-based engine selection in analyze_query (lines 259-350)."""

    def test_no_searxng_no_llm_returns_reliability_sorted(self):
        """Without searxng and no LLM, reliability-based sorting is used."""
        engine = _make_meta_engine(
            available_engines=["brave", "wikipedia", "arxiv"],
        )
        engine.llm = None
        result = engine.analyze_query("generic query")
        assert isinstance(result, list)
        assert len(result) == 3

    def test_analyze_query_specialized_domain(self):
        """Specialized query terms like 'scientific paper' select specific engines."""
        engine = _make_meta_engine(
            available_engines=["arxiv", "pubmed", "wikipedia", "searxng"],
        )
        result = engine.analyze_query("scientific paper on quantum computing")
        assert result[0] == "arxiv"

    def test_analyze_query_arxiv_keyword(self):
        """Query containing 'arxiv' prioritizes arxiv engine."""
        engine = _make_meta_engine(
            available_engines=["arxiv", "wikipedia", "searxng"],
        )
        result = engine.analyze_query("arxiv papers on AI")
        assert result[0] == "arxiv"

    def test_analyze_query_pubmed_keyword(self):
        """Query containing 'pubmed' prioritizes pubmed engine."""
        engine = _make_meta_engine(
            available_engines=["pubmed", "wikipedia", "searxng"],
        )
        result = engine.analyze_query("pubmed clinical trials")
        assert result[0] == "pubmed"

    def test_analyze_query_searxng_first_for_general(self):
        """General query with searxng available returns searxng first."""
        engine = _make_meta_engine(
            available_engines=["searxng", "wikipedia", "brave"],
        )
        result = engine.analyze_query("what is the weather today")
        assert result[0] == "searxng"

    def test_analyze_query_no_searxng_no_llm(self):
        """Without searxng or LLM, returns reliability-sorted engines."""
        engine = _make_meta_engine(
            available_engines=["wikipedia", "brave"],
        )
        engine.llm = None
        result = engine.analyze_query("general question")
        assert isinstance(result, list)
        assert len(result) == 2

    def test_analyze_query_no_searxng_with_llm(self):
        """Without searxng but with LLM, line 245 returns reliability-sorted."""
        engine = _make_meta_engine(
            available_engines=["wikipedia", "brave"],
        )
        result = engine.analyze_query("general question")
        # Line 245 condition: searxng not in available → returns reliability sort
        assert isinstance(result, list)

    def test_analyze_query_specialized_no_matching_engines(self):
        """Specialized term but no matching engines available → falls through."""
        engine = _make_meta_engine(
            available_engines=["searxng", "brave"],
        )
        # "scientific paper" matches but neither arxiv nor pubmed nor wikipedia available
        result = engine.analyze_query("scientific paper on topic")
        # Falls through to searxng-first path
        assert result[0] == "searxng"

    def test_analyze_query_code_related(self):
        """Code-related query selects github if available."""
        engine = _make_meta_engine(
            available_engines=["github", "searxng", "wikipedia"],
        )
        result = engine.analyze_query("code implementation of binary search")
        assert "github" in result

    def test_analyze_query_github_related(self):
        """Repository-related query selects github."""
        engine = _make_meta_engine(
            available_engines=["github", "searxng", "wikipedia"],
        )
        result = engine.analyze_query("repository for machine learning models")
        assert "github" in result

    def test_analyze_query_medical(self):
        """Medical/clinical query selects pubmed if available."""
        engine = _make_meta_engine(
            available_engines=["pubmed", "searxng", "wikipedia"],
        )
        result = engine.analyze_query("clinical trial results for aspirin")
        assert result[0] == "pubmed"


class TestGetSearchConfig:
    """Test _get_search_config method."""

    def test_empty_snapshot(self):
        """Empty settings_snapshot returns empty config."""
        engine = _make_meta_engine(settings_snapshot={})
        engine.settings_snapshot = {}
        config = engine._get_search_config()
        assert config == {} or isinstance(config, dict)

    def test_no_snapshot(self):
        """None settings_snapshot logs warning and returns empty."""
        engine = _make_meta_engine(settings_snapshot={})
        engine.settings_snapshot = None
        config = engine._get_search_config()
        assert config == {}

    def test_delegates_to_get_available_engines(self):
        """_get_search_config delegates to the shared get_available_engines function."""
        expected = {"brave": {"api_key": "test-key", "reliability": 0.8}}
        engine = _make_meta_engine(settings_snapshot={"search.max_results": 10})
        engine.settings_snapshot = {"search.max_results": 10}

        with patch(
            "local_deep_research.web_search_engines.engines.meta_search_engine.get_available_engines",
            return_value=expected,
        ):
            config = engine._get_search_config()
        assert "brave" in config
        assert config["brave"]["api_key"] == "test-key"
