import io
import os

from django.core.files.base import ContentFile
from django.core.files.storage import FileSystemStorage
import pillow_heif
from PIL import Image, ImageSequence

pillow_heif.register_heif_opener()
from storages.backends.s3boto3 import S3Boto3Storage, S3StaticStorage

# All formats Pillow handles natively (no extra plugins needed).
# Add '.heic' / '.heif' if you install pillow-heif.
_IMAGE_EXTS = {
    '.jpg', '.jpeg', '.jpe', '.jfif',   # JPEG variants
    '.png',                              # PNG
    '.gif',                              # GIF (animated preserved)
    '.bmp', '.dib',                      # BMP
    '.tiff', '.tif',                     # TIFF
    '.tga',                              # Truevision TGA
    '.ico',                              # ICO (largest frame used)
    '.ppm', '.pgm', '.pbm', '.pnm',     # Portable pixmap family
    '.pcx',                              # PCX
    '.heic', '.heif',                    # Apple HEIC/HEIF (pillow-heif)
}

def _to_webp(content, quality: int = 85) -> io.BytesIO:
    img = Image.open(content)
    frames = list(ImageSequence.Iterator(img))
    out = io.BytesIO()
    if len(frames) > 1:
        converted = [f.copy().convert('RGBA') for f in frames]
        converted[0].save(
            out,
            format='WEBP',
            save_all=True,
            append_images=converted[1:],
            loop=img.info.get('loop', 0),
            quality=quality,
        )
    else:
        img.convert('RGBA').save(out, format='WEBP', quality=quality)
    out.seek(0)
    return out


class WebPConversionMixin:
    """
    Intercepts image/GIF uploads and converts them to WebP before storage.
    Videos are saved as-is; use `vontor_cz.tasks.convert_video_to_webm` async
    to transcode them to WebM after save.
    """
    WEBP_QUALITY: int = 85

    def _save(self, name: str, content) -> str:
        root, ext = os.path.splitext(name)
        if ext.lower() in _IMAGE_EXTS:
            try:
                webp_data = _to_webp(content, self.WEBP_QUALITY)
                content = ContentFile(webp_data.read())
                name = root + '.webp'
            except Exception:
                content.seek(0)
        return super()._save(name, content)


class MediaStorage(WebPConversionMixin, S3Boto3Storage):
    def exists(self, name):
        if not name:
            return False
        return super().exists(name)


class LocalMediaStorage(WebPConversionMixin, FileSystemStorage):
    pass


class StaticStorage(S3StaticStorage):
    def exists(self, name):
        if not name:
            return False
        return super().exists(name)
