"""Construye el workflow ComfyUI de UN elemento de interfaz de juego (UI/HUD) en API format.

Elementos de UI/HUD de juego (botones, marcos/paneles, barras de vida/mana/XP,
iconos de UI, cursores, vinhetas de menu): pieza unica centrada, fondo limpio y
uniforme, estilo consistente entre elementos del mismo set, recortable a alpha. Es
el builder hermano de comfyui_build_item_icon_workflow / comfyui_build_pixelart_workflow
/ comfyui_build_seamless_tile_workflow: mismo patron (PURO, dict API format) que
compone funciones existentes del registry, no reescribe el grafo.

Cableado:

    CheckpointLoaderSimple -> [LoraLoader opcional de estilo] -> KSampler
                          -> CLIPTextEncode (prompt scaffold de UI) ...
                          -> VAEDecode -> [Image Rembg opcional] -> SaveImage

Compone:
  - comfyui_build_txt2img_workflow  -> base txt2img cuadrada
  - comfyui_inject_lora             -> LoRA de estilo opcional (consistencia)
  - 'Image Rembg (Remove Background)' (helper local) -> fondo transparente

Por que Rembg y NO comfyui_matting_luma_to_alpha: un elemento de UI es una pieza
SOLIDA con silueta definida (un boton, un marco, una barra); rembg recorta limpio
la silueta dejando alpha. La luma-to-alpha es para translucidos sobre negro
(humo/fuego/magia) y aplanaria el elemento. Si el caller prefiere recortar fuera
del workflow (transparent=False) deja la imagen opaca sobre fondo plano, recortable
luego por el pipeline o el caller.

El mismo ui_style + checkpoint + (lora) en todas las piezas de un set (botones,
barras, marcos) hace que combinen visualmente: es la clave de un HUD coherente,
igual que en los iconos de inventario.

class_types/inputs verificados contra /object_info del servidor (8GB lowvram):
CheckpointLoaderSimple, CLIPTextEncode, EmptyLatentImage, KSampler, VAEDecode,
SaveImage, LoraLoader, 'Image Rembg (Remove Background)' (transparency BOOLEAN).

Funcion pura: sin red, sin I/O. No muta dicts de entrada (copia profunda en el
helper de rembg). Determinista para los mismos argumentos.
"""
from __future__ import annotations

import copy
import os
import sys

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

# Negativo por defecto pensado para UI/HUD: una sola pieza limpia, sin personajes
# ni escenas ni texto/marcas que ensucien la silueta centrada y recortable.
_UI_NEGATIVE = (
    "blurry, lowres, character, person, face, landscape, scene, "
    "multiple elements, cluttered, busy background, text, label, watermark, "
    "signature, photo, photorealistic, jpeg artifacts, cropped, out of frame, "
    "deformed"
)


def _inject_rembg(workflow: dict, model: str) -> dict:
    """Inserta 'Image Rembg (Remove Background)' (transparency=True) entre VAEDecode y SaveImage.

    Mismo helper que usan comfyui_build_item_icon_workflow / comfyui_build_sprite_sheet_workflow:
    el nodo recorta la silueta del elemento de UI dejando alpha. Repunta
    SaveImage.images a la salida del Rembg.
    """
    wf = copy.deepcopy(workflow)
    vaedecode_id = next(
        (nid for nid, n in wf.items() if n.get("class_type") == "VAEDecode"), None
    )
    save_id = next((nid for nid, n in wf.items() if n.get("class_type") == "SaveImage"), None)
    if vaedecode_id is None or save_id is None:
        raise ValueError(
            "comfyui_build_ui_hud_workflow: no se encontro VAEDecode/SaveImage para Rembg"
        )
    numeric = [int(k) for k in wf.keys() if str(k).isdigit()]
    rembg_id = str((max(numeric) + 1) if numeric else len(wf) + 1)
    wf[rembg_id] = {
        "class_type": "Image Rembg (Remove Background)",
        "inputs": {
            "images": [vaedecode_id, 0],
            "transparency": True,
            "model": model,
            "post_processing": False,
            "only_mask": False,
            "alpha_matting": False,
            "alpha_matting_foreground_threshold": 240,
            "alpha_matting_background_threshold": 10,
            "alpha_matting_erode_size": 10,
            "background_color": "none",
        },
    }
    wf[save_id]["inputs"]["images"] = [rembg_id, 0]
    return wf


def comfyui_build_ui_hud_workflow(
    element: str,
    *,
    ui_style: str = "fantasy game UI",
    checkpoint: str = "IMG_dreamshaper_8.safetensors",
    size: int = 512,
    transparent: bool = True,
    seed: int = 0,
    lora: str | None = None,
    lora_strength: float = 1.0,
    rembg_model: str = "u2net",
    negative: str | None = None,
    steps: int = 28,
    cfg: float = 7.0,
    sampler_name: str = "dpmpp_2m",
    scheduler: str = "karras",
    filename_prefix: str = "ui_hud",
) -> dict:
    """Construye el dict (API format) del workflow de un elemento de UI/HUD de juego.

    Args:
        element: nombre del elemento de interfaz (ej. "health bar", "wooden button",
            "ornate frame", "magic icon", "menu cursor", "mana orb"). Se inserta en
            un prompt scaffold de UI. No puede estar vacio.
        ui_style: descriptor de estilo de la interfaz que mantiene consistentes las
            piezas de un set (ej. "fantasy game UI", "sci-fi HUD, neon glow",
            "pixel art UI", "minimal flat UI"). Pasa el MISMO ui_style + checkpoint +
            (lora) a todos los elementos del HUD para coherencia visual. keyword-only.
        checkpoint: checkpoint del servidor. 'IMG_dreamshaper_8.safetensors' (SD1.5,
            holgado en 8GB lowvram) por defecto; 'IMG_juggernaut_xl_v11.safetensors'
            para SDXL (mas VRAM, subir size a 768/1024). keyword-only.
        size: lado del cuadrado en px (width = height = size). 512 SD1.5 por
            defecto. keyword-only.
        transparent: si True inyecta Rembg y el PNG sale con alpha (fondo
            recortado). Si False deja el elemento opaco sobre fondo plano,
            recortable luego por el caller/pipeline. keyword-only.
        seed: semilla del KSampler. keyword-only.
        lora: LoRA de estilo opcional en models/loras (ej.
            'SD15_detail_tweaker.safetensors'). None = sin LoRA. keyword-only.
        lora_strength: fuerza del LoRA sobre model y clip. Se clampa a [0.0, 2.0].
            keyword-only.
        rembg_model: modelo Rembg ('u2net' general, 'isnet-anime' para anime).
            Solo se usa si transparent=True. keyword-only.
        negative: prompt negativo. None usa el negativo por defecto pensado para
            UI (una pieza, fondo limpio, sin personajes/escena/texto). keyword-only.
        steps, cfg, sampler_name, scheduler, filename_prefix: parametros de
            generacion. keyword-only.

    Returns:
        dict en API format listo para comfyui_submit_workflow: txt2img base
        cuadrada con prompt scaffold de UI ('{element}, {ui_style}, game UI element,
        centered, clean, plain background, high detail') + LoRA de estilo opcional +
        Rembg (si transparent). Es UN elemento; un HUD completo -> llamar por element
        con el mismo ui_style/checkpoint/lora y montar con comfyui_build_grid si se
        quiere un atlas.

    Raises:
        ValueError: si element esta vacio, o si la base no tiene VAEDecode/SaveImage
            donde inyectar el Rembg (propagado por el helper).
    """
    from ml.comfyui_build_txt2img_workflow import comfyui_build_txt2img_workflow

    if not element or not element.strip():
        raise ValueError("comfyui_build_ui_hud_workflow: 'element' no puede estar vacio")

    lora_strength = max(0.0, min(2.0, float(lora_strength)))
    neg = _UI_NEGATIVE if negative is None else negative

    # Prompt scaffold de UI: pieza unica, centrada, fondo plano, recortable.
    positive = (
        f"{element.strip()}, {ui_style}, game UI element, centered, clean, "
        "plain background, high detail"
    )

    wf = comfyui_build_txt2img_workflow(
        checkpoint,
        positive,
        neg,
        steps=steps,
        cfg=cfg,
        width=size,
        height=size,
        seed=seed,
        sampler_name=sampler_name,
        scheduler=scheduler,
        filename_prefix=filename_prefix,
    )

    if lora:
        from ml.comfyui_inject_lora import comfyui_inject_lora

        wf = comfyui_inject_lora(
            wf, lora, strength_model=lora_strength, strength_clip=lora_strength
        )

    if transparent:
        wf = _inject_rembg(wf, rembg_model)

    return wf


if __name__ == "__main__":
    import json

    wf = comfyui_build_ui_hud_workflow(
        "ornate health bar frame",
        ui_style="fantasy game UI, gold filigree",
        transparent=True,
        seed=42,
    )
    print(
        json.dumps(
            {
                "nodes": list(wf),
                "classes": sorted({n["class_type"] for n in wf.values()}),
            },
            indent=2,
        )
    )
