"""Abstract base class for backup storage backends."""

from __future__ import annotations

from abc import ABC, abstractmethod
from pathlib import Path


class StorageBackend(ABC):
    """Abstract base class for backup storage backends.

    Storage backends handle the persistence of backup files to various
    storage systems (local filesystem, S3, etc.).

    Example:
        >>> storage = LocalStorageBackend(Path("/backups"))
        >>> storage.upload(Path("/tmp/backup.tar.gz"), "mycontainer/backup-1.tar.gz")
        '/backups/mycontainer/backup-1.tar.gz'
    """

    @property
    @abstractmethod
    def name(self) -> str:
        """Return the backend name."""
        ...

    @abstractmethod
    def is_configured(self) -> bool:
        """Check if the backend is properly configured.

        Returns:
            True if the backend is ready to use
        """
        ...

    @abstractmethod
    def upload(
        self,
        local_path: Path,
        remote_path: str,
        metadata: dict[str, str] | None = None,
    ) -> str:
        """Upload a file to storage.

        Args:
            local_path: Path to local file to upload
            remote_path: Destination path in storage
            metadata: Optional metadata to store with the file

        Returns:
            Full storage path/URI of the uploaded file

        Raises:
            StorageError: If upload fails
        """
        ...

    @abstractmethod
    def download(self, remote_path: str, local_path: Path) -> None:
        """Download a file from storage.

        Args:
            remote_path: Path to file in storage
            local_path: Local destination path

        Raises:
            StorageError: If download fails
            BackupNotFoundError: If file doesn't exist
        """
        ...

    @abstractmethod
    def delete(self, remote_path: str) -> None:
        """Delete a file from storage.

        Args:
            remote_path: Path to file in storage

        Raises:
            StorageError: If deletion fails
        """
        ...

    @abstractmethod
    def exists(self, remote_path: str) -> bool:
        """Check if a file exists in storage.

        Args:
            remote_path: Path to check

        Returns:
            True if file exists
        """
        ...

    @abstractmethod
    def list(self, prefix: str) -> list[str]:
        """List files with the given prefix.

        Args:
            prefix: Path prefix to filter by

        Returns:
            List of file paths matching the prefix
        """
        ...

    @abstractmethod
    def get_size(self, remote_path: str) -> int:
        """Get the size of a file in bytes.

        Args:
            remote_path: Path to file

        Returns:
            File size in bytes

        Raises:
            BackupNotFoundError: If file doesn't exist
        """
        ...

    @abstractmethod
    def get_total_size(self, prefix: str) -> int:
        """Get total size of all files with the given prefix.

        Args:
            prefix: Path prefix to filter by

        Returns:
            Total size in bytes
        """
        ...
