from abc import ABC, abstractmethod
from typing import Optional, Dict, Any, List


class BaseStorageProvider(ABC):
    """Abstract base class for cloud storage providers"""

    def __init__(self, bucket_name: str, **kwargs):
        self.bucket_name = bucket_name
        self.config = kwargs
        self._initialize_client()

    @abstractmethod
    def _initialize_client(self):
        """Initialize the cloud provider client"""
        pass

    @abstractmethod
    def upload(
        self,
        data: bytes,
        remote_path: str,
        content_type: str = "application/octet-stream",
        metadata: Optional[Dict[str, str]] = None,
        cache_control: Optional[str] = None,
    ) -> str:
        """Upload data to storage and return public URL"""
        pass

    @abstractmethod
    def download(self, remote_path: str) -> bytes:
        """Download data from storage"""
        pass

    @abstractmethod
    def get_size(self, remote_path: str) -> int:
        """Upload data to storage and return public URL"""
        pass

    @abstractmethod
    def download_as_string(self, remote_path: str) -> str:
        """Download as string"""
        pass

    @abstractmethod
    def download_as_bytes(self, remote_path: str) -> bytes:
        """Download as bytes"""
        pass

    @abstractmethod
    def get_content_type(self, remote_path: str) -> str:
        """Get content type of  object"""
        pass

    @abstractmethod
    def copy(self, source_path: str, destination_path: str) -> str:
        """Copy object inside  bucket"""
        pass

    @abstractmethod
    def delete(self, remote_path: str) -> bool:
        """Delete object from storage"""
        pass

    @abstractmethod
    def exists(self, remote_path: str) -> bool:
        """Delete object from storage"""
        pass

    @abstractmethod
    def rename(self, source_path: str, destination_path: str) -> str:
        """Move """
        pass

    @abstractmethod
    def list_objects(self, prefix: str = "", max_results: int = 1000) -> List[str]:
        """List objects in bucket with optional prefix"""
        pass

    @abstractmethod
    def exists(self, remote_path: str) -> bool:
        """Check if object exists"""
        pass

    @abstractmethod
    def get_public_url(self, remote_path: str) -> str:
        """Get public URL for object"""
        pass

    @abstractmethod
    def get_signed_url(self, remote_path: str, expiration: int = 3600) -> str:
        """Generate signed/presigned URL"""
        pass
