"""Construye el workflow ComfyUI de UN icono de estado / buff-debuff (API format).

Iconos de estado de juego (veneno, quemadura, congelacion, escudo, regeneracion,
aturdimiento, velocidad, sangrado, bendicion, maldicion): simbolo unico, audaz y
LEGIBLE A TAMANO REDUCIDO, centrado, fondo limpio y uniforme, estilo de UI
consistente entre estados del mismo set, recortable a alpha. Es el builder hermano
de comfyui_build_item_icon_workflow / comfyui_build_ui_hud_workflow: mismo patron
(PURO, dict API format) que compone funciones existentes del registry, no reescribe
el grafo.

DISTINTO de item_icon y ui_hud: un icono de estado no es un objeto de inventario
(item_icon) ni un elemento de chrome grande de la interfaz (ui_hud, botones/marcos/
barras). Es un SIMBOLO compacto que se pinta encima del retrato/barra del personaje
para indicar un efecto activo: por eso el prompt empuja a "simple bold symbol,
readable at small size" y el tamano por defecto es menor (256), porque el icono se
mostrara a 16-32 px en el HUD y un simbolo recargado se vuelve ilegible.

Cableado:

    CheckpointLoaderSimple -> [LoraLoader opcional de estilo] -> KSampler
                          -> CLIPTextEncode (prompt scaffold de icono de estado) ...
                          -> 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 icono de estado es un simbolo
SOLIDO con silueta definida; rembg recorta limpio la silueta dejando alpha. La
luma-to-alpha es para translucidos sobre negro (humo/fuego/magia) y aplanaria el
simbolo. 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 todos los iconos de un set (veneno,
escudo, velocidad...) hace que combinen visualmente: es la clave de una barra de
estados coherente, igual que en los iconos de inventario y los elementos del HUD.

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 iconos de estado: un solo simbolo limpio y
# legible, sin escena ni personaje ni texto/marcas que ensucien la silueta
# centrada y recortable. Empuja contra el detalle excesivo que arruina la
# legibilidad cuando el icono se muestra a 16-32 px en el HUD.
_STATUS_NEGATIVE = (
    "blurry, lowres, intricate details, complex, busy background, "
    "cluttered, multiple symbols, detailed scene, landscape, character, "
    "person, face, text, letters, words, watermark, signature, photo, "
    "photorealistic, realistic, 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_ui_hud_workflow:
    el nodo recorta la silueta del simbolo de estado 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_status_effect_icon_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_status_effect_icon_workflow(
    effect: str,
    *,
    ui_style: str = "game status icon, bold symbol, flat",
    checkpoint: str = "IMG_dreamshaper_8.safetensors",
    size: int = 256,
    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 = "status_effect_icon",
) -> dict:
    """Construye el dict (API format) del workflow de un icono de estado / buff-debuff.

    Args:
        effect: nombre del efecto de estado (ej. "poison", "burning", "frozen",
            "shield", "regeneration", "stun", "speed boost", "bleed", "curse").
            Se inserta en un prompt scaffold de icono de estado. No puede estar
            vacio.
        ui_style: descriptor de estilo de UI que mantiene consistentes los iconos
            de un set (ej. "game status icon, bold symbol, flat", "sci-fi HUD
            status, neon glow", "pixel art status icon", "minimal flat status
            icon"). Pasa el MISMO ui_style + checkpoint + (lora) a todos los iconos
            de la barra de estados 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). keyword-only.
        size: lado del cuadrado en px (width = height = size). 256 por defecto:
            son iconos compactos que se muestran a tamano reducido en el HUD.
            keyword-only.
        transparent: si True inyecta Rembg y el PNG sale con alpha (fondo
            recortado). Si False deja el simbolo 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
            iconos de estado (un simbolo simple legible, fondo limpio, sin
            escena/personaje/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 icono de estado ('{effect} status effect
        icon, {ui_style}, simple bold symbol, centered, readable at small size,
        plain background, ...') + LoRA de estilo opcional + Rembg (si transparent).
        Es UN icono; una barra de estados completa -> llamar por effect con el
        mismo ui_style/checkpoint/lora y montar con comfyui_build_grid si se quiere
        un atlas.

    Raises:
        ValueError: si effect 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 effect or not effect.strip():
        raise ValueError(
            "comfyui_build_status_effect_icon_workflow: 'effect' no puede estar vacio"
        )

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

    # Prompt scaffold de icono de estado: simbolo unico, audaz, centrado, legible
    # a tamano reducido, fondo plano, recortable.
    positive = (
        f"{effect.strip()} status effect icon, {ui_style}, simple bold symbol, "
        "centered, readable at small size, plain background, clean, 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_status_effect_icon_workflow(
        "poison",
        ui_style="game status icon, bold symbol, flat, green",
        transparent=True,
        seed=42,
    )
    print(
        json.dumps(
            {
                "nodes": list(wf),
                "classes": sorted({n["class_type"] for n in wf.values()}),
            },
            indent=2,
        )
    )
