"""
Interface for S3 upload services.

Defines the contract for S3 upload operations including dataset chunk uploads,
manifest management, and file organization.
"""

from abc import ABC, abstractmethod
from typing import List, Dict, Any
from ..models import DatasetChunk, UploadResult, UploadConfig


class UploadServiceInterface(ABC):
    """
    Interface for S3 upload operations.
    
    Handles uploading dataset chunks to S3, managing manifests and drop IDs,
    and organizing files according to CloudZero folder structure.
    """
    
    @abstractmethod
    def upload_dataset_chunk(
        self,
        chunk: DatasetChunk,
        drop_id: str,
        billing_period: str
    ) -> UploadResult:
        """
        Upload a single dataset chunk to S3.
        
        Args:
            chunk: Dataset chunk with data and metadata
            drop_id: Unique drop identifier for this upload batch
            billing_period: Billing period in YYYYMMDD-YYYYMMDD format
            
        Returns:
            UploadResult with upload outcome and metadata
        """
        pass
    
    @abstractmethod
    def stream_upload_files(
        self,
        dataset_name: str,
        provider: str,
        months: List[str],
        stage: str,
        organization: str,
        drop_id: str
    ) -> List[UploadResult]:
        """
        Stream upload multiple files for a provider.
        
        Loads and uploads files one at a time to minimize memory usage.
        
        Args:
            dataset_name: Name of the dataset
            provider: Provider name
            months: List of months to process
            stage: Processing stage
            organization: Organization name
            drop_id: Unique drop identifier
            
        Returns:
            List of UploadResult for each uploaded file
        """
        pass
    
    @abstractmethod
    def update_manifest_for_drop(
        self,
        organization: str,
        provider: str,
        billing_period: str,
        drop_id: str
    ) -> None:
        """
        Update manifest file for a drop.
        
        Args:
            organization: Organization name
            provider: Provider name  
            billing_period: Billing period
            drop_id: Drop identifier to add to manifest
        """
        pass
    
    @abstractmethod
    def prune_old_drops_for_period(
        self,
        organization: str,
        provider: str,
        billing_period: str,
        max_drops: int = 3
    ) -> List[str]:
        """
        Prune old drops for a billing period, keeping latest N drops.
        
        Args:
            organization: Organization name
            provider: Provider name
            billing_period: Billing period
            max_drops: Maximum number of drops to keep
            
        Returns:
            List of error messages from pruning operations
        """
        pass
    
    @abstractmethod
    def calculate_billing_period(self, month: str) -> str:
        """
        Calculate billing period from month string.
        
        Args:
            month: Month in YYYY-MM format
            
        Returns:
            Billing period in YYYYMMDD-YYYYMMDD format
        """
        pass
    
    @abstractmethod
    def validate_bucket_access(self, bucket: str, region: str) -> bool:
        """
        Validate S3 bucket access and permissions.
        
        Args:
            bucket: S3 bucket name
            region: S3 region
            
        Returns:
            True if bucket is accessible, False otherwise
            
        Raises:
            UploadServiceError: If validation fails with details
        """
        pass
    
    @abstractmethod
    def generate_drop_id(self) -> str:
        """
        Generate unique drop ID for upload batch.
        
        Returns:
            Unique drop identifier (timestamp-based)
        """
        pass