"""Consulta el catalogo de nodos de un servidor ComfyUI via GET /object_info.

Funcion impura: hace red (HTTP GET). Solo stdlib (urllib, json).

El catalogo describe cada class_type disponible: sus inputs requeridos y
opcionales, sus tipos, y los valores enumerados (ej. la lista de checkpoints
visibles para el servidor en CheckpointLoaderSimple). Util para validar un
workflow antes de enviarlo y para descubrir que checkpoints/samplers existen.
"""
import json
import urllib.error
import urllib.parse
import urllib.request


def comfyui_object_info(
    server: str = "127.0.0.1:8188",
    node_class: str | None = None,
    timeout: float = 30.0,
) -> dict:
    """Recupera el catalogo de nodos (o uno concreto) de ComfyUI.

    Args:
        server: host:port del servidor ComfyUI (sin esquema).
        node_class: si se pasa, consulta solo ese class_type via
            GET /object_info/{node_class} (ej. "CheckpointLoaderSimple").
            Si es None, devuelve el catalogo completo (GET /object_info).
        timeout: timeout de la peticion HTTP en segundos.

    Returns:
        dict con el catalogo. Con node_class=None es {class_type: spec, ...}.
        Con node_class set, ComfyUI devuelve {class_type: spec} (un solo item).

    Raises:
        RuntimeError: si la peticion HTTP falla (conexion rechazada, timeout,
            HTTP de error) o si la respuesta no es JSON valido. El mensaje
            incluye el cuerpo del error cuando ComfyUI lo provee.
    """
    path = "/object_info"
    if node_class is not None:
        path = f"/object_info/{urllib.parse.quote(node_class)}"
    url = f"http://{server}{path}"
    try:
        with urllib.request.urlopen(url, timeout=timeout) as resp:
            return json.loads(resp.read())
    except urllib.error.HTTPError as exc:
        body = exc.read().decode(errors="replace")
        raise RuntimeError(
            f"comfyui_object_info: HTTP {exc.code} en {url}: {body}"
        ) from exc
    except urllib.error.URLError as exc:
        raise RuntimeError(
            f"comfyui_object_info: no se pudo conectar a {url}: {exc.reason}"
        ) from exc
    except json.JSONDecodeError as exc:
        raise RuntimeError(
            f"comfyui_object_info: respuesta no es JSON valido desde {url}: {exc}"
        ) from exc


if __name__ == "__main__":
    info = comfyui_object_info()
    print(f"nodos disponibles: {len(info)}")
    ckpts = info["CheckpointLoaderSimple"]["input"]["required"]["ckpt_name"][0]
    print(f"checkpoints visibles: {ckpts}")
