import boto3
from botocore.client import Config
from botocore.exceptions import ClientError
from abc import ABC, abstractmethod
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from core import AppConfig

class StorageRepository(ABC):
    @abstractmethod
    def upload_file(self, file_obj, bucket: str, file_path: str) -> None:
        pass

    @abstractmethod
    def download_file(self, bucket: str, filename: str, local_path: str) -> None:
        pass

    @abstractmethod
    def check_connection(self, bucket: str) -> str:
        pass

# Concrete Implementations
class MinIOStorageRepository(StorageRepository):
    def __init__(self, config: AppConfig):
        self.config = config
        self.client = boto3.client(
            "s3",
            endpoint_url=config.minio_endpoint,
            aws_access_key_id=config.minio_access_key,
            aws_secret_access_key=config.minio_secret_key,
            config=Config(signature_version="s3v4")
        )

    def upload_file(self, file_obj, bucket: str, file_path: str) -> None:
        self.client.upload_fileobj(file_obj, bucket, file_path)

    def download_file(self, bucket: str, filename: str, local_path: str) -> None:
        self.client.download_file(bucket, filename, local_path)

    def check_connection(self, bucket: str) -> str:
        try:
            self.client.head_bucket(Bucket=bucket)
            return "connected"
        except Exception as e:
            return f"error: {str(e)}"

    def get_file_url(self, bucket: str, file_path: str, expires: int = 3600) -> str:
        """Generate a presigned URL to share an S3 object"""
        try:
            url = self.client.generate_presigned_url(
                'get_object',
                Params={'Bucket': bucket, 'Key': file_path},
                ExpiresIn=expires
            )
            return url
        except ClientError as e:
            print(f"Error generating presigned URL: {e}")
            return None