"""Original read-only graph trace; no model imports, downloads or execution."""

import argparse
import json
import sys
from pathlib import Path


def review(graph):
    if (
        not isinstance(graph, dict)
        or not isinstance(graph.get("nodes"), list)
        or not isinstance(graph.get("links"), list)
    ):
        raise ValueError("Use a UI export with nodes and tuple-link arrays")
    if len(graph["nodes"]) > 1000 or len(graph["links"]) > 5000:
        raise ValueError("Use at most 1000 nodes and 5000 links")
    nodes = {
        n["id"]: n for n in graph["nodes"] if isinstance(n, dict) and isinstance(n.get("id"), int)
    }
    links = {
        link[0]: link
        for link in graph["links"]
        if isinstance(link, list) and len(link) >= 6 and isinstance(link[0], int)
    }

    def source(link_id):
        visited = set()
        while link_id is not None and link_id not in visited:
            visited.add(link_id)
            edge = links.get(link_id)
            if not edge:
                return None
            node = nodes.get(edge[1])
            if not node:
                return None
            if node.get("type") != "Reroute":
                return {
                    "node_id": node["id"],
                    "node_type": node.get("type"),
                    "output_slot": edge[2],
                }
            inputs = node.get("inputs", [])
            link_id = inputs[0].get("link") if inputs and isinstance(inputs[0], dict) else None
        return None

    generators = []
    for node in nodes.values():
        if node.get("type") != "HunyuanVideoFoleyGeneratorAdvanced":
            continue
        ports = {
            port.get("name"): port.get("link")
            for port in node.get("inputs", [])
            if isinstance(port, dict)
        }
        generators.append(
            {
                "node_id": node["id"],
                "compiled_input_has_reference": ports.get("compiled_model") is not None,
                "compiled_input_source": source(ports.get("compiled_model")),
                "video_input_source": source(ports.get("video")),
                "images_input_source": source(ports.get("images")),
                "fps_input_source": source(ports.get("fps")),
            }
        )
    return {
        "scope": "Read-only tuple-link trace through Reroute nodes; not full graph, port-type, installed-node or runtime validation",
        "node_count": len(graph["nodes"]),
        "link_count": len(graph["links"]),
        "model_execution_tested": False,
        "generators": generators,
    }


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("workflow", type=Path)
    args = parser.parse_args()
    try:
        if args.workflow.stat().st_size > 1024 * 1024:
            raise ValueError("Choose a UI workflow JSON up to 1 MB")
        print(json.dumps(review(json.loads(args.workflow.read_text())), indent=2))
    except (OSError, ValueError, TypeError, KeyError) as error:
        print(f"Could not trace this graph: {error}", file=sys.stderr)
        raise SystemExit(2) from None
