"""
Tests for the RetrieverSearchEngine class.

Tests cover:
- Initialization and configuration
- Document conversion
- Preview generation
- Full content retrieval
- Async search
"""

from unittest.mock import Mock, MagicMock, AsyncMock
import pytest


class TestRetrieverSearchEngineInit:
    """Tests for RetrieverSearchEngine initialization."""

    def test_init_with_retriever(self):
        """Initialize with a retriever."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "MockRetriever"

        engine = RetrieverSearchEngine(retriever=mock_retriever)

        assert engine.retriever is mock_retriever
        assert engine.max_results == 10
        assert engine.name == "MockRetriever"

    def test_init_with_custom_name(self):
        """Initialize with custom name."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        engine = RetrieverSearchEngine(
            retriever=mock_retriever, name="CustomRetriever"
        )

        assert engine.name == "CustomRetriever"

    def test_init_with_custom_max_results(self):
        """Initialize with custom max_results."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        engine = RetrieverSearchEngine(retriever=mock_retriever, max_results=25)

        assert engine.max_results == 25


class TestRun:
    """Tests for run method."""

    def test_run_returns_results(self):
        """Run returns search results."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        # Create mock documents
        mock_doc1 = Mock()
        mock_doc1.page_content = "This is document 1 content"
        mock_doc1.metadata = {
            "title": "Doc 1",
            "source": "https://example.com/1",
        }

        mock_doc2 = Mock()
        mock_doc2.page_content = "This is document 2 content"
        mock_doc2.metadata = {"title": "Doc 2", "url": "https://example.com/2"}

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"
        mock_retriever.invoke.return_value = [mock_doc1, mock_doc2]

        engine = RetrieverSearchEngine(retriever=mock_retriever)
        results = engine.run("test query")

        assert len(results) == 2
        assert results[0]["title"] == "Doc 1"
        assert results[0]["url"] == "https://example.com/1"
        assert "document 1 content" in results[0]["snippet"]
        assert results[1]["title"] == "Doc 2"

    def test_run_respects_max_results(self):
        """Run respects max_results limit."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        # Create 5 mock documents
        mock_docs = []
        for i in range(5):
            doc = Mock()
            doc.page_content = f"Content {i}"
            doc.metadata = {"title": f"Doc {i}"}
            mock_docs.append(doc)

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"
        mock_retriever.invoke.return_value = mock_docs

        engine = RetrieverSearchEngine(retriever=mock_retriever, max_results=2)
        results = engine.run("test query")

        assert len(results) == 2

    def test_run_exception(self):
        """Run handles exceptions."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"
        mock_retriever.invoke.side_effect = Exception("Retriever error")

        engine = RetrieverSearchEngine(retriever=mock_retriever)
        results = engine.run("test query")

        assert results == []


class TestConvertDocumentToResult:
    """Tests for _convert_document_to_result method."""

    def test_convert_with_full_metadata(self):
        """Convert document with full metadata."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"

        engine = RetrieverSearchEngine(retriever=mock_retriever)

        mock_doc = Mock()
        mock_doc.page_content = "Full document content here"
        mock_doc.metadata = {
            "title": "Test Document",
            "source": "https://example.com/doc",
            "author": "John Doe",
            "date": "2024-01-15",
            "score": 0.95,
        }

        result = engine._convert_document_to_result(mock_doc, 0)

        assert result["title"] == "Test Document"
        assert result["url"] == "https://example.com/doc"
        assert result["author"] == "John Doe"
        assert result["date"] == "2024-01-15"
        assert result["score"] == 0.95
        assert result["full_content"] == "Full document content here"

    def test_convert_with_minimal_metadata(self):
        """Convert document with minimal metadata."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"

        engine = RetrieverSearchEngine(
            retriever=mock_retriever, name="MyRetriever"
        )

        mock_doc = Mock()
        mock_doc.page_content = "Simple content"
        mock_doc.metadata = {}

        result = engine._convert_document_to_result(mock_doc, 2)

        assert result["title"] == "Document 3"
        assert "retriever://MyRetriever/doc_2" in result["url"]
        assert result["author"] == ""
        assert result["source"] == "MyRetriever"

    def test_convert_truncates_long_content(self):
        """Convert document truncates long content in snippet."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"

        engine = RetrieverSearchEngine(retriever=mock_retriever)

        mock_doc = Mock()
        mock_doc.page_content = "A" * 1000  # Long content
        mock_doc.metadata = {}

        result = engine._convert_document_to_result(mock_doc, 0)

        assert len(result["snippet"]) == 500
        assert result["full_content"] == "A" * 1000

    def test_convert_uses_url_metadata_fallback(self):
        """Convert document uses url metadata as fallback."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"

        engine = RetrieverSearchEngine(retriever=mock_retriever)

        mock_doc = Mock()
        mock_doc.page_content = "Content"
        mock_doc.metadata = {"url": "https://example.com/from-url"}

        result = engine._convert_document_to_result(mock_doc, 0)

        assert result["url"] == "https://example.com/from-url"


class TestGetPreviews:
    """Tests for _get_previews method."""

    def test_get_previews_returns_results(self):
        """Get previews returns results."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_doc = Mock()
        mock_doc.page_content = "Preview content"
        mock_doc.metadata = {"title": "Preview Doc"}

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"
        mock_retriever.invoke.return_value = [mock_doc]

        engine = RetrieverSearchEngine(retriever=mock_retriever)
        previews = engine._get_previews("test query")

        assert len(previews) == 1
        assert previews[0]["title"] == "Preview Doc"

    def test_get_previews_exception(self):
        """Get previews handles exceptions."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"
        mock_retriever.invoke.side_effect = Exception("Error")

        engine = RetrieverSearchEngine(retriever=mock_retriever)
        previews = engine._get_previews("test query")

        assert previews == []


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

    def test_get_full_content_preserves_items(self):
        """Get full content preserves items."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "TestRetriever"

        engine = RetrieverSearchEngine(retriever=mock_retriever)

        items = [
            {
                "title": "Doc 1",
                "full_content": "Full content 1",
                "snippet": "Short",
            },
            {"title": "Doc 2", "snippet": "Short snippet only"},
        ]

        results = engine._get_full_content(items)

        assert len(results) == 2
        assert results[0]["full_content"] == "Full content 1"
        # Second item should get full_content from snippet
        assert results[1]["full_content"] == "Short snippet only"


class TestAsyncRun:
    """Tests for arun method."""

    @pytest.mark.asyncio
    async def test_arun_with_async_retriever(self):
        """Async run uses async retriever method."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_doc = Mock()
        mock_doc.page_content = "Async content"
        mock_doc.metadata = {"title": "Async Doc"}

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "AsyncRetriever"
        mock_retriever.aget_relevant_documents = AsyncMock(
            return_value=[mock_doc]
        )

        engine = RetrieverSearchEngine(retriever=mock_retriever)
        results = await engine.arun("test query")

        assert len(results) == 1
        assert results[0]["title"] == "Async Doc"
        mock_retriever.aget_relevant_documents.assert_called_once_with(
            "test query"
        )

    @pytest.mark.asyncio
    async def test_arun_falls_back_to_sync(self):
        """Async run falls back to sync for non-async retrievers."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_doc = Mock()
        mock_doc.page_content = "Sync content"
        mock_doc.metadata = {"title": "Sync Doc"}

        mock_retriever = MagicMock()
        mock_retriever.__class__.__name__ = "SyncRetriever"
        mock_retriever.invoke.return_value = [mock_doc]
        # Delete the auto-created attribute so hasattr returns False
        del mock_retriever.aget_relevant_documents

        engine = RetrieverSearchEngine(retriever=mock_retriever)
        results = await engine.arun("test query")

        assert len(results) == 1
        assert results[0]["title"] == "Sync Doc"

    @pytest.mark.asyncio
    async def test_arun_exception(self):
        """Async run handles exceptions."""
        from local_deep_research.web_search_engines.engines.search_engine_retriever import (
            RetrieverSearchEngine,
        )

        mock_retriever = Mock()
        mock_retriever.__class__.__name__ = "ErrorRetriever"
        mock_retriever.aget_relevant_documents = AsyncMock(
            side_effect=Exception("Async error")
        )

        engine = RetrieverSearchEngine(retriever=mock_retriever)
        results = await engine.arun("test query")

        assert results == []
