"""
Tests for the LocalSearchEngine and LocalEmbeddingManager classes.

Tests cover:
- Helper functions (_get_file_loader, _load_document)
- LocalEmbeddingManager initialization and methods
- LocalSearchEngine initialization and methods
- Search functionality
- Folder indexing
"""

import json
from pathlib import Path
from unittest.mock import Mock, patch


class TestGetFileLoader:
    """Tests for _get_file_loader helper function."""

    def test_get_file_loader_pdf(self, tmp_path):
        """Get file loader for PDF files."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _get_file_loader,
        )

        pdf_file = tmp_path / "test.pdf"
        pdf_file.touch()

        mock_loader = Mock()
        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.get_loader_for_path",
            return_value=mock_loader,
        ) as mock_get_loader:
            result = _get_file_loader(str(pdf_file))
            mock_get_loader.assert_called_once_with(str(pdf_file))
            assert result is mock_loader

    def test_get_file_loader_txt(self, tmp_path):
        """Get file loader for text files."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _get_file_loader,
        )

        txt_file = tmp_path / "test.txt"
        txt_file.touch()

        mock_loader = Mock()
        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.get_loader_for_path",
            return_value=mock_loader,
        ) as mock_get_loader:
            result = _get_file_loader(str(txt_file))
            mock_get_loader.assert_called_once_with(str(txt_file))
            assert result is mock_loader

    def test_get_file_loader_markdown(self, tmp_path):
        """Get file loader for markdown files."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _get_file_loader,
        )

        md_file = tmp_path / "test.md"
        md_file.touch()

        mock_loader = Mock()
        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.get_loader_for_path",
            return_value=mock_loader,
        ) as mock_get_loader:
            result = _get_file_loader(str(md_file))
            mock_get_loader.assert_called_once_with(str(md_file))
            assert result is mock_loader

    def test_get_file_loader_docx(self, tmp_path):
        """Get file loader for Word documents."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _get_file_loader,
        )

        docx_file = tmp_path / "test.docx"
        docx_file.touch()

        mock_loader = Mock()
        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.get_loader_for_path",
            return_value=mock_loader,
        ) as mock_get_loader:
            result = _get_file_loader(str(docx_file))
            mock_get_loader.assert_called_once_with(str(docx_file))
            assert result is mock_loader

    def test_get_file_loader_csv(self, tmp_path):
        """Get file loader for CSV files."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _get_file_loader,
        )

        csv_file = tmp_path / "test.csv"
        csv_file.touch()

        mock_loader = Mock()
        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.get_loader_for_path",
            return_value=mock_loader,
        ) as mock_get_loader:
            result = _get_file_loader(str(csv_file))
            mock_get_loader.assert_called_once_with(str(csv_file))
            assert result is mock_loader

    def test_get_file_loader_xlsx(self, tmp_path):
        """Get file loader for Excel files."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _get_file_loader,
        )

        xlsx_file = tmp_path / "test.xlsx"
        xlsx_file.touch()

        mock_loader = Mock()
        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.get_loader_for_path",
            return_value=mock_loader,
        ) as mock_get_loader:
            result = _get_file_loader(str(xlsx_file))
            mock_get_loader.assert_called_once_with(str(xlsx_file))
            assert result is mock_loader

    def test_get_file_loader_unknown_extension(self, tmp_path):
        """Get file loader for unknown extension falls back to TextLoader."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _get_file_loader,
        )

        unknown_file = tmp_path / "test.xyz"
        unknown_file.touch()

        # When extension is not supported, get_loader_for_path returns None
        # and _get_file_loader falls back to TextLoader
        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.is_extension_supported",
            return_value=False,
        ):
            with patch(
                "local_deep_research.web_search_engines.engines.search_engine_local.TextLoader"
            ) as mock_text_loader:
                _get_file_loader(str(unknown_file))
                mock_text_loader.assert_called_once_with(
                    str(unknown_file),
                    encoding="utf-8",
                    autodetect_encoding=True,
                )

    def test_get_file_loader_exception(self, tmp_path):
        """Get file loader handles exceptions."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _get_file_loader,
        )

        pdf_file = tmp_path / "test.pdf"
        pdf_file.touch()

        # When get_loader_for_path raises an exception, it should return None
        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.is_extension_supported",
            return_value=True,
        ):
            with patch(
                "local_deep_research.web_search_engines.engines.search_engine_local.get_loader_for_path",
                return_value=None,
            ):
                with patch(
                    "local_deep_research.web_search_engines.engines.search_engine_local.TextLoader",
                    side_effect=Exception("Loader error"),
                ):
                    loader = _get_file_loader(str(pdf_file))
                    assert loader is None


class TestLoadDocument:
    """Tests for _load_document helper function."""

    def test_load_document_success(self, tmp_path):
        """Load document successfully."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _load_document,
        )
        from langchain_core.documents import Document

        txt_file = tmp_path / "test.txt"
        txt_file.write_text("Test content")

        mock_doc = Document(page_content="Test content", metadata={})
        mock_loader = Mock()
        mock_loader.load.return_value = [mock_doc]

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local._get_file_loader",
            return_value=mock_loader,
        ):
            docs = _load_document(txt_file)

            assert len(docs) == 1
            assert docs[0].page_content == "Test content"
            assert docs[0].metadata["source"] == str(txt_file)
            assert docs[0].metadata["filename"] == "test.txt"

    def test_load_document_no_loader(self, tmp_path):
        """Load document with no available loader."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _load_document,
        )

        file_path = tmp_path / "test.xyz"
        file_path.touch()

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local._get_file_loader",
            return_value=None,
        ):
            docs = _load_document(file_path)
            assert docs == []

    def test_load_document_exception(self, tmp_path):
        """Load document handles exceptions."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            _load_document,
        )

        txt_file = tmp_path / "test.txt"
        txt_file.touch()

        mock_loader = Mock()
        mock_loader.load.side_effect = Exception("Load error")

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local._get_file_loader",
            return_value=mock_loader,
        ):
            docs = _load_document(txt_file)
            assert docs == []


class TestLocalEmbeddingManagerInit:
    """Tests for LocalEmbeddingManager initialization."""

    def test_init_with_defaults(self, tmp_path):
        """Initialize with default values."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.get_cache_directory",
            return_value=tmp_path,
        ):
            manager = LocalEmbeddingManager()

            assert manager.embedding_model == "all-MiniLM-L6-v2"
            assert manager.embedding_device == "cpu"
            assert manager.embedding_model_type == "sentence_transformers"
            assert manager.chunk_size == 1000
            assert manager.chunk_overlap == 200
            assert manager._embeddings is None  # Lazy initialization

    def test_init_with_custom_cache_dir(self, tmp_path):
        """Initialize with custom cache directory."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        custom_cache = tmp_path / "custom_cache"
        manager = LocalEmbeddingManager(cache_dir=str(custom_cache))

        assert manager.cache_dir == custom_cache
        assert custom_cache.exists()

    def test_init_with_ollama(self, tmp_path):
        """Initialize with Ollama embeddings."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(
            embedding_model_type="ollama",
            embedding_model="llama2",
            ollama_base_url="http://localhost:11434",
            cache_dir=str(tmp_path),
        )

        assert manager.embedding_model_type == "ollama"
        assert manager.embedding_model == "llama2"
        assert manager.ollama_base_url == "http://localhost:11434"

    def test_init_with_settings_snapshot(self, tmp_path):
        """Initialize with settings snapshot."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        settings = {"_username": "testuser"}
        manager = LocalEmbeddingManager(
            settings_snapshot=settings, cache_dir=str(tmp_path)
        )

        assert manager.username == "testuser"
        assert manager.settings_snapshot == settings


class TestLocalEmbeddingManagerEmbeddings:
    """Tests for LocalEmbeddingManager embeddings property."""

    def test_embeddings_lazy_initialization(self, tmp_path):
        """Embeddings are lazily initialized."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        assert manager._embeddings is None

        # Mock the embeddings initialization
        mock_embeddings = Mock()
        with patch.object(
            manager, "_initialize_embeddings", return_value=mock_embeddings
        ):
            embeddings = manager.embeddings

            assert embeddings is mock_embeddings
            assert manager._embeddings is mock_embeddings

    def test_embeddings_reuse(self, tmp_path):
        """Embeddings are reused after initialization."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        mock_embeddings = Mock()
        manager._embeddings = mock_embeddings

        # Should return existing embeddings without reinitializing
        with patch.object(manager, "_initialize_embeddings") as mock_init:
            embeddings = manager.embeddings

            assert embeddings is mock_embeddings
            mock_init.assert_not_called()


class TestLocalEmbeddingManagerIndexedFolders:
    """Tests for LocalEmbeddingManager indexed folders management."""

    def test_load_indexed_folders_empty(self, tmp_path):
        """Load indexed folders when no metadata exists."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        assert manager.indexed_folders == {}

    def test_load_indexed_folders_from_disk(self, tmp_path):
        """Load indexed folders from disk."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        # Create metadata file
        metadata = {
            "abc123": {
                "path": "/test/folder",
                "last_indexed": 1234567890,
                "file_count": 10,
            }
        }
        metadata_file = tmp_path / "index_metadata.json"
        metadata_file.write_text(json.dumps(metadata))

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        assert "abc123" in manager.indexed_folders
        assert manager.indexed_folders["abc123"]["path"] == "/test/folder"

    def test_save_indexed_folders(self, tmp_path):
        """Save indexed folders to disk."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))
        manager.indexed_folders = {
            "xyz789": {
                "path": "/another/folder",
                "last_indexed": 9876543210,
            }
        }

        manager._save_indexed_folders()

        metadata_file = tmp_path / "index_metadata.json"
        assert metadata_file.exists()

        saved_data = json.loads(metadata_file.read_text())
        assert "xyz789" in saved_data


class TestLocalEmbeddingManagerFolderHash:
    """Tests for LocalEmbeddingManager folder hash methods."""

    def test_get_folder_hash(self, tmp_path):
        """Get folder hash is deterministic."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        folder_path = tmp_path / "test_folder"
        folder_path.mkdir()

        hash1 = LocalEmbeddingManager.get_folder_hash(folder_path)
        hash2 = LocalEmbeddingManager.get_folder_hash(folder_path)

        assert hash1 == hash2
        assert len(hash1) == 32  # MD5 hash length

    def test_get_folder_hash_different_folders(self, tmp_path):
        """Different folders have different hashes."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        folder1 = tmp_path / "folder1"
        folder2 = tmp_path / "folder2"
        folder1.mkdir()
        folder2.mkdir()

        hash1 = LocalEmbeddingManager.get_folder_hash(folder1)
        hash2 = LocalEmbeddingManager.get_folder_hash(folder2)

        assert hash1 != hash2

    def test_get_index_path(self, tmp_path):
        """Get index path for a folder."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        folder_path = Path("/test/folder")
        index_path = manager._get_index_path(folder_path)

        assert "index_" in str(index_path)
        assert index_path.parent == tmp_path


class TestLocalEmbeddingManagerGetAllFiles:
    """Tests for LocalEmbeddingManager _get_all_files method."""

    def test_get_all_files(self, tmp_path):
        """Get all files in a folder recursively."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        # Create test folder structure
        (tmp_path / "file1.txt").touch()
        (tmp_path / "file2.txt").touch()
        subdir = tmp_path / "subdir"
        subdir.mkdir()
        (subdir / "file3.txt").touch()

        files = list(LocalEmbeddingManager._get_all_files(tmp_path))

        assert len(files) == 3
        filenames = [f.name for f in files]
        assert "file1.txt" in filenames
        assert "file2.txt" in filenames
        assert "file3.txt" in filenames


class TestLocalEmbeddingManagerCheckConfigChanged:
    """Tests for LocalEmbeddingManager config change detection."""

    def test_check_config_changed_new_folder(self, tmp_path):
        """Config changed is True for new folder."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        folder = tmp_path / "new_folder"
        folder.mkdir()

        assert manager._check_config_changed(folder) is True

    def test_check_config_changed_same_config(self, tmp_path):
        """Config changed is False when config is the same."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        folder = tmp_path / "test_folder"
        folder.mkdir()

        folder_hash = manager.get_folder_hash(folder)
        manager.indexed_folders[folder_hash] = {
            "chunk_size": 1000,
            "chunk_overlap": 200,
            "embedding_model": "all-MiniLM-L6-v2",
        }

        assert manager._check_config_changed(folder) is False

    def test_check_config_changed_different_chunk_size(self, tmp_path):
        """Config changed is True when chunk size differs."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        folder = tmp_path / "test_folder"
        folder.mkdir()

        folder_hash = manager.get_folder_hash(folder)
        manager.indexed_folders[folder_hash] = {
            "chunk_size": 500,  # Different from default 1000
            "chunk_overlap": 200,
            "embedding_model": "all-MiniLM-L6-v2",
        }

        assert manager._check_config_changed(folder) is True


class TestLocalEmbeddingManagerClearCache:
    """Tests for LocalEmbeddingManager clear_cache method."""

    def test_clear_cache(self, tmp_path):
        """Clear cache removes vector stores from memory."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))
        manager.vector_stores = {"hash1": Mock(), "hash2": Mock()}

        manager.clear_cache()

        assert manager.vector_stores == {}


class TestLocalEmbeddingManagerGetIndexedFoldersInfo:
    """Tests for LocalEmbeddingManager get_indexed_folders_info method."""

    def test_get_indexed_folders_info_empty(self, tmp_path):
        """Get indexed folders info when no folders indexed."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        info = manager.get_indexed_folders_info()

        assert info == []

    def test_get_indexed_folders_info_with_folders(self, tmp_path):
        """Get indexed folders info with indexed folders."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalEmbeddingManager,
        )

        manager = LocalEmbeddingManager(cache_dir=str(tmp_path))

        test_folder = tmp_path / "test_folder"
        test_folder.mkdir()

        folder_hash = manager.get_folder_hash(test_folder)
        manager.indexed_folders[folder_hash] = {
            "path": str(test_folder),
            "last_indexed": 1234567890,
            "file_count": 5,
            "chunk_count": 20,
        }

        info = manager.get_indexed_folders_info()

        assert len(info) == 1
        assert info[0]["path"] == str(test_folder)
        assert info[0]["file_count"] == 5
        assert "last_indexed_formatted" in info[0]


class TestLocalSearchEngineInit:
    """Tests for LocalSearchEngine initialization."""

    def test_init_with_valid_paths(self, tmp_path):
        """Initialize with valid folder paths."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        # Mock embedding manager to avoid actual initialization
        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True

            engine = LocalSearchEngine(
                paths=[str(folder)],
                name="Test Collection",
                description="Test description",
            )

            assert str(folder) in engine.valid_folder_paths
            assert engine.name == "Test Collection"
            assert engine.description == "Test description"

    def test_init_with_invalid_paths(self, tmp_path):
        """Initialize with invalid folder paths."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        invalid_path = str(tmp_path / "nonexistent")

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ):
            engine = LocalSearchEngine(paths=[invalid_path])

            assert invalid_path not in engine.valid_folder_paths
            assert engine.valid_folder_paths == []

    def test_init_with_custom_max_results(self, tmp_path):
        """Initialize with custom max_results."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True

            engine = LocalSearchEngine(paths=[str(folder)], max_results=50)

            assert engine.max_results == 50

    def test_init_with_collections(self, tmp_path):
        """Initialize with named collections."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder1 = tmp_path / "research"
        folder2 = tmp_path / "notes"
        folder1.mkdir()
        folder2.mkdir()

        collections = {
            "research": {
                "paths": [str(folder1)],
                "description": "Research papers",
            },
            "notes": {"paths": [str(folder2)], "description": "Personal notes"},
        }

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True

            engine = LocalSearchEngine(
                paths=[str(folder1), str(folder2)], collections=collections
            )

            assert "research" in engine.collections
            assert "notes" in engine.collections


class TestLocalSearchEngineGetPreviews:
    """Tests for LocalSearchEngine _get_previews method."""

    def test_get_previews_returns_results(self, tmp_path):
        """Get previews returns formatted results."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        mock_results = [
            {
                "content": "Test content for document one",
                "metadata": {
                    "source": str(folder / "doc1.txt"),
                    "filename": "doc1.txt",
                },
                "similarity": 0.95,
                "folder": folder,
            }
        ]

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True
            mock_manager.return_value.search.return_value = mock_results

            engine = LocalSearchEngine(paths=[str(folder)])
            previews = engine._get_previews("test query")

            assert len(previews) == 1
            assert previews[0]["title"] == "doc1.txt"
            assert previews[0]["similarity"] == 0.95

    def test_get_previews_empty_results(self, tmp_path):
        """Get previews handles empty results."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True
            mock_manager.return_value.search.return_value = []

            engine = LocalSearchEngine(paths=[str(folder)])
            previews = engine._get_previews("test query")

            assert previews == []

    def test_get_previews_no_valid_folders(self, tmp_path):
        """Get previews returns empty for no valid folders."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ):
            engine = LocalSearchEngine(paths=["/nonexistent/path"])
            previews = engine._get_previews("test query")

            assert previews == []


class TestLocalSearchEngineGetFullContent:
    """Tests for LocalSearchEngine _get_full_content method."""

    def test_get_full_content_preserves_content(self, tmp_path):
        """Get full content preserves full content from items."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        items = [
            {
                "id": "local-1",
                "title": "Doc 1",
                "_full_content": "This is the full content of document 1",
                "_metadata": {"source": "/path/to/doc1.txt"},
            }
        ]

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True

            with patch(
                "local_deep_research.web_search_engines.engines.search_engine_local.search_config"
            ) as mock_config:
                mock_config.SEARCH_SNIPPETS_ONLY = False

                engine = LocalSearchEngine(paths=[str(folder)])
                results = engine._get_full_content(items)

                assert len(results) == 1
                assert (
                    results[0]["full_content"]
                    == "This is the full content of document 1"
                )
                assert "_full_content" not in results[0]

    def test_get_full_content_snippets_only(self, tmp_path):
        """Get full content respects snippets-only mode."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        items = [
            {
                "id": "local-1",
                "title": "Doc 1",
                "_full_content": "Full content",
            }
        ]

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True

            with patch(
                "local_deep_research.web_search_engines.engines.search_engine_local.search_config"
            ) as mock_config:
                mock_config.SEARCH_SNIPPETS_ONLY = True

                engine = LocalSearchEngine(paths=[str(folder)])
                results = engine._get_full_content(items)

                # In snippets-only mode, items are returned as-is
                assert results == items


class TestLocalSearchEngineRun:
    """Tests for LocalSearchEngine run method."""

    def test_run_returns_results(self, tmp_path):
        """Run returns search results."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        mock_results = [
            {
                "content": "Test content",
                "metadata": {
                    "source": str(folder / "doc.txt"),
                    "filename": "doc.txt",
                },
                "similarity": 0.9,
                "folder": folder,
            }
        ]

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True
            mock_manager.return_value.search.return_value = mock_results
            mock_manager.return_value.clear_cache = Mock()

            with patch(
                "local_deep_research.web_search_engines.engines.search_engine_local.search_config"
            ) as mock_config:
                mock_config.SEARCH_SNIPPETS_ONLY = False

                engine = LocalSearchEngine(paths=[str(folder)])

                # Mock _filter_for_relevance to return all items
                with patch.object(
                    engine, "_filter_for_relevance", side_effect=lambda x, q: x
                ):
                    results = engine.run("test query")

                    assert len(results) >= 1

    def test_run_with_collection_filter(self, tmp_path):
        """Run with collection filter in query."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        collections = {
            "research": {
                "paths": [str(folder)],
                "description": "Research papers",
            },
        }

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True
            mock_manager.return_value.search.return_value = []
            mock_manager.return_value.clear_cache = Mock()

            engine = LocalSearchEngine(
                paths=[str(folder)], collections=collections
            )
            results = engine.run("collection:research test query")

            # Should parse collection from query
            assert results == []

    def test_run_empty_previews(self, tmp_path):
        """Run returns empty when no previews found."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True
            mock_manager.return_value.search.return_value = []
            mock_manager.return_value.clear_cache = Mock()

            engine = LocalSearchEngine(paths=[str(folder)])
            results = engine.run("test query")

            assert results == []


class TestLocalSearchEngineGetCollectionsInfo:
    """Tests for LocalSearchEngine get_collections_info method."""

    def test_get_collections_info(self, tmp_path):
        """Get collections info returns collection details."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        collections = {
            "docs": {"paths": [str(folder)], "description": "Documents"},
        }

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True
            mock_manager.return_value.indexed_folders = {}
            mock_manager.return_value.get_folder_hash.return_value = "abc123"

            engine = LocalSearchEngine(
                paths=[str(folder)], collections=collections
            )
            info = engine.get_collections_info()

            assert len(info) == 1
            assert info[0]["name"] == "docs"
            assert info[0]["description"] == "Documents"


class TestLocalSearchEngineReindexCollection:
    """Tests for LocalSearchEngine reindex_collection method."""

    def test_reindex_collection_success(self, tmp_path):
        """Reindex collection successfully."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        collections = {
            "docs": {"paths": [str(folder)], "description": "Documents"},
        }

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True

            engine = LocalSearchEngine(
                paths=[str(folder)], collections=collections
            )
            result = engine.reindex_collection("docs")

            assert result is True

    def test_reindex_collection_not_found(self, tmp_path):
        """Reindex collection that doesn't exist."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True

            engine = LocalSearchEngine(paths=[str(folder)])
            result = engine.reindex_collection("nonexistent")

            assert result is False


class TestLocalSearchEngineFromConfig:
    """Tests for LocalSearchEngine from_config class method."""

    def test_from_config_with_collections(self, tmp_path):
        """Create from config with collections."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        config = {
            "collections": {
                "docs": {"paths": [str(folder)], "description": "Documents"},
            },
            "max_results": 20,
            "embedding_model": "custom-model",
            "chunk_size": 500,
        }

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True

            engine = LocalSearchEngine.from_config(config)

            assert engine.max_results == 20
            assert "docs" in engine.collections

    def test_from_config_with_folder_paths(self, tmp_path):
        """Create from config with folder_paths fallback."""
        from local_deep_research.web_search_engines.engines.search_engine_local import (
            LocalSearchEngine,
        )

        folder = tmp_path / "documents"
        folder.mkdir()

        config = {
            "folder_paths": [str(folder)],
            "max_results": 15,
        }

        with patch(
            "local_deep_research.web_search_engines.engines.search_engine_local.LocalEmbeddingManager"
        ) as mock_manager:
            mock_manager.return_value.index_folder.return_value = True

            engine = LocalSearchEngine.from_config(config)

            assert engine.max_results == 15
            assert "default" in engine.collections
