"""Abstract base class for encryption backends."""

from __future__ import annotations

from abc import ABC, abstractmethod
from pathlib import Path
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from gaol.storage.models import VolumeConfig, VolumeState


class EncryptionBackendBase(ABC):
    """Abstract interface for encryption backends."""

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

    @abstractmethod
    def is_available(self) -> bool:
        """Check if this backend is available on the system."""
        ...

    @abstractmethod
    def create(self, config: VolumeConfig, key: bytes, storage_dir: Path) -> VolumeState:
        """Create a new encrypted volume.

        Args:
            config: Volume configuration
            key: Encryption key (raw bytes)
            storage_dir: Directory to store volume data

        Returns:
            Initial volume state

        Raises:
            StorageError: If creation fails
        """
        ...

    @abstractmethod
    def unlock(self, state: VolumeState, key: bytes) -> VolumeState:
        """Unlock (decrypt) a volume.

        Args:
            state: Current volume state
            key: Encryption key

        Returns:
            Updated volume state with mount_point set

        Raises:
            VolumeKeyError: If key is incorrect
            StorageError: If unlock fails
        """
        ...

    @abstractmethod
    def lock(self, state: VolumeState) -> VolumeState:
        """Lock (re-encrypt) a volume.

        Args:
            state: Current volume state (must be unlocked)

        Returns:
            Updated volume state

        Raises:
            VolumeMountedError: If volume is mounted
            StorageError: If lock fails
        """
        ...

    @abstractmethod
    def destroy(self, state: VolumeState) -> None:
        """Destroy a volume and all its data.

        Args:
            state: Volume state (must be locked)

        Raises:
            VolumeUnlockedError: If volume is unlocked
            StorageError: If destruction fails
        """
        ...

    @abstractmethod
    def get_mount_path(self, state: VolumeState) -> Path | None:
        """Get the accessible path for a volume.

        Args:
            state: Volume state

        Returns:
            Path to mounted/decrypted data, or None if locked
        """
        ...

    def resize(self, state: VolumeState, new_size_mb: int, key: bytes) -> VolumeState:
        """Resize a volume.

        Default implementation raises NotImplementedError.

        Args:
            state: Volume state (should be locked)
            new_size_mb: New size in megabytes
            key: Encryption key

        Returns:
            Updated volume state
        """
        raise NotImplementedError(f"{self.name} does not support volume resizing")
