"""Tests for CollectionDeletionService."""

from unittest.mock import MagicMock, Mock, patch


from local_deep_research.research_library.deletion.services.collection_deletion import (
    CollectionDeletionService,
)


class TestCollectionDeletionServiceInit:
    """Tests for CollectionDeletionService initialization."""

    def test_initializes_with_username(self):
        """Should initialize with username."""
        service = CollectionDeletionService(username="testuser")
        assert service.username == "testuser"


class TestCollectionDeletionServiceDeleteCollection:
    """Tests for delete_collection method."""

    def test_returns_error_when_collection_not_found(self):
        """Should return error when collection doesn't exist."""
        service = CollectionDeletionService(username="testuser")

        with patch(
            "local_deep_research.research_library.deletion.services.collection_deletion.get_user_db_session"
        ) as mock_get_session:
            mock_session = MagicMock()
            mock_cm = MagicMock()
            mock_cm.__enter__ = Mock(return_value=mock_session)
            mock_cm.__exit__ = Mock(return_value=None)
            mock_get_session.return_value = mock_cm

            mock_session.query.return_value.get.return_value = None

            result = service.delete_collection("nonexistent-id")

        assert result["deleted"] is False
        assert "not found" in result["error"].lower()

    def test_deletes_collection_successfully(self):
        """Should delete collection and return stats."""
        service = CollectionDeletionService(username="testuser")

        with patch(
            "local_deep_research.research_library.deletion.services.collection_deletion.get_user_db_session"
        ) as mock_get_session:
            mock_session = MagicMock()
            mock_cm = MagicMock()
            mock_cm.__enter__ = Mock(return_value=mock_session)
            mock_cm.__exit__ = Mock(return_value=None)
            mock_get_session.return_value = mock_cm

            # Mock collection
            mock_collection = MagicMock()
            mock_collection.id = "col-123"
            mock_collection.name = "Test Collection"
            mock_session.query.return_value.get.return_value = mock_collection

            # Mock document collection links
            mock_doc_collection = MagicMock()
            mock_doc_collection.document_id = "doc-1"
            mock_session.query.return_value.filter_by.return_value.all.return_value = [
                mock_doc_collection
            ]
            mock_session.query.return_value.filter_by.return_value.count.return_value = 2
            mock_session.query.return_value.filter_by.return_value.delete.return_value = 1

            with patch(
                "local_deep_research.research_library.deletion.services.collection_deletion.CascadeHelper"
            ) as mock_helper:
                mock_helper.delete_collection_chunks.return_value = 10
                mock_helper.delete_rag_indices_for_collection.return_value = {
                    "deleted_indices": 1
                }

                result = service.delete_collection("col-123")

        assert result["deleted"] is True
        assert result["collection_id"] == "col-123"
        assert result["chunks_deleted"] == 10

    def test_deletes_orphaned_documents_by_default(self):
        """Should delete orphaned documents when enabled."""
        service = CollectionDeletionService(username="testuser")

        with patch(
            "local_deep_research.research_library.deletion.services.collection_deletion.get_user_db_session"
        ) as mock_get_session:
            mock_session = MagicMock()
            mock_cm = MagicMock()
            mock_cm.__enter__ = Mock(return_value=mock_session)
            mock_cm.__exit__ = Mock(return_value=None)
            mock_get_session.return_value = mock_cm

            mock_collection = MagicMock()
            mock_collection.id = "col-123"
            mock_collection.name = "Test Collection"
            mock_session.query.return_value.get.return_value = mock_collection

            mock_doc_collection = MagicMock()
            mock_doc_collection.document_id = "doc-1"
            mock_session.query.return_value.filter_by.return_value.all.return_value = [
                mock_doc_collection
            ]
            mock_session.query.return_value.filter_by.return_value.count.side_effect = [
                2,  # Folders count
                0,  # Remaining collections for doc (orphaned)
            ]
            mock_session.query.return_value.filter_by.return_value.delete.return_value = 1

            with patch(
                "local_deep_research.research_library.deletion.services.collection_deletion.CascadeHelper"
            ) as mock_helper:
                mock_helper.delete_collection_chunks.return_value = 5
                mock_helper.delete_rag_indices_for_collection.return_value = {
                    "deleted_indices": 1
                }
                mock_helper.delete_document_completely.return_value = True

                result = service.delete_collection(
                    "col-123", delete_orphaned_documents=True
                )

        assert result["deleted"] is True

    def test_handles_exception_gracefully(self):
        """Should handle exceptions and rollback."""
        service = CollectionDeletionService(username="testuser")

        with patch(
            "local_deep_research.research_library.deletion.services.collection_deletion.get_user_db_session"
        ) as mock_get_session:
            mock_session = MagicMock()
            mock_cm = MagicMock()
            mock_cm.__enter__ = Mock(return_value=mock_session)
            mock_cm.__exit__ = Mock(return_value=None)
            mock_get_session.return_value = mock_cm

            mock_session.query.side_effect = Exception("DB Error")

            result = service.delete_collection("col-123")

        assert result["deleted"] is False
        assert "error" in result


class TestCollectionDeletionServiceDeleteIndexOnly:
    """Tests for delete_collection_index_only method."""

    def test_returns_error_when_collection_not_found(self):
        """Should return error when collection doesn't exist."""
        service = CollectionDeletionService(username="testuser")

        with patch(
            "local_deep_research.research_library.deletion.services.collection_deletion.get_user_db_session"
        ) as mock_get_session:
            mock_session = MagicMock()
            mock_cm = MagicMock()
            mock_cm.__enter__ = Mock(return_value=mock_session)
            mock_cm.__exit__ = Mock(return_value=None)
            mock_get_session.return_value = mock_cm

            mock_session.query.return_value.get.return_value = None

            result = service.delete_collection_index_only("nonexistent-id")

        assert result["deleted"] is False
        assert "not found" in result["error"].lower()

    def test_deletes_index_and_resets_collection(self):
        """Should delete index and reset collection settings."""
        service = CollectionDeletionService(username="testuser")

        with patch(
            "local_deep_research.research_library.deletion.services.collection_deletion.get_user_db_session"
        ) as mock_get_session:
            mock_session = MagicMock()
            mock_cm = MagicMock()
            mock_cm.__enter__ = Mock(return_value=mock_session)
            mock_cm.__exit__ = Mock(return_value=None)
            mock_get_session.return_value = mock_cm

            mock_collection = MagicMock()
            mock_collection.id = "col-123"
            mock_collection.embedding_model = "text-embedding-ada-002"
            mock_session.query.return_value.get.return_value = mock_collection
            mock_session.query.return_value.filter_by.return_value.update.return_value = 5
            mock_session.query.return_value.filter_by.return_value.delete.return_value = 1

            with patch(
                "local_deep_research.research_library.deletion.services.collection_deletion.CascadeHelper"
            ) as mock_helper:
                mock_helper.delete_collection_chunks.return_value = 20
                mock_helper.delete_rag_indices_for_collection.return_value = {
                    "deleted_indices": 1
                }

                result = service.delete_collection_index_only("col-123")

        assert result["deleted"] is True
        assert result["chunks_deleted"] == 20
        assert result["indices_deleted"] == 1
        assert mock_collection.embedding_model is None


class TestCollectionDeletionServiceGetDeletionPreview:
    """Tests for get_deletion_preview method."""

    def test_returns_not_found_for_missing_collection(self):
        """Should return found=False for missing collection."""
        service = CollectionDeletionService(username="testuser")

        with patch(
            "local_deep_research.research_library.deletion.services.collection_deletion.get_user_db_session"
        ) as mock_get_session:
            mock_session = MagicMock()
            mock_cm = MagicMock()
            mock_cm.__enter__ = Mock(return_value=mock_session)
            mock_cm.__exit__ = Mock(return_value=None)
            mock_get_session.return_value = mock_cm

            mock_session.query.return_value.get.return_value = None

            result = service.get_deletion_preview("nonexistent-id")

        assert result["found"] is False

    def test_returns_collection_details(self):
        """Should return collection details for preview."""
        service = CollectionDeletionService(username="testuser")

        with patch(
            "local_deep_research.research_library.deletion.services.collection_deletion.get_user_db_session"
        ) as mock_get_session:
            mock_session = MagicMock()
            mock_cm = MagicMock()
            mock_cm.__enter__ = Mock(return_value=mock_session)
            mock_cm.__exit__ = Mock(return_value=None)
            mock_get_session.return_value = mock_cm

            mock_collection = MagicMock()
            mock_collection.id = "col-123"
            mock_collection.name = "Test Collection"
            mock_collection.description = "A test collection"
            mock_collection.is_default = False
            mock_collection.embedding_model = "text-embedding-ada-002"
            mock_session.query.return_value.get.return_value = mock_collection
            mock_session.query.return_value.filter_by.return_value.count.return_value = 10
            mock_session.query.return_value.filter_by.return_value.first.return_value = MagicMock()

            result = service.get_deletion_preview("col-123")

        assert result["found"] is True
        assert result["name"] == "Test Collection"
        assert result["documents_count"] == 10
        assert result["has_rag_index"] is True
