"""
Document Service for storage-backed file operations.

Provides a unified interface for document upload, download, and serving
using the storage abstraction layer.
"""

from dataclasses import dataclass
from typing import TYPE_CHECKING, Any
from uuid import uuid4

if TYPE_CHECKING:
    from shared.storage.base import StorageBackend


@dataclass
class DocumentResult:
    """Result of document operation."""

    id: str
    file_path: str
    filename: str | None = None


class DocumentService:
    """Service for document file operations using storage backend.

    Provides upload, download, and URL generation for documents and images.
    """

    # Storage path prefixes
    DOCUMENTS_PREFIX = "documents"
    IMAGES_PREFIX = "images"

    def __init__(
        self,
        storage_backend: "StorageBackend",
        admin_db: Any | None = None,
    ) -> None:
        """Initialize document service.

        Args:
            storage_backend: Storage backend for file operations.
            admin_db: Optional AdminDB instance for database operations.
        """
        self._storage = storage_backend
        self._admin_db = admin_db

    def upload_document(
        self,
        content: bytes,
        filename: str,
        dataset_id: str | None = None,
        document_id: str | None = None,
    ) -> DocumentResult:
        """Upload a document to storage.

        Args:
            content: Document content as bytes.
            filename: Original filename.
            dataset_id: Optional dataset ID for organization.
            document_id: Optional document ID (generated if not provided).

        Returns:
            DocumentResult with ID and storage path.
        """
        if document_id is None:
            document_id = str(uuid4())

        # Extract extension from filename
        ext = ""
        if "." in filename:
            ext = "." + filename.rsplit(".", 1)[-1].lower()

        # Build logical path
        remote_path = f"{self.DOCUMENTS_PREFIX}/{document_id}{ext}"

        # Upload via storage backend
        self._storage.upload_bytes(content, remote_path, overwrite=True)

        return DocumentResult(
            id=document_id,
            file_path=remote_path,
            filename=filename,
        )

    def download_document(self, remote_path: str) -> bytes:
        """Download a document from storage.

        Args:
            remote_path: Logical path to the document.

        Returns:
            Document content as bytes.
        """
        return self._storage.download_bytes(remote_path)

    def get_document_url(
        self,
        remote_path: str,
        expires_in_seconds: int = 3600,
    ) -> str:
        """Get a URL for accessing a document.

        Args:
            remote_path: Logical path to the document.
            expires_in_seconds: URL validity duration.

        Returns:
            Pre-signed URL for document access.
        """
        return self._storage.get_presigned_url(remote_path, expires_in_seconds)

    def document_exists(self, remote_path: str) -> bool:
        """Check if a document exists in storage.

        Args:
            remote_path: Logical path to the document.

        Returns:
            True if document exists.
        """
        return self._storage.exists(remote_path)

    def delete_document_files(self, remote_path: str) -> bool:
        """Delete a document from storage.

        Args:
            remote_path: Logical path to the document.

        Returns:
            True if document was deleted.
        """
        return self._storage.delete(remote_path)

    def save_page_image(
        self,
        document_id: str,
        page_num: int,
        content: bytes,
    ) -> str:
        """Save a page image to storage.

        Args:
            document_id: Document ID.
            page_num: Page number (1-indexed).
            content: Image content as bytes.

        Returns:
            Logical path where image was stored.
        """
        remote_path = f"{self.IMAGES_PREFIX}/{document_id}/page_{page_num}.png"
        self._storage.upload_bytes(content, remote_path, overwrite=True)
        return remote_path

    def get_page_image_url(
        self,
        document_id: str,
        page_num: int,
        expires_in_seconds: int = 3600,
    ) -> str:
        """Get a URL for accessing a page image.

        Args:
            document_id: Document ID.
            page_num: Page number (1-indexed).
            expires_in_seconds: URL validity duration.

        Returns:
            Pre-signed URL for image access.
        """
        remote_path = f"{self.IMAGES_PREFIX}/{document_id}/page_{page_num}.png"
        return self._storage.get_presigned_url(remote_path, expires_in_seconds)

    def get_page_image(self, document_id: str, page_num: int) -> bytes:
        """Download a page image from storage.

        Args:
            document_id: Document ID.
            page_num: Page number (1-indexed).

        Returns:
            Image content as bytes.
        """
        remote_path = f"{self.IMAGES_PREFIX}/{document_id}/page_{page_num}.png"
        return self._storage.download_bytes(remote_path)

    def delete_document_images(self, document_id: str) -> int:
        """Delete all images for a document.

        Args:
            document_id: Document ID.

        Returns:
            Number of images deleted.
        """
        prefix = f"{self.IMAGES_PREFIX}/{document_id}/"
        image_paths = self._storage.list_files(prefix)

        deleted_count = 0
        for path in image_paths:
            if self._storage.delete(path):
                deleted_count += 1

        return deleted_count

    def list_document_images(self, document_id: str) -> list[str]:
        """List all images for a document.

        Args:
            document_id: Document ID.

        Returns:
            List of image paths.
        """
        prefix = f"{self.IMAGES_PREFIX}/{document_id}/"
        return self._storage.list_files(prefix)
