# /opt/docker/dev/service_finder/backend/app/services/storage_service.py
import uuid
import socket
from io import BytesIO
from datetime import timedelta
from minio import Minio
from minio.error import S3Error
from app.core.config import settings
import logging

logger = logging.getLogger(__name__)


class StorageService:
    """MinIO S3 objektumtároló szolgáltatás."""

    @classmethod
    def _resolve_endpoint(cls, endpoint: str) -> str:
        """
        Resolve hostname to IP address if endpoint contains a hostname.
        This helps with MinIO 'invalid hostname' issues.
        """
        if "://" in endpoint:
            # Remove protocol
            endpoint = endpoint.split("://")[1]
        
        if ":" in endpoint:
            host, port = endpoint.split(":", 1)
        else:
            host, port = endpoint, "9000"
        
        # Try to resolve hostname to IP
        try:
            ip = socket.gethostbyname(host)
            resolved_endpoint = f"{ip}:{port}"
            logger.debug(f"Resolved endpoint {endpoint} -> {resolved_endpoint}")
            return resolved_endpoint
        except socket.gaierror:
            logger.warning(f"Could not resolve hostname {host}, using original endpoint")
            return endpoint

    # MinIO kliens inicializálása a konfigurációból
    @classmethod
    def _get_client(cls):
        """Get MinIO client with resolved endpoint."""
        resolved_endpoint = cls._resolve_endpoint(settings.MINIO_ENDPOINT)
        return Minio(
            endpoint=resolved_endpoint,
            access_key=settings.MINIO_ACCESS_KEY,
            secret_key=settings.MINIO_SECRET_KEY,
            secure=settings.MINIO_SECURE,
        )
    
    @classmethod
    def _get_client_instance(cls):
        """Get client instance (cached)."""
        if not hasattr(cls, '_client_instance'):
            cls._client_instance = cls._get_client()
        return cls._client_instance
    
    # Client property
    @classmethod
    def client(cls):
        """Get MinIO client instance."""
        return cls._get_client_instance()

    @classmethod
    async def ensure_bucket_exists(cls, bucket_name: str) -> bool:
        """
        Ellenőrzi, hogy a megadott vödör létezik-e, ha nem, létrehozza.
        
        Args:
            bucket_name: A vödör neve
        
        Returns:
            True ha a vödör létezik vagy sikeresen létrejött, False ha hiba történt.
        """
        try:
            client = cls.client()
            if not client.bucket_exists(bucket_name):
                client.make_bucket(bucket_name)
                logger.info(f"Bucket '{bucket_name}' created.")
            else:
                logger.debug(f"Bucket '{bucket_name}' already exists.")
            return True
        except S3Error as e:
            logger.error(f"Error ensuring bucket '{bucket_name}': {e}")
            return False

    @classmethod
    async def upload_image(
        cls,
        file_bytes: bytes,
        bucket_name: str,
        object_name: str,
        content_type: str = "application/octet-stream",
    ) -> str:
        """
        Feltölt egy fájlt a MinIO tárolóba.
        
        Args:
            file_bytes: A fájl tartalma bájtokban
            bucket_name: Cél vödör neve
            object_name: Objektum neve (pl. 'images/photo.jpg')
            content_type: MIME típus (alapértelmezett: 'application/octet-stream')
        
        Returns:
            Az objektum teljes elérési útja (bucket/object_name)
        
        Raises:
            S3Error: Ha a feltöltés sikertelen
        """
        await cls.ensure_bucket_exists(bucket_name)
        
        # Feltöltés
        client = cls.client()
        client.put_object(
            bucket_name=bucket_name,
            object_name=object_name,
            data=BytesIO(file_bytes),
            length=len(file_bytes),
            content_type=content_type,
        )
        logger.info(f"Uploaded object '{object_name}' to bucket '{bucket_name}'.")
        return f"{bucket_name}/{object_name}"

    @classmethod
    def get_presigned_url(
        cls,
        bucket_name: str,
        object_name: str,
        expires: timedelta = timedelta(hours=1),
    ) -> str:
        """
        Generál egy előjegyzett URL-t a fájl letöltéséhez.
        
        Args:
            bucket_name: A vödör neve
            object_name: Az objektum neve
            expires: Az URL érvényességi ideje (alapértelmezett: 1 óra)
        
        Returns:
            Az előjegyzett URL string
        """
        try:
            client = cls.client()
            url = client.presigned_get_object(
                bucket_name=bucket_name,
                object_name=object_name,
                expires=int(expires.total_seconds()),
            )
            logger.debug(f"Generated presigned URL for '{bucket_name}/{object_name}'.")
            return url
        except S3Error as e:
            logger.error(f"Error generating presigned URL: {e}")
            raise

    # Kompatibilitás a régi kóddal
    BUCKET_NAME = "vehicle-documents"

    @classmethod
    async def upload_document(cls, file_bytes: bytes, file_name: str, folder: str) -> str:
        """Kompatibilitási metódus a régi kóddal."""
        object_name = f"{folder}/{uuid.uuid4()}_{file_name}"
        return await cls.upload_image(
            file_bytes=file_bytes,
            bucket_name=cls.BUCKET_NAME,
            object_name=object_name,
            content_type="application/octet-stream",
        )