"""Combina una lista de PIL Images en un grid NxM con gap y labels opcionales."""

from __future__ import annotations

import math


def image_grid(
    images: list["PIL.Image.Image"],
    cols: int = 4,
    labels: list[str] | None = None,
    gap_px: int = 8,
    bg_color: tuple = (20, 20, 20),
) -> "PIL.Image.Image":
    """Combina una lista de imagenes en un grid NxM.

    Asume que todas las imagenes tienen el mismo tamano (usa el maximo
    ancho/alto detectado). Calcula rows = ceil(n / cols) automaticamente.

    Args:
        images: lista de PIL.Image.Image a colocar en el grid.
        cols: numero de columnas del grid (default 4).
        labels: lista opcional de strings. Si se proporciona, se escribe
                un label encima de cada celda usando la fuente default de PIL.
        gap_px: espacio en pixeles entre celdas y en los bordes (default 8).
        bg_color: color de fondo RGB del canvas (default casi negro (20,20,20)).

    Returns:
        Una sola PIL.Image en modo RGB con el grid montado.

    Raises:
        ImportError: si Pillow no esta instalado.
        ValueError: si images esta vacio.
    """
    try:
        from PIL import Image, ImageDraw, ImageFont
    except ImportError as exc:
        raise ImportError(
            "Pillow no esta instalado. Instalar con: pip install Pillow"
        ) from exc

    if not images:
        raise ValueError("image_grid: la lista de imagenes no puede estar vacia")

    n = len(images)
    rows = math.ceil(n / cols)

    # Tamano de celda: max ancho y alto de todas las imagenes
    cell_w = max(img.width for img in images)
    cell_h = max(img.height for img in images)

    canvas_w = cols * cell_w + (cols + 1) * gap_px
    canvas_h = rows * cell_h + (rows + 1) * gap_px

    canvas = Image.new("RGB", (canvas_w, canvas_h), color=bg_color)

    draw = ImageDraw.Draw(canvas) if labels else None
    font = None
    if draw:
        try:
            font = ImageFont.load_default()
        except Exception:
            font = None

    for idx, img in enumerate(images):
        row = idx // cols
        col = idx % cols
        x = gap_px + col * (cell_w + gap_px)
        y = gap_px + row * (cell_h + gap_px)

        # Convertir a RGB si hace falta (RGBA, L, P, etc.)
        paste_img = img.convert("RGB") if img.mode != "RGB" else img
        canvas.paste(paste_img, (x, y))

        if draw and labels and idx < len(labels):
            label = labels[idx]
            # Texto en la esquina superior izquierda de la celda
            draw.text((x + 2, y + 2), label, fill=(255, 255, 255), font=font)

    return canvas
