"""ImageGenResult — resultado de una operacion de generacion de imagen."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

# PIL.Image.Image se importa solo para type-checking estatico (mypy/pyright).
# En runtime NO se importa aqui — el consumidor ya tiene PIL instalado si
# trabaja con imagenes reales. Esto evita ImportError cuando el modulo se
# importa en contextos sin Pillow (ej. el orquestador Go via grpc/json).
if TYPE_CHECKING:
    from PIL.Image import Image as PILImage

try:
    from pydantic import BaseModel, ConfigDict, field_validator

    class ImageGenResult(BaseModel):
        """Resultado de una operacion de generacion de imagen con modelo de difusion.

        El campo `image` contiene el objeto PIL.Image.Image generado. No es
        serializable a JSON — se accede directamente para guardar a disco o
        pasar a pipelines de post-proceso. Para serializar el resultado,
        usar solo el campo `meta` (que incluye la config usada) y guardar
        la imagen por separado.

        Attributes:
            image:        Imagen generada. Tipo PIL.Image.Image en runtime.
                          No incluido en model_dump() ni model_dump_json().
                          None si la generacion fallo (ver meta["error"]).
            meta:         Diccionario con metadata de la generacion. Debe incluir:
                          - "config": GenerationConfig.model_dump() con los params usados.
                          - "model": nombre del modelo.
                          - "seed_used": semilla real usada (util cuando seed=-1).
                          - "sampler": nombre del sampler.
                          Puede incluir campos adicionales del backend.
            duration_ms:  Tiempo total de generacion en milisegundos.
            vram_peak_mb: Pico de VRAM consumida durante la generacion en MiB.
                          None si no se pudo medir (CPU inference o backend sin soporte).
        """

        model_config = ConfigDict(arbitrary_types_allowed=True)

        image: Any  # PIL.Image.Image en runtime; Any para evitar dep dura
        meta: dict[str, Any]
        duration_ms: int
        vram_peak_mb: int | None = None

        @field_validator("image", mode="before")
        @classmethod
        def _validate_image(cls, v: Any) -> Any:
            # Aceptar None (generacion fallida) o cualquier objeto imagen.
            # No forzamos importar PIL aqui — la validacion real la hace el backend.
            return v

        def model_dump(self, **kwargs: Any) -> dict[str, Any]:
            """Serializa a dict excluyendo el campo image (no serializable a JSON).

            Returns:
                dict con meta, duration_ms y vram_peak_mb. El campo image se omite.
            """
            return {
                "meta": self.meta,
                "duration_ms": self.duration_ms,
                "vram_peak_mb": self.vram_peak_mb,
            }

        def model_dump_json(self, **kwargs: Any) -> str:
            """Serializa a JSON excluyendo el campo image.

            Returns:
                String JSON con meta, duration_ms y vram_peak_mb.
            """
            import json

            return json.dumps(self.model_dump())

except ImportError:
    from dataclasses import dataclass

    @dataclass
    class ImageGenResult:  # type: ignore[no-redef]
        """Resultado de generacion de imagen (fallback dataclass).

        El campo `image` es PIL.Image.Image en runtime. No serializable a JSON.
        Usar `meta` + guardar imagen por separado para persistencia.

        Attributes:
            image:        PIL.Image.Image generada. None si fallo.
            meta:         Metadata: config usada, modelo, seed_used, sampler, etc.
            duration_ms:  Duracion total de generacion en milisegundos.
            vram_peak_mb: Pico de VRAM en MiB. None si no se pudo medir.
        """

        image: Any  # PIL.Image.Image
        meta: dict
        duration_ms: int
        vram_peak_mb: int | None = None
