"""
Delete API Routes

Provides endpoints for delete operations:
- Delete document
- Delete document blob only
- Delete documents in bulk
- Delete blobs in bulk
- Remove document from collection
- Delete collection
- Delete collection index only
"""

from flask import Blueprint, jsonify, request, session


from ....web.auth.decorators import login_required
from ...utils import handle_api_error
from ..services.document_deletion import DocumentDeletionService
from ..services.collection_deletion import CollectionDeletionService
from ..services.bulk_deletion import BulkDeletionService


delete_bp = Blueprint("delete", __name__, url_prefix="/library/api")
# NOTE: Routes use session["username"] (not .get()) intentionally.
# @login_required guarantees the key exists; direct access fails fast
# if the decorator is ever removed.


class _ValidationError(ValueError):
    """Raised when request validation fails."""

    def __init__(self, message: str):
        super().__init__(message)
        self.message = message


def _validate_document_ids() -> list:
    """Extract and validate document_ids from the JSON request body.

    Returns:
        list: The validated document IDs.

    Raises:
        _ValidationError: If the request body is missing or invalid.
    """
    data = request.get_json()
    if not data or "document_ids" not in data:
        raise _ValidationError("document_ids required in request body")

    document_ids = data["document_ids"]
    if not isinstance(document_ids, list) or not document_ids:
        raise _ValidationError("document_ids must be a non-empty list")

    return document_ids


# =============================================================================
# Document Delete Endpoints
# =============================================================================


@delete_bp.route("/document/<string:document_id>", methods=["DELETE"])
@login_required
def delete_document(document_id):
    """
    Delete a document and all related data.

    Tooltip: "Permanently delete this document, including PDF and text content.
              This cannot be undone."

    Returns:
        JSON with deletion details including chunks deleted, blob size freed
    """
    try:
        username = session["username"]
        service = DocumentDeletionService(username)
        result = service.delete_document(document_id)

        if result.get("deleted"):
            return jsonify({"success": True, **result})
        return jsonify({"success": False, **result}), 404

    except Exception as e:
        return handle_api_error("deleting document", e)


@delete_bp.route("/document/<string:document_id>/blob", methods=["DELETE"])
@login_required
def delete_document_blob(document_id):
    """
    Delete PDF binary but keep document metadata and text content.

    Tooltip: "Remove the PDF file to save space. Text content will be
              preserved for searching."

    Returns:
        JSON with bytes freed
    """
    try:
        username = session["username"]
        service = DocumentDeletionService(username)
        result = service.delete_blob_only(document_id)

        if result.get("deleted"):
            return jsonify({"success": True, **result})
        error_code = (
            404 if "not found" in result.get("error", "").lower() else 400
        )
        return jsonify({"success": False, **result}), error_code

    except Exception as e:
        return handle_api_error("deleting document blob", e)


@delete_bp.route("/document/<string:document_id>/preview", methods=["GET"])
@login_required
def get_document_deletion_preview(document_id):
    """
    Get a preview of what will be deleted.

    Returns information about the document to help user confirm deletion.
    """
    try:
        username = session["username"]
        service = DocumentDeletionService(username)
        result = service.get_deletion_preview(document_id)

        if result.get("found"):
            return jsonify({"success": True, **result})
        return jsonify({"success": False, "error": "Document not found"}), 404

    except Exception as e:
        return handle_api_error("getting document preview", e)


# =============================================================================
# Collection Document Endpoints
# =============================================================================


@delete_bp.route(
    "/collection/<string:collection_id>/document/<string:document_id>",
    methods=["DELETE"],
)
@login_required
def remove_document_from_collection(collection_id, document_id):
    """
    Remove document from a collection.

    If the document is not in any other collection, it will be deleted.

    Tooltip: "Remove from this collection. If not in any other collection,
              the document will be deleted."

    Returns:
        JSON with unlink status and whether document was deleted
    """
    try:
        username = session["username"]
        service = DocumentDeletionService(username)
        result = service.remove_from_collection(document_id, collection_id)

        if result.get("unlinked"):
            return jsonify({"success": True, **result})
        return jsonify({"success": False, **result}), 404

    except Exception as e:
        return handle_api_error("removing document from collection", e)


# =============================================================================
# Collection Delete Endpoints
# =============================================================================


@delete_bp.route("/collections/<string:collection_id>", methods=["DELETE"])
@login_required
def delete_collection(collection_id):
    """
    Delete a collection and clean up all related data.

    Deletes the collection, its RAG index, chunks, and any orphaned
    documents (documents not in any other collection).

    Returns:
        JSON with deletion details including orphaned documents deleted
    """
    try:
        username = session["username"]
        service = CollectionDeletionService(username)
        result = service.delete_collection(
            collection_id, delete_orphaned_documents=True
        )

        if result.get("deleted"):
            return jsonify({"success": True, **result})
        error = result.get("error", "Unknown error")
        status_code = 404 if "not found" in error.lower() else 400
        return jsonify({"success": False, **result}), status_code

    except Exception as e:
        return handle_api_error("deleting collection", e)


@delete_bp.route(
    "/collections/<string:collection_id>/index", methods=["DELETE"]
)
@login_required
def delete_collection_index(collection_id):
    """
    Delete only the RAG index for a collection, keeping the collection itself.

    Useful for rebuilding an index from scratch.

    Returns:
        JSON with deletion details
    """
    try:
        username = session["username"]
        service = CollectionDeletionService(username)
        result = service.delete_collection_index_only(collection_id)

        if result.get("deleted"):
            return jsonify({"success": True, **result})
        return jsonify({"success": False, **result}), 404

    except Exception as e:
        return handle_api_error("deleting collection index", e)


@delete_bp.route("/collections/<string:collection_id>/preview", methods=["GET"])
@login_required
def get_collection_deletion_preview(collection_id):
    """
    Get a preview of what will be deleted.

    Returns information about the collection to help user confirm deletion.
    """
    try:
        username = session["username"]
        service = CollectionDeletionService(username)
        result = service.get_deletion_preview(collection_id)

        if result.get("found"):
            return jsonify({"success": True, **result})
        return jsonify({"success": False, "error": "Collection not found"}), 404

    except Exception as e:
        return handle_api_error("getting collection preview", e)


# =============================================================================
# Bulk Delete Endpoints
# =============================================================================


@delete_bp.route("/documents/bulk", methods=["DELETE"])
@login_required
def delete_documents_bulk():
    """
    Delete multiple documents at once.

    Tooltip: "Permanently delete all selected documents and their associated data."

    Request body:
        {"document_ids": ["id1", "id2", ...]}

    Returns:
        JSON with bulk deletion results
    """
    try:
        document_ids = _validate_document_ids()
        username = session["username"]
        service = BulkDeletionService(username)
        result = service.delete_documents(document_ids)

        return jsonify({"success": True, **result})

    except _ValidationError as e:
        return jsonify({"success": False, "error": e.message}), 400
    except Exception as e:
        return handle_api_error("bulk deleting documents", e)


@delete_bp.route("/documents/blobs", methods=["DELETE"])
@login_required
def delete_documents_blobs_bulk():
    """
    Delete PDF binaries for multiple documents.

    Tooltip: "Remove PDF files from selected documents to free up database space.
              Text content is preserved."

    Request body:
        {"document_ids": ["id1", "id2", ...]}

    Returns:
        JSON with bulk blob deletion results
    """
    try:
        document_ids = _validate_document_ids()
        username = session["username"]
        service = BulkDeletionService(username)
        result = service.delete_blobs(document_ids)

        return jsonify({"success": True, **result})

    except _ValidationError as e:
        return jsonify({"success": False, "error": e.message}), 400
    except Exception as e:
        return handle_api_error("bulk deleting blobs", e)


@delete_bp.route(
    "/collection/<string:collection_id>/documents/bulk", methods=["DELETE"]
)
@login_required
def remove_documents_from_collection_bulk(collection_id):
    """
    Remove multiple documents from a collection.

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

    Request body:
        {"document_ids": ["id1", "id2", ...]}

    Returns:
        JSON with bulk removal results
    """
    try:
        document_ids = _validate_document_ids()
        username = session["username"]
        service = BulkDeletionService(username)
        result = service.remove_documents_from_collection(
            document_ids, collection_id
        )

        return jsonify({"success": True, **result})

    except _ValidationError as e:
        return jsonify({"success": False, "error": e.message}), 400
    except Exception as e:
        return handle_api_error("bulk removing documents from collection", e)


@delete_bp.route("/documents/preview", methods=["POST"])
@login_required
def get_bulk_deletion_preview():
    """
    Get a preview of what will be affected by a bulk operation.

    Request body:
        {
            "document_ids": ["id1", "id2", ...],
            "operation": "delete" or "delete_blobs"
        }

    Returns:
        JSON with preview information
    """
    try:
        document_ids = _validate_document_ids()
        data = request.get_json()
        operation = data.get("operation", "delete")

        username = session["username"]
        service = BulkDeletionService(username)
        result = service.get_bulk_preview(document_ids, operation)

        return jsonify({"success": True, **result})

    except _ValidationError as e:
        return jsonify({"success": False, "error": e.message}), 400
    except Exception as e:
        return handle_api_error("getting bulk preview", e)
