"""Tests offline de comfyui_build_seamless_tile_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_seamless_tile_workflow import (  # noqa: E402
    comfyui_build_seamless_tile_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_seamless_inserted():
    wf = comfyui_build_seamless_tile_workflow("seamless grass texture")
    tiles = _by_class(wf, "SeamlessTile")
    assert len(tiles) == 1
    st = tiles[0]
    assert st["inputs"]["tiling"] == "enable"
    assert st["inputs"]["copy_model"] == "Make a copy"
    # KSampler toma el MODEL del SeamlessTile.
    tile_id = _id_of(wf, "SeamlessTile")
    ks = next(n for n in wf.values() if n["class_type"] == "KSampler")
    assert ks["inputs"]["model"] == [tile_id, 0]
    # SeamlessTile.model apunta al checkpoint (no hay LoRA).
    ckpt_id = _id_of(wf, "CheckpointLoaderSimple")
    assert st["inputs"]["model"] == [ckpt_id, 0]
    # CircularVAEDecode reemplaza VAEDecode.
    assert len(_by_class(wf, "CircularVAEDecode")) == 1
    assert len(_by_class(wf, "VAEDecode")) == 0
    cvd = _by_class(wf, "CircularVAEDecode")[0]
    assert cvd["inputs"]["tiling"] == "enable"


def test_edge_x_only():
    wf = comfyui_build_seamless_tile_workflow("brick wall", tiling="x_only")
    assert _by_class(wf, "SeamlessTile")[0]["inputs"]["tiling"] == "x_only"
    assert _by_class(wf, "CircularVAEDecode")[0]["inputs"]["tiling"] == "x_only"


def test_edge_no_circular_vae():
    wf = comfyui_build_seamless_tile_workflow("grass", circular_vae=False)
    assert len(_by_class(wf, "CircularVAEDecode")) == 0
    assert len(_by_class(wf, "VAEDecode")) == 1
    assert len(_by_class(wf, "SeamlessTile")) == 1


def test_edge_material_lora_before_tile():
    wf = comfyui_build_seamless_tile_workflow(
        "stone", material_lora="SD15_detail_tweaker.safetensors", lora_strength=0.7
    )
    loras = _by_class(wf, "LoraLoader")
    assert len(loras) == 1
    lora_id = _id_of(wf, "LoraLoader")
    # SeamlessTile toma el MODEL de la LoRA (no del checkpoint crudo).
    st = _by_class(wf, "SeamlessTile")[0]
    assert st["inputs"]["model"] == [lora_id, 0]


def test_error_empty_prompt():
    try:
        comfyui_build_seamless_tile_workflow("")
        assert False
    except ValueError as e:
        assert "positive" in str(e)


def test_error_bad_tiling():
    try:
        comfyui_build_seamless_tile_workflow("x", tiling="diagonal")
        assert False
    except ValueError as e:
        assert "tiling" in str(e)


def test_error_bad_copy_model():
    try:
        comfyui_build_seamless_tile_workflow("x", copy_model="overwrite")
        assert False
    except ValueError as e:
        assert "copy_model" in str(e)


def test_purity_input_not_mutated():
    from ml.comfyui_build_txt2img_workflow import comfyui_build_txt2img_workflow

    base = comfyui_build_txt2img_workflow("IMG_dreamshaper_8.safetensors", "x")
    snapshot = copy.deepcopy(base)
    # No es la entrada directa, pero verificamos que el builder no muta el resultado de txt2img
    # llamandolo dos veces sin estado compartido.
    a = comfyui_build_seamless_tile_workflow("grass", seed=1)
    b = comfyui_build_seamless_tile_workflow("grass", seed=1)
    assert a == b
    assert base == snapshot
