"""Tests for BulkDeletionService."""

from unittest.mock import MagicMock, Mock, patch


from local_deep_research.research_library.deletion.services.bulk_deletion import (
    BulkDeletionService,
)


class TestBulkDeletionServiceInit:
    """Tests for BulkDeletionService initialization."""

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

    def test_creates_document_service(self):
        """Should create internal DocumentDeletionService."""
        service = BulkDeletionService(username="testuser")
        assert service._document_service is not None
        assert service._document_service.username == "testuser"


class TestBulkDeletionServiceDeleteDocuments:
    """Tests for delete_documents method."""

    def test_deletes_multiple_documents(self):
        """Should delete multiple documents and aggregate results."""
        service = BulkDeletionService(username="testuser")

        # Mock the internal document service
        service._document_service = MagicMock()
        service._document_service.delete_document.side_effect = [
            {
                "deleted": True,
                "title": "Doc 1",
                "chunks_deleted": 5,
                "blob_size": 1024,
            },
            {
                "deleted": True,
                "title": "Doc 2",
                "chunks_deleted": 3,
                "blob_size": 2048,
            },
        ]

        result = service.delete_documents(["doc-1", "doc-2"])

        assert result["total"] == 2
        assert result["deleted"] == 2
        assert result["failed"] == 0
        assert result["total_chunks_deleted"] == 8
        assert result["total_bytes_freed"] == 3072
        assert len(result["results"]) == 2

    def test_handles_partial_failures(self):
        """Should handle mix of success and failure."""
        service = BulkDeletionService(username="testuser")

        service._document_service = MagicMock()
        service._document_service.delete_document.side_effect = [
            {
                "deleted": True,
                "title": "Doc 1",
                "chunks_deleted": 5,
                "blob_size": 1024,
            },
            {"deleted": False, "error": "Not found"},
            {
                "deleted": True,
                "title": "Doc 3",
                "chunks_deleted": 2,
                "blob_size": 512,
            },
        ]

        result = service.delete_documents(["doc-1", "doc-2", "doc-3"])

        assert result["total"] == 3
        assert result["deleted"] == 2
        assert result["failed"] == 1
        assert len(result["errors"]) == 1

    def test_returns_empty_result_for_empty_list(self):
        """Should handle empty document list."""
        service = BulkDeletionService(username="testuser")
        service._document_service = MagicMock()

        result = service.delete_documents([])

        assert result["total"] == 0
        assert result["deleted"] == 0


class TestBulkDeletionServiceDeleteBlobs:
    """Tests for delete_blobs method."""

    def test_deletes_multiple_blobs(self):
        """Should delete blobs for multiple documents."""
        service = BulkDeletionService(username="testuser")

        service._document_service = MagicMock()
        service._document_service.delete_blob_only.side_effect = [
            {"deleted": True, "bytes_freed": 1024},
            {"deleted": True, "bytes_freed": 2048},
        ]

        result = service.delete_blobs(["doc-1", "doc-2"])

        assert result["total"] == 2
        assert result["deleted"] == 2
        assert result["total_bytes_freed"] == 3072

    def test_handles_documents_without_blobs(self):
        """Should handle documents that have no stored PDF."""
        service = BulkDeletionService(username="testuser")

        service._document_service = MagicMock()
        service._document_service.delete_blob_only.side_effect = [
            {"deleted": True, "bytes_freed": 1024},
            {
                "deleted": False,
                "error": "Document has no stored PDF (storage_mode is 'none')",
            },
        ]

        result = service.delete_blobs(["doc-1", "doc-2"])

        assert result["deleted"] == 1
        # May be skipped or failed depending on error message matching
        assert result["skipped"] + result["failed"] == 1


class TestBulkDeletionServiceRemoveDocumentsFromCollection:
    """Tests for remove_documents_from_collection method."""

    def test_removes_multiple_documents(self):
        """Should remove multiple documents from collection."""
        service = BulkDeletionService(username="testuser")

        service._document_service = MagicMock()
        service._document_service.remove_from_collection.side_effect = [
            {"unlinked": True, "document_deleted": False, "chunks_deleted": 3},
            {"unlinked": True, "document_deleted": True, "chunks_deleted": 5},
        ]

        result = service.remove_documents_from_collection(
            ["doc-1", "doc-2"], "col-1"
        )

        assert result["total"] == 2
        assert result["unlinked"] == 2
        assert result["deleted"] == 1  # One was orphaned and deleted
        assert result["total_chunks_deleted"] == 8

    def test_handles_removal_failures(self):
        """Should handle removal failures."""
        service = BulkDeletionService(username="testuser")

        service._document_service = MagicMock()
        service._document_service.remove_from_collection.side_effect = [
            {"unlinked": True, "document_deleted": False, "chunks_deleted": 3},
            {"unlinked": False, "error": "Document not in collection"},
        ]

        result = service.remove_documents_from_collection(
            ["doc-1", "doc-2"], "col-1"
        )

        assert result["unlinked"] == 1
        assert result["failed"] == 1
        assert len(result["errors"]) == 1


class TestBulkDeletionServiceGetBulkPreview:
    """Tests for get_bulk_preview method."""

    def test_get_bulk_preview_returns_result(self):
        """Should return preview result structure."""
        service = BulkDeletionService(username="testuser")

        # Mock the database session at the correct import location
        with patch(
            "local_deep_research.database.session_context.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 documents
            mock_doc = MagicMock()
            mock_doc.title = "Doc 1"
            mock_doc.filename = "doc1.pdf"
            mock_session.query.return_value.get.return_value = mock_doc
            mock_session.query.return_value.filter.return_value.count.return_value = 5

            result = service.get_bulk_preview(["doc-1"], "delete")

        # Should return a dict with expected structure
        assert "total_documents" in result

    def test_get_bulk_preview_empty_list(self):
        """Should handle empty document list."""
        service = BulkDeletionService(username="testuser")

        with patch(
            "local_deep_research.database.session_context.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

            result = service.get_bulk_preview([], "delete")

        assert result["total_documents"] == 0
