"""
Tests for uncovered code paths in FullSearchResults.

Targets:
- _get_full_content() method (entirely untested)
- SSRF validation blocking all URLs
- check_urls with null LLM
- run() with SSRF-blocked URLs returning results without full content
"""

from unittest.mock import Mock, patch


class TestGetFullContent:
    """Tests for _get_full_content method."""

    def _make_engine(self):
        from local_deep_research.web_search_engines.engines.full_search import (
            FullSearchResults,
        )

        mock_llm = Mock()
        mock_web_search = Mock()
        engine = FullSearchResults(llm=mock_llm, web_search=mock_web_search)
        return engine

    def test_get_full_content_all_urls_valid(self):
        """_get_full_content fetches content for valid URLs."""
        engine = self._make_engine()

        items = [
            {"link": "https://example.com/1", "title": "R1"},
            {"link": "https://example.com/2", "title": "R2"},
        ]

        mock_doc1 = Mock()
        mock_doc1.page_content = "<p>Content 1</p>"
        mock_doc1.metadata = {"source": "https://example.com/1"}
        mock_doc2 = Mock()
        mock_doc2.page_content = "<p>Content 2</p>"
        mock_doc2.metadata = {"source": "https://example.com/2"}

        with patch(
            "local_deep_research.web_search_engines.engines.full_search.validate_url",
            return_value=True,
        ):
            with patch(
                "local_deep_research.web_search_engines.engines.full_search.AsyncChromiumLoader"
            ) as mock_loader:
                mock_loader.return_value.load.return_value = [
                    mock_doc1,
                    mock_doc2,
                ]
                engine.bs_transformer = Mock()
                engine.bs_transformer.transform_documents.return_value = [
                    mock_doc1,
                    mock_doc2,
                ]

                with patch.object(
                    engine,
                    "remove_boilerplate",
                    side_effect=["Clean 1", "Clean 2"],
                ):
                    result = engine._get_full_content(items)

        assert result[0]["full_content"] == "Clean 1"
        assert result[1]["full_content"] == "Clean 2"

    def test_get_full_content_no_valid_urls(self):
        """_get_full_content returns items with None content when all URLs fail SSRF."""
        engine = self._make_engine()

        items = [
            {"link": "http://192.168.1.1/internal", "title": "R1"},
            {"link": "http://10.0.0.1/secret", "title": "R2"},
        ]

        with patch(
            "local_deep_research.web_search_engines.engines.full_search.validate_url",
            return_value=False,
        ):
            result = engine._get_full_content(items)

        assert result[0]["full_content"] is None
        assert result[1]["full_content"] is None

    def test_get_full_content_loader_exception(self):
        """_get_full_content returns None content on loader exception."""
        engine = self._make_engine()

        items = [{"link": "https://example.com/1", "title": "R1"}]

        with patch(
            "local_deep_research.web_search_engines.engines.full_search.validate_url",
            return_value=True,
        ):
            with patch(
                "local_deep_research.web_search_engines.engines.full_search.AsyncChromiumLoader"
            ) as mock_loader:
                mock_loader.return_value.load.side_effect = Exception(
                    "Network error"
                )

                result = engine._get_full_content(items)

        assert result[0]["full_content"] is None

    def test_get_full_content_item_without_link(self):
        """_get_full_content handles items without link key."""
        engine = self._make_engine()

        items = [
            {"title": "No link item"},
            {"link": "https://example.com/1", "title": "Has link"},
        ]

        with patch(
            "local_deep_research.web_search_engines.engines.full_search.validate_url",
            return_value=True,
        ):
            with patch(
                "local_deep_research.web_search_engines.engines.full_search.AsyncChromiumLoader"
            ) as mock_loader:
                mock_doc = Mock()
                mock_doc.page_content = "<p>Content</p>"
                mock_doc.metadata = {"source": "https://example.com/1"}
                mock_loader.return_value.load.return_value = [mock_doc]
                engine.bs_transformer = Mock()
                engine.bs_transformer.transform_documents.return_value = [
                    mock_doc
                ]

                with patch.object(
                    engine, "remove_boilerplate", return_value="Clean"
                ):
                    result = engine._get_full_content(items)

        assert result[0]["full_content"] is None  # No link -> None
        assert result[1]["full_content"] == "Clean"

    def test_get_full_content_mixed_ssrf_validation(self):
        """_get_full_content handles mix of valid and SSRF-blocked URLs."""
        engine = self._make_engine()

        items = [
            {"link": "https://example.com/ok", "title": "Good"},
            {"link": "http://192.168.1.1/bad", "title": "Bad"},
        ]

        def mock_validate(url):
            return "example.com" in url

        with patch(
            "local_deep_research.web_search_engines.engines.full_search.validate_url",
            side_effect=mock_validate,
        ):
            with patch(
                "local_deep_research.web_search_engines.engines.full_search.AsyncChromiumLoader"
            ) as mock_loader:
                mock_doc = Mock()
                mock_doc.page_content = "<p>Content</p>"
                mock_doc.metadata = {"source": "https://example.com/ok"}
                mock_loader.return_value.load.return_value = [mock_doc]
                engine.bs_transformer = Mock()
                engine.bs_transformer.transform_documents.return_value = [
                    mock_doc
                ]

                with patch.object(
                    engine, "remove_boilerplate", return_value="Clean"
                ):
                    result = engine._get_full_content(items)

        assert result[0]["full_content"] == "Clean"
        # Item with SSRF-blocked link won't be in url_to_content
        assert result[1]["full_content"] is None


class TestCheckUrlsNullLlm:
    """Tests for check_urls with null LLM."""

    def test_check_urls_null_llm_returns_results_unchanged(self):
        """check_urls returns results unchanged when LLM is None."""
        from local_deep_research.web_search_engines.engines.full_search import (
            FullSearchResults,
        )

        mock_web_search = Mock()
        engine = FullSearchResults(llm=None, web_search=mock_web_search)

        results = [
            {"link": "https://example.com/1", "title": "Result 1"},
            {"link": "https://example.com/2", "title": "Result 2"},
        ]

        filtered = engine.check_urls(results, "test query")

        assert filtered == results
        assert len(filtered) == 2


class TestRunSsrfBlocking:
    """Tests for run() SSRF blocking paths."""

    def test_run_all_urls_ssrf_blocked(self):
        """run() returns results without full content when all URLs fail SSRF."""
        from local_deep_research.web_search_engines.engines.full_search import (
            FullSearchResults,
        )

        mock_llm = Mock()
        mock_web_search = Mock()
        mock_web_search.invoke.return_value = [
            {"link": "http://192.168.1.1/internal", "title": "Internal"},
        ]

        with patch(
            "local_deep_research.web_search_engines.engines.full_search.QUALITY_CHECK_DDG_URLS",
            False,
        ):
            with patch(
                "local_deep_research.web_search_engines.engines.full_search.validate_url",
                return_value=False,
            ):
                engine = FullSearchResults(
                    llm=mock_llm, web_search=mock_web_search
                )
                results = engine.run("test query")

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

    def test_run_doc_without_source_metadata(self):
        """run() handles documents without source in metadata."""
        from local_deep_research.web_search_engines.engines.full_search import (
            FullSearchResults,
        )

        mock_llm = Mock()
        mock_web_search = Mock()
        mock_web_search.invoke.return_value = [
            {"link": "https://example.com/1", "title": "R1"},
        ]

        with patch(
            "local_deep_research.web_search_engines.engines.full_search.QUALITY_CHECK_DDG_URLS",
            False,
        ):
            with patch(
                "local_deep_research.web_search_engines.engines.full_search.validate_url",
                return_value=True,
            ):
                with patch(
                    "local_deep_research.web_search_engines.engines.full_search.AsyncChromiumLoader"
                ) as mock_loader:
                    # Doc without source metadata
                    mock_doc = Mock()
                    mock_doc.page_content = "<p>Content</p>"
                    mock_doc.metadata = {}  # No source
                    mock_loader.return_value.load.return_value = [mock_doc]

                    engine = FullSearchResults(
                        llm=mock_llm, web_search=mock_web_search
                    )
                    engine.bs_transformer = Mock()
                    engine.bs_transformer.transform_documents.return_value = [
                        mock_doc
                    ]

                    results = engine.run("test query")

        assert len(results) == 1
        # No source in metadata -> no content mapped
        assert results[0]["full_content"] is None
