"""Helpers for optional motion artifact encoding."""

from __future__ import annotations

from io import BytesIO
from pathlib import Path
from typing import Any


class MotionEncodingUnavailableError(RuntimeError):
    """Raised when optional motion-encoding dependencies are unavailable."""


def encode_gif(frame_pngs: list[bytes], path: Path, *, fps: int) -> Path:
    """Encode PNG frames into a looping GIF written to ``path``."""

    if not frame_pngs:
        raise ValueError("motion snapshot requires at least one frame")
    if fps < 1:
        raise ValueError(f"motion snapshot fps must be >= 1, got {fps}")

    try:
        from PIL import Image
    except ImportError as exc:  # pragma: no cover - depends on optional dependency
        raise MotionEncodingUnavailableError(
            "GIF motion snapshots require Pillow; install infra-screenshot[motion]"
        ) from exc

    frames: list[Any] = []
    for frame_png in frame_pngs:
        with BytesIO(frame_png) as buffer:
            with Image.open(buffer) as image:
                frames.append(image.convert("RGBA"))

    duration_ms = max(1, int(round(1000.0 / float(fps))))
    first, *rest = frames
    try:
        first.save(
            path,
            format="GIF",
            save_all=True,
            append_images=rest,
            duration=duration_ms,
            loop=0,
            disposal=2,
        )
    finally:
        for frame in frames:
            try:
                frame.close()
            except Exception:
                pass
    return path
