import boto3
import uuid
import os
from typing import Optional
from botocore.exceptions import ClientError
from app.core.config import settings
from app.core.logging_config import logger

class StorageHelper:
    """Utility class to upload product images to MinIO (dev) or AWS S3 (production)."""

    def __init__(self):
        # 1. Konfigurasi S3 Client
        session_opts = {
            "aws_access_key_id": settings.AWS_ACCESS_KEY_ID,
            "aws_secret_access_key": settings.AWS_SECRET_ACCESS_KEY,
        }
        
        # Tambahkan endpoint URL untuk local MinIO dev environment
        if settings.AWS_S3_ENDPOINT_URL:
            session_opts["endpoint_url"] = settings.AWS_S3_ENDPOINT_URL
            
        self.s3_client = boto3.client("s3", **session_opts)
        self.bucket_name = settings.AWS_S3_BUCKET
        self._ensure_bucket_exists()

    def _ensure_bucket_exists(self):
        """Verify storage bucket exists, attempting creation if missing."""
        try:
            self.s3_client.head_bucket(Bucket=self.bucket_name)
        except ClientError as e:
            error_code = e.response.get("Error", {}).get("Code")
            # Jika bucket tidak ditemukan (404), buat bucket baru
            if error_code == "404" or error_code == "NoSuchBucket":
                try:
                    logger.info(f"Creating storage bucket: {self.bucket_name}")
                    self.s3_client.create_bucket(Bucket=self.bucket_name)
                    
                    # Set bucket policy agar object di dalamnya bisa dibaca public (untuk render gambar di UI)
                    public_read_policy = f"""{{
                        "Version": "2012-10-17",
                        "Statement": [
                            {{
                                "Sid": "PublicRead",
                                "Effect": "Allow",
                                "Principal": "*",
                                "Action": ["s3:GetObject"],
                                "Resource": ["arn:aws:s3:::{self.bucket_name}/*"]
                            }}
                        ]
                    }}"""
                    self.s3_client.put_bucket_policy(Bucket=self.bucket_name, Policy=public_read_policy)
                except Exception as ex:
                    logger.warning(f"Failed to auto-create bucket or set policy: {ex}. Storage operations might fail if bucket doesn't exist.")
            else:
                logger.error(f"Storage connection issue: {e}")

    def upload_file(self, file_data: bytes, filename: str, content_type: str) -> Optional[str]:
        """Upload image bytes to storage bucket, returning its public URL link."""
        # Gunakan UUID name generator untuk mencegah tabrakan nama file
        ext = os.path.splitext(filename)[1] or ".jpg"
        unique_filename = f"products/{uuid.uuid4()}{ext}"

        try:
            self.s3_client.put_object(
                Bucket=self.bucket_name,
                Key=unique_filename,
                Body=file_data,
                ContentType=content_type,
                ACL="public-read"  # Agar gambar bisa diakses langsung via browser
            )
            
            # Hasilkan Link File URL
            if settings.AWS_S3_ENDPOINT_URL:
                # Local MinIO URL
                return f"{settings.AWS_S3_ENDPOINT_URL}/{self.bucket_name}/{unique_filename}"
            else:
                # AWS S3 standard URL
                return f"https://{self.bucket_name}.s3.amazonaws.com/{unique_filename}"
                
        except Exception as e:
            logger.error(f"Failed uploading file to storage: {e}")
            return None

# Instansiasi objek tunggal (singleton helper)
try:
    storage_helper = StorageHelper()
except Exception as e:
    logger.error(f"Could not connect to S3/MinIO client: {e}. Falling back to mock storage.")
    storage_helper = None
