"""Supabase Storage service for post image uploads."""
import asyncio
import uuid
from typing import Optional
from loguru import logger

from src.config import settings


ALLOWED_CONTENT_TYPES = {
    "image/jpeg", "image/png", "image/gif", "image/webp",
    "video/mp4", "video/webm", "video/quicktime"
}
MAX_IMAGE_SIZE = 5 * 1024 * 1024  # 5MB
MAX_VIDEO_SIZE = 50 * 1024 * 1024  # 50MB
MAX_FILE_SIZE = MAX_IMAGE_SIZE  # Deprecated: for backward compatibility
BUCKET_NAME = "post-images"

CONTENT_TYPE_EXTENSIONS = {
    "image/jpeg": "jpg",
    "image/png": "png",
    "image/gif": "gif",
    "image/webp": "webp",
    "video/mp4": "mp4",
    "video/webm": "webm",
    "video/quicktime": "mov",
}


class StorageService:
    """Handles image uploads to Supabase Storage."""

    def __init__(self):
        from supabase import create_client
        key = settings.supabase_service_role_key or settings.supabase_key
        self.client = create_client(settings.supabase_url, key)
        self._bucket_ensured = False

    def _ensure_bucket(self):
        """Create the post-images bucket if it doesn't exist."""
        if self._bucket_ensured:
            return
        try:
            self.client.storage.get_bucket(BUCKET_NAME)
        except Exception:
            try:
                self.client.storage.create_bucket(
                    BUCKET_NAME,
                    options={"public": True}
                )
                logger.info(f"Created storage bucket: {BUCKET_NAME}")
            except Exception as e:
                if "already exists" in str(e).lower() or "Duplicate" in str(e):
                    pass
                else:
                    logger.error(f"Failed to create bucket: {e}")
                    raise
        self._bucket_ensured = True

    async def upload_media(
        self,
        file_content: bytes,
        content_type: str,
        user_id: str,
    ) -> str:
        """Upload an image or video to Supabase Storage.

        Args:
            file_content: File bytes
            content_type: MIME type (e.g., 'image/jpeg', 'video/mp4')
            user_id: User ID for folder organization

        Returns:
            Public URL of the uploaded media.

        Raises:
            ValueError: If content type is not allowed or file is too large.
        """
        if content_type not in ALLOWED_CONTENT_TYPES:
            raise ValueError(
                f"Unzulässiger Dateityp: {content_type}. "
                f"Erlaubt: JPEG, PNG, GIF, WebP, MP4, WebM, MOV"
            )

        # Check size based on type
        is_video = content_type.startswith("video/")
        max_size = MAX_VIDEO_SIZE if is_video else MAX_IMAGE_SIZE

        if len(file_content) > max_size:
            max_mb = max_size // 1024 // 1024
            media_type = "Video" if is_video else "Bild"
            raise ValueError(f"{media_type} zu groß (max. {max_mb} MB)")

        ext = CONTENT_TYPE_EXTENSIONS.get(content_type, "bin")
        file_name = f"{user_id}/{uuid.uuid4()}.{ext}"

        def _upload():
            self._ensure_bucket()
            self.client.storage.from_(BUCKET_NAME).upload(
                path=file_name,
                file=file_content,
                file_options={"content-type": content_type},
            )

        await asyncio.to_thread(_upload)

        public_url = f"{settings.supabase_url}/storage/v1/object/public/{BUCKET_NAME}/{file_name}"
        media_type = "video" if is_video else "image"
        logger.info(f"Uploaded {media_type}: {file_name}")
        return public_url

    async def upload_image(
        self,
        file_content: bytes,
        content_type: str,
        user_id: str,
    ) -> str:
        """DEPRECATED: Upload an image to Supabase Storage.

        Use upload_media() instead. This method is kept for backward compatibility.

        Returns the public URL of the uploaded image.
        """
        return await self.upload_media(file_content, content_type, user_id)

    async def delete_image(self, image_url: str) -> None:
        """Delete an image from Supabase Storage by its public URL."""
        prefix = f"{settings.supabase_url}/storage/v1/object/public/{BUCKET_NAME}/"
        if not image_url.startswith(prefix):
            logger.warning(f"Cannot delete image, URL doesn't match bucket: {image_url}")
            return

        file_path = image_url[len(prefix):]

        def _delete():
            self._ensure_bucket()
            self.client.storage.from_(BUCKET_NAME).remove([file_path])

        await asyncio.to_thread(_delete)
        logger.info(f"Deleted image: {file_path}")

    @staticmethod
    def get_proxy_url(image_url: str, app_base_url: str = "") -> str:
        """
        Convert a Supabase storage URL to a proxied HTTPS URL.

        This solves mixed content issues when Supabase storage uses HTTP
        but the app uses HTTPS.

        Args:
            image_url: The original Supabase storage URL
            app_base_url: Base URL of the app (e.g., https://linkedin.onyva.dev)

        Returns:
            Proxied URL through the app (e.g., /proxy/image/post-images/...)
        """
        if not image_url:
            return ""

        # Extract bucket and path from Supabase URL
        # Format: http://supabase.../storage/v1/object/public/{bucket}/{path}
        parts = image_url.split("/storage/v1/object/public/")
        if len(parts) != 2:
            return image_url  # Return original if format doesn't match

        bucket_and_path = parts[1]  # e.g., "post-images/user-id/file.jpg"
        parts2 = bucket_and_path.split("/", 1)
        if len(parts2) != 2:
            return image_url

        bucket, path = parts2

        # Return proxy URL
        return f"{app_base_url}/proxy/image/{bucket}/{path}"


# Global singleton
storage = StorageService()
