"""Tests for LibraryRAGService.get_current_index_info and close methods."""

from datetime import datetime
from unittest.mock import patch, MagicMock


def _make_service():
    """Create a LibraryRAGService with mocked dependencies."""
    with (
        patch(
            "local_deep_research.research_library.services.library_rag_service.LocalEmbeddingManager"
        ),
        patch(
            "local_deep_research.research_library.services.library_rag_service.get_user_db_session"
        ),
        patch(
            "local_deep_research.research_library.services.library_rag_service.FileIntegrityManager"
        ),
        patch(
            "local_deep_research.research_library.services.library_rag_service.get_text_splitter"
        ),
    ):
        from local_deep_research.research_library.services.library_rag_service import (
            LibraryRAGService,
        )

        service = LibraryRAGService(
            username="testuser",
            db_password="testpass",
        )
    return service


class TestGetCurrentIndexInfo:
    """Tests for get_current_index_info()."""

    @patch(
        "local_deep_research.research_library.services.library_rag_service.get_user_db_session"
    )
    def test_returns_none_when_no_index(self, mock_session_ctx):
        mock_session = MagicMock()
        mock_session_ctx.return_value.__enter__ = MagicMock(
            return_value=mock_session
        )
        mock_session_ctx.return_value.__exit__ = MagicMock(return_value=None)

        # Collection found, but no RAG index
        mock_collection = MagicMock()
        mock_collection.id = "coll-123"

        mock_session.query.return_value.filter_by.return_value.first.side_effect = [
            mock_collection,  # collection query
            None,  # rag_index query
        ]
        # For the "all indices" debug query
        mock_session.query.return_value.all.return_value = []

        service = _make_service()
        result = service.get_current_index_info(collection_id="coll-123")
        assert result is None

    @patch(
        "local_deep_research.research_library.services.library_rag_service.get_user_db_session"
    )
    def test_returns_index_info_with_collection_id(self, mock_session_ctx):
        mock_session = MagicMock()
        mock_session_ctx.return_value.__enter__ = MagicMock(
            return_value=mock_session
        )
        mock_session_ctx.return_value.__exit__ = MagicMock(return_value=None)

        # Collection found
        mock_collection = MagicMock()

        # RAG index found
        mock_rag_index = MagicMock()
        mock_rag_index.embedding_model = "all-MiniLM-L6-v2"
        mock_rag_index.embedding_model_type = MagicMock()
        mock_rag_index.embedding_model_type.value = "sentence_transformers"
        mock_rag_index.embedding_dimension = 384
        mock_rag_index.chunk_size = 1000
        mock_rag_index.chunk_overlap = 200
        mock_rag_index.created_at = datetime(2024, 1, 1)
        mock_rag_index.last_updated_at = datetime(2024, 6, 15)

        # Set up query chain for collection and rag_index
        mock_session.query.return_value.filter_by.return_value.first.side_effect = [
            mock_collection,  # collection query
            mock_rag_index,  # rag_index query
        ]

        # Chunk count and doc count
        mock_session.query.return_value.filter_by.return_value.scalar.return_value = 500
        mock_session.query.return_value.filter_by.return_value.count.return_value = 10

        service = _make_service()
        result = service.get_current_index_info(collection_id="coll-123")

        assert result is not None
        assert result["embedding_model"] == "all-MiniLM-L6-v2"
        assert result["embedding_dimension"] == 384
        assert result["chunk_size"] == 1000

    @patch(
        "local_deep_research.research_library.services.library_rag_service.get_user_db_session"
    )
    @patch("local_deep_research.database.library_init.get_default_library_id")
    def test_defaults_to_library_collection(
        self, mock_get_default, mock_session_ctx
    ):
        mock_get_default.return_value = "default-lib-id"

        mock_session = MagicMock()
        mock_session_ctx.return_value.__enter__ = MagicMock(
            return_value=mock_session
        )
        mock_session_ctx.return_value.__exit__ = MagicMock(return_value=None)

        # No RAG index
        mock_session.query.return_value.filter_by.return_value.first.return_value = None
        mock_session.query.return_value.all.return_value = []

        service = _make_service()
        result = service.get_current_index_info()  # No collection_id

        # Should have called get_default_library_id
        mock_get_default.assert_called_once()
        assert result is None


class TestClose:
    """Tests for close() method."""

    def test_close_clears_resources(self):
        service = _make_service()
        # Simulate having resources set
        service.faiss_index = MagicMock()
        service.rag_index_record = MagicMock()
        service.integrity_manager = MagicMock()

        service.close()

        assert service.embedding_manager is None
        assert service.faiss_index is None
        assert service.rag_index_record is None
        assert service.integrity_manager is None
        assert service._closed is True

    def test_close_is_idempotent(self):
        service = _make_service()
        service.close()
        service.close()  # Should not raise
        assert service._closed is True
