"""Tests offline de comfyui_build_parallax_background_workflow (estructura del dict, sin GPU)."""

import copy
import os
import sys

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from ml.comfyui_build_parallax_background_workflow import (  # noqa: E402
    comfyui_build_parallax_background_workflow,
)


def _by_class(wf, cls):
    return [n for n in wf.values() if n["class_type"] == cls]


def _id_of(wf, cls):
    return next(nid for nid, n in wf.items() if n["class_type"] == cls)


def test_golden_background_plus_depth():
    wf = comfyui_build_parallax_background_workflow("forest at dusk, fantasy")
    # Base txt2img presente.
    assert len(_by_class(wf, "CheckpointLoaderSimple")) == 1
    assert len(_by_class(wf, "KSampler")) == 1
    assert len(_by_class(wf, "VAEDecode")) == 1
    # Nodo de profundidad sobre el IMAGE del VAEDecode.
    depths = _by_class(wf, "DepthAnythingV2Preprocessor")
    assert len(depths) == 1
    vae_id = _id_of(wf, "VAEDecode")
    assert depths[0]["inputs"]["image"] == [vae_id, 0]
    assert depths[0]["inputs"]["ckpt_name"] == "depth_anything_v2_vitl.pth"
    # Dos SaveImage: uno para el fondo, otro para el depth map.
    saves = _by_class(wf, "SaveImage")
    assert len(saves) == 2
    depth_id = _id_of(wf, "DepthAnythingV2Preprocessor")
    save_depth = next(s for s in saves if s["inputs"]["images"] == [depth_id, 0])
    assert "depth" in save_depth["inputs"]["filename_prefix"]


def test_edge_scene_style_reflected_in_prompt():
    wf = comfyui_build_parallax_background_workflow(
        "underwater cavern", style="painterly background, no characters"
    )
    texts = [n["inputs"]["text"] for n in _by_class(wf, "CLIPTextEncode")]
    positive = next(t for t in texts if "underwater cavern" in t)
    assert "underwater cavern" in positive
    assert "painterly background" in positive


def test_edge_layers_reflected_in_depth_filename():
    wf = comfyui_build_parallax_background_workflow("desert canyon", layers=5)
    saves = _by_class(wf, "SaveImage")
    depth_save = next(s for s in saves if "depth" in s["inputs"]["filename_prefix"])
    assert "5L" in depth_save["inputs"]["filename_prefix"]


def test_edge_dims_reflected_in_latent():
    wf = comfyui_build_parallax_background_workflow(
        "city skyline", width=1280, height=512
    )
    lat = _by_class(wf, "EmptyLatentImage")[0]
    assert lat["inputs"]["width"] == 1280
    assert lat["inputs"]["height"] == 512


def test_edge_alt_depth_node_no_ckpt():
    # MiDaS no tiene ckpt_name: el builder no debe inyectarlo.
    wf = comfyui_build_parallax_background_workflow(
        "snowy mountains", depth_node="MiDaS-DepthMapPreprocessor"
    )
    midas = _by_class(wf, "MiDaS-DepthMapPreprocessor")
    assert len(midas) == 1
    assert "ckpt_name" not in midas[0]["inputs"]
    assert "resolution" in midas[0]["inputs"]


def test_error_empty_scene():
    try:
        comfyui_build_parallax_background_workflow("")
        assert False
    except ValueError as e:
        assert "scene" in str(e)


def test_error_layers_below_two():
    try:
        comfyui_build_parallax_background_workflow("forest", layers=1)
        assert False
    except ValueError as e:
        assert "layers" in str(e)


def test_purity_deterministic_and_no_global_state():
    a = comfyui_build_parallax_background_workflow("forest", seed=1)
    b = comfyui_build_parallax_background_workflow("forest", seed=1)
    assert a == b
    # Modificar el resultado no afecta a llamadas posteriores.
    snapshot = copy.deepcopy(a)
    a["3"]["inputs"]["seed"] = 999
    c = comfyui_build_parallax_background_workflow("forest", seed=1)
    assert c == snapshot
