"""Limpia los outputs/previews residuales de los nodos de ComfyUI en la UI via CDP.

ComfyUI cachea los outputs de cada ejecucion en `app.nodeOutputs`, un store
indexado por node_id. La ruta de carga `app.loadApiJson` (la que usa
comfyui_load_workflow_ui) reconstruye el grafo pero NO resetea ese store ni los
previews de los nodos. Cuando un workflow nuevo reusa un node_id que ya existia
en el store, el preview cacheado del workflow anterior se vuelve a pintar sobre
el nodo nuevo, que muchas veces es de otro tipo (ej. una imagen pegada bajo un
`CheckpointLoaderSimple` o un `SaveGLB`).

Esta funcion vacia `app.nodeOutputs` y borra `imgs`/`images` de todos los nodos
vivos del grafo, sin tocar la topologia del grafo (no borra nodos ni links), y
marca el canvas dirty para repintar. Es la version no destructiva de
`app.clean()` (que ademas haria `rootGraph.clear()`).

Funcion impura: hace red (CDP WebSocket) y muta el estado de la UI.
"""

try:  # ejecucion directa del archivo / fn run (browser/ en sys.path[0])
    from cdp_eval import cdp_eval
except ImportError:  # importado como paquete (sys.path = python/functions)
    from browser.cdp_eval import cdp_eval


def comfyui_clear_node_outputs_ui(
    *,
    port: int = 9222,
    server_url_substr: str = "8188",
    timeout_s: float = 15.0,
) -> dict:
    """Limpia previews/outputs residuales de todos los nodos del grafo de ComfyUI.

    Args:
        port: puerto de remote debugging del Chrome diario. Default 9222.
        server_url_substr: substring de la URL de la pestana de ComfyUI (default
            "8188", el puerto del server). Identifica la pestana entre las
            abiertas.
        timeout_s: timeout de la conexion CDP en segundos.

    Returns:
        dict {ok: bool, cleared: bool, error: str, store_cleared: int,
        nodes_touched: int, nodes: int}. ok/cleared True si la limpieza termino
        sin excepcion en la pagina. `store_cleared` es el numero de entradas
        eliminadas de `app.nodeOutputs`; `nodes_touched` los nodos a los que se
        les quito un preview; `nodes` el total de nodos del grafo.
    """
    expr = (
        "(function(){"
        "  if(!window.app){ return {ok:false, cleared:false, error:'window.app no disponible en la pestana'}; }"
        "  try{"
        "    var store=0;"
        "    if(app.nodeOutputs){ for(var k in app.nodeOutputs){ if(Object.prototype.hasOwnProperty.call(app.nodeOutputs,k)){ delete app.nodeOutputs[k]; store++; } } }"
        "    var nodes=(app.graph && app.graph._nodes)? app.graph._nodes : [];"
        "    var touched=0;"
        "    for(var i=0;i<nodes.length;i++){"
        "      var nd=nodes[i];"
        "      if(nd.imgs!==undefined || nd.images!==undefined){ touched++; }"
        "      nd.imgs=undefined;"
        "      nd.images=undefined;"
        "      nd.imageIndex=null;"
        "      nd.overIndex=null;"
        "      if('animatedImages' in nd){ nd.animatedImages=undefined; }"
        "    }"
        "    if(app.graph && app.graph.setDirtyCanvas){ app.graph.setDirtyCanvas(true,true); }"
        "    return {ok:true, cleared:true, error:'', store_cleared:store, nodes_touched:touched, nodes:nodes.length};"
        "  }catch(e){ return {ok:false, cleared:false, error:String(e)}; }"
        "})()"
    )
    r = cdp_eval(
        expr,
        port=port,
        target_url_substr=server_url_substr,
        await_promise=False,
        timeout_s=timeout_s,
    )
    if not r["ok"]:
        return {
            "ok": False,
            "cleared": False,
            "error": r["error"],
            "store_cleared": 0,
            "nodes_touched": 0,
            "nodes": 0,
        }
    val = r["value"] or {}
    return {
        "ok": bool(val.get("cleared")),
        "cleared": bool(val.get("cleared")),
        "error": val.get("error", ""),
        "store_cleared": int(val.get("store_cleared", 0)),
        "nodes_touched": int(val.get("nodes_touched", 0)),
        "nodes": int(val.get("nodes", 0)),
    }


if __name__ == "__main__":
    import json

    print(
        json.dumps(
            comfyui_clear_node_outputs_ui(),
            ensure_ascii=False,
            indent=2,
        )
    )
