"""Abstract base for filesystem readers."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from gaol.diff.models import DiffOptions, FilesystemManifest


class FilesystemReader(ABC):
    """Abstract base for reading container filesystems.

    Each runtime implements its own reader using the most efficient
    method for accessing the container's filesystem.

    - Docker: Uses tar-based API (get_archive)
    - nspawn: Direct filesystem access at /var/lib/machines/
    - libvirt: Would use libguestfs tools
    """

    @property
    @abstractmethod
    def runtime_name(self) -> str:
        """Name of the runtime this reader supports."""
        pass

    @abstractmethod
    def read_container(
        self,
        container_id: str,
        options: DiffOptions | None = None,
    ) -> FilesystemManifest:
        """Read filesystem manifest from a container.

        Args:
            container_id: Container identifier (name or ID)
            options: Diff options for filtering

        Returns:
            FilesystemManifest with all file entries
        """
        pass

    @abstractmethod
    def read_snapshot(
        self,
        container_name: str,
        snapshot_name: str,
        options: DiffOptions | None = None,
    ) -> FilesystemManifest:
        """Read filesystem manifest from a snapshot.

        Args:
            container_name: Container name
            snapshot_name: Snapshot name
            options: Diff options for filtering

        Returns:
            FilesystemManifest with all file entries
        """
        pass

    def read_image(
        self,
        image_name: str,
        options: DiffOptions | None = None,
    ) -> FilesystemManifest:
        """Read filesystem manifest from a base image.

        Default implementation raises NotImplementedError.
        Override in subclasses that support image reading.

        Args:
            image_name: Image identifier
            options: Diff options for filtering

        Returns:
            FilesystemManifest with all file entries
        """
        raise NotImplementedError(
            f"{self.runtime_name} does not support reading base images"
        )

    def read_file_content(
        self,
        container_id: str,
        path: str,
        max_size: int = 1024 * 1024,
    ) -> bytes | None:
        """Read file content from a container.

        Used for content diff display. Default returns None (not supported).

        Args:
            container_id: Container identifier
            path: File path within container
            max_size: Maximum bytes to read

        Returns:
            File content bytes or None if not supported/too large
        """
        return None
