"""Tests de estructura/determinismo para comfyui_build_sprite_from_sketch_workflow (func pura, ControlNet)."""

import os
import sys

import pytest

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

from ml.comfyui_build_sprite_from_sketch_workflow import comfyui_build_sprite_from_sketch_workflow
from _comfyui_wf_assert import assert_api_format, class_types, node_by_ct


def test_estructura_txt2img_mas_controlnet():
    # txt2img (EmptyLatentImage, denoise alto) guiado por ControlNet atado al boceto.
    wf = comfyui_build_sprite_from_sketch_workflow("sketch.png", "armored knight")
    assert_api_format(wf)
    cts = class_types(wf)
    for ct in ("CheckpointLoaderSimple", "EmptyLatentImage", "CLIPTextEncode", "KSampler",
               "VAEDecode", "SaveImage", "LoadImage", "ControlNetLoader", "ControlNetApply"):
        assert ct in cts, f"falta nodo {ct}"


def test_lineart_default_preprocesador_y_modelo():
    wf = comfyui_build_sprite_from_sketch_workflow("s.png", "knight", control_type="lineart")
    assert "LineArtPreprocessor" in class_types(wf)
    assert node_by_ct(wf, "ControlNetLoader")["inputs"]["control_net_name"] == \
        "control_v11p_sd15_lineart_fp16.safetensors"
    # el ControlNetApply consume el mapa de lineas del preprocesador, no el LoadImage directo.
    pre_id = next(nid for nid, n in wf.items() if n["class_type"].endswith("Preprocessor"))
    assert node_by_ct(wf, "ControlNetApply")["inputs"]["image"] == [pre_id, 0]


def test_canny_preprocesador_y_modelo():
    wf = comfyui_build_sprite_from_sketch_workflow("s.png", "chest", control_type="canny")
    assert "CannyEdgePreprocessor" in class_types(wf)
    assert node_by_ct(wf, "ControlNetLoader")["inputs"]["control_net_name"] == \
        "control_v11p_sd15_canny_fp16.safetensors"


def test_preprocess_false_pasa_boceto_directo():
    wf = comfyui_build_sprite_from_sketch_workflow("s.png", "k", preprocess=False)
    assert not any(n["class_type"].endswith("Preprocessor") for n in wf.values())
    load_id = next(nid for nid, n in wf.items() if n["class_type"] == "LoadImage")
    assert node_by_ct(wf, "ControlNetApply")["inputs"]["image"] == [load_id, 0]


def test_controlnet_name_override_y_strength():
    wf = comfyui_build_sprite_from_sketch_workflow(
        "s.png", "k", control_type="lineart",
        controlnet_name="control_v11p_sd15_canny_fp16.safetensors", strength=0.65)
    assert node_by_ct(wf, "ControlNetLoader")["inputs"]["control_net_name"] == \
        "control_v11p_sd15_canny_fp16.safetensors"
    assert node_by_ct(wf, "ControlNetApply")["inputs"]["strength"] == 0.65


def test_strength_se_clampa():
    wf = comfyui_build_sprite_from_sketch_workflow("s.png", "k", strength=5.0)
    assert node_by_ct(wf, "ControlNetApply")["inputs"]["strength"] == 2.0


def test_lora_inyecta():
    assert "LoraLoader" in class_types(
        comfyui_build_sprite_from_sketch_workflow("s.png", "k", lora="x.safetensors"))


def test_errores():
    with pytest.raises(ValueError):
        comfyui_build_sprite_from_sketch_workflow("", "k")
    with pytest.raises(ValueError):
        comfyui_build_sprite_from_sketch_workflow("s.png", "")
    with pytest.raises(ValueError):
        comfyui_build_sprite_from_sketch_workflow("s.png", "k", control_type="depth")


def test_determinista():
    a = comfyui_build_sprite_from_sketch_workflow("s.png", "knight", seed=7, strength=0.8)
    b = comfyui_build_sprite_from_sketch_workflow("s.png", "knight", seed=7, strength=0.8)
    assert a == b
