"""
Bulk deletion service.

Handles bulk operations:
- Delete multiple documents
- Delete blobs for multiple documents
- Remove multiple documents from a collection
"""

from typing import Dict, Any, List

from loguru import logger

from .document_deletion import DocumentDeletionService


class BulkDeletionService:
    """Service for bulk deletion operations."""

    def __init__(self, username: str):
        """
        Initialize bulk deletion service.

        Args:
            username: Username for database session
        """
        self.username = username
        self._document_service = DocumentDeletionService(username)

    def delete_documents(self, document_ids: List[str]) -> Dict[str, Any]:
        """
        Delete multiple documents.

        Args:
            document_ids: List of document IDs to delete

        Returns:
            Dict with bulk deletion results:
            {
                "total": int,
                "deleted": int,
                "failed": int,
                "total_chunks_deleted": int,
                "total_bytes_freed": int,
                "results": List[Dict],
                "errors": List[Dict]
            }
        """
        result: Dict[str, Any] = {
            "total": len(document_ids),
            "deleted": 0,
            "failed": 0,
            "total_chunks_deleted": 0,
            "total_bytes_freed": 0,
            "results": [],
            "errors": [],
        }

        for document_id in document_ids:
            delete_result = self._document_service.delete_document(document_id)

            if delete_result.get("deleted"):
                result["deleted"] += 1
                result["total_chunks_deleted"] += delete_result.get(
                    "chunks_deleted", 0
                )
                result["total_bytes_freed"] += delete_result.get("blob_size", 0)
                result["results"].append(
                    {
                        "document_id": document_id,
                        "title": delete_result.get("title", "Unknown"),
                        "chunks_deleted": delete_result.get(
                            "chunks_deleted", 0
                        ),
                        "blob_size": delete_result.get("blob_size", 0),
                    }
                )
            else:
                result["failed"] += 1
                result["errors"].append(
                    {
                        "document_id": document_id,
                        "error": delete_result.get("error", "Unknown error"),
                    }
                )

        logger.info(
            f"Bulk delete: {result['deleted']}/{result['total']} documents, "
            f"{result['total_chunks_deleted']} chunks, "
            f"{result['total_bytes_freed']} bytes"
        )

        return result

    def delete_blobs(self, document_ids: List[str]) -> Dict[str, Any]:
        """
        Delete PDF binaries for multiple documents, keeping text content.

        Args:
            document_ids: List of document IDs to delete blobs for

        Returns:
            Dict with bulk blob deletion results:
            {
                "total": int,
                "deleted": int,
                "skipped": int,
                "failed": int,
                "total_bytes_freed": int,
                "results": List[Dict],
                "errors": List[Dict]
            }
        """
        result: Dict[str, Any] = {
            "total": len(document_ids),
            "deleted": 0,
            "skipped": 0,
            "failed": 0,
            "total_bytes_freed": 0,
            "results": [],
            "errors": [],
        }

        for document_id in document_ids:
            delete_result = self._document_service.delete_blob_only(document_id)

            if delete_result.get("deleted"):
                result["deleted"] += 1
                result["total_bytes_freed"] += delete_result.get(
                    "bytes_freed", 0
                )
                result["results"].append(
                    {
                        "document_id": document_id,
                        "bytes_freed": delete_result.get("bytes_freed", 0),
                    }
                )
            elif "no stored PDF" in delete_result.get("error", "").lower():
                result["skipped"] += 1
            else:
                result["failed"] += 1
                result["errors"].append(
                    {
                        "document_id": document_id,
                        "error": delete_result.get("error", "Unknown error"),
                    }
                )

        logger.info(
            f"Bulk blob delete: {result['deleted']}/{result['total']} blobs, "
            f"{result['total_bytes_freed']} bytes freed"
        )

        return result

    def remove_documents_from_collection(
        self,
        document_ids: List[str],
        collection_id: str,
    ) -> Dict[str, Any]:
        """
        Remove multiple documents from a collection.

        Documents that are not in any other collection will be deleted.

        Args:
            document_ids: List of document IDs to remove
            collection_id: ID of the collection

        Returns:
            Dict with bulk removal results:
            {
                "total": int,
                "unlinked": int,
                "deleted": int,
                "failed": int,
                "total_chunks_deleted": int,
                "results": List[Dict],
                "errors": List[Dict]
            }
        """
        result: Dict[str, Any] = {
            "total": len(document_ids),
            "unlinked": 0,
            "deleted": 0,
            "failed": 0,
            "total_chunks_deleted": 0,
            "results": [],
            "errors": [],
        }

        for document_id in document_ids:
            remove_result = self._document_service.remove_from_collection(
                document_id, collection_id
            )

            if remove_result.get("unlinked"):
                result["unlinked"] += 1
                result["total_chunks_deleted"] += remove_result.get(
                    "chunks_deleted", 0
                )
                if remove_result.get("document_deleted"):
                    result["deleted"] += 1
                result["results"].append(
                    {
                        "document_id": document_id,
                        "document_deleted": remove_result.get(
                            "document_deleted", False
                        ),
                        "chunks_deleted": remove_result.get(
                            "chunks_deleted", 0
                        ),
                    }
                )
            else:
                result["failed"] += 1
                result["errors"].append(
                    {
                        "document_id": document_id,
                        "error": remove_result.get("error", "Unknown error"),
                    }
                )

        logger.info(
            f"Bulk remove from collection: {result['unlinked']}/{result['total']} "
            f"unlinked, {result['deleted']} deleted, "
            f"{result['total_chunks_deleted']} chunks"
        )

        return result

    def get_bulk_preview(
        self,
        document_ids: List[str],
        operation: str = "delete",
    ) -> Dict[str, Any]:
        """
        Get a preview of what will be affected by a bulk operation.

        Args:
            document_ids: List of document IDs
            operation: Type of operation ("delete", "delete_blobs")

        Returns:
            Dict with preview information
        """
        from ....database.models.library import Document, DocumentChunk
        from ....database.session_context import get_user_db_session
        from ..utils.cascade_helper import CascadeHelper

        result: Dict[str, Any] = {
            "total_documents": len(document_ids),
            "found_documents": 0,
            "total_blob_size": 0,
            "documents_with_blobs": 0,
            "total_chunks": 0,
            "documents": [],
        }

        with get_user_db_session(self.username) as session:
            for document_id in document_ids:
                document = session.query(Document).get(document_id)
                if not document:
                    continue

                result["found_documents"] += 1
                blob_size = CascadeHelper.get_document_blob_size(
                    session, document_id
                )

                if blob_size > 0:
                    result["documents_with_blobs"] += 1
                    result["total_blob_size"] += blob_size

                chunks = (
                    session.query(DocumentChunk)
                    .filter(
                        DocumentChunk.source_id == document_id,
                        DocumentChunk.source_type == "document",
                    )
                    .count()
                )
                result["total_chunks"] += chunks

                result["documents"].append(
                    {
                        "id": document_id,
                        "title": document.title
                        or document.filename
                        or "Untitled",
                        "has_blob": blob_size > 0,
                        "blob_size": blob_size,
                        "chunks_count": chunks,
                    }
                )

        return result
