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

import os
import sys

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


def _classes(wf):
    return sorted({n["class_type"] for n in wf.values()})


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 _pos_with(wf, needle):
    return next(
        n for n in wf.values()
        if n["class_type"] == "CLIPTextEncode" and needle in n["inputs"]["text"]
    )


def _neg(wf):
    return next(
        n["inputs"]["text"] for n in wf.values()
        if n["class_type"] == "CLIPTextEncode" and "solid object" in n["inputs"]["text"]
    )


def test_golden_weather_on_black_recipe():
    wf = comfyui_build_weather_overlay_workflow("heavy rain", on_black=True, seed=7)
    cls = _classes(wf)
    # Cadena base txt2img pura: NO lleva Rembg (el matting es luma-to-alpha aparte).
    assert "CheckpointLoaderSimple" in cls
    assert "KSampler" in cls
    assert "VAEDecode" in cls
    assert "SaveImage" in cls
    assert "Image Rembg (Remove Background)" not in cls
    # El clima + la cobertura full-screen + el fondo negro (apto luma->alpha) aparecen.
    pos = _pos_with(wf, "heavy rain")
    txt = pos["inputs"]["text"]
    assert "full screen atmospheric layer" in txt
    assert "solid pure black background" in txt
    assert "seamless full screen coverage" in txt
    assert "game VFX" in txt
    # SaveImage toma del VAEDecode directamente (sin recorte intermedio).
    vd_id = _id_of(wf, "VAEDecode")
    save = next(n for n in wf.values() if n["class_type"] == "SaveImage")
    assert save["inputs"]["images"] == [vd_id, 0]


def test_golden_landscape_dims_default():
    # Apaisado 16:9 a resolucion de pantalla por defecto (NO cuadrado: es una capa
    # full-screen, no un sujeto centrado).
    wf = comfyui_build_weather_overlay_workflow("falling snow")
    latent = _by_class(wf, "EmptyLatentImage")[0]["inputs"]
    assert latent["width"] == 1024
    assert latent["height"] == 576
    assert latent["width"] > latent["height"]  # apaisado


def test_edge_on_black_toggles_layer_mode():
    # on_black=True -> particulas/estrias sobre negro plano (luma->alpha additive) +
    # el negativo refuerza fondo negro (rechaza gris/blanco/cielo).
    wf_black = comfyui_build_weather_overlay_workflow("god rays", on_black=True)
    pos_black = _pos_with(wf_black, "god rays")["inputs"]["text"]
    assert "solid pure black background" in pos_black
    assert "translucent layer" not in pos_black
    assert "white background" in _neg(wf_black)  # refuerzo de fondo negro plano
    # on_black=False -> pelicula translucida semi-transparente (sin refuerzo de fondo).
    wf_film = comfyui_build_weather_overlay_workflow("god rays", on_black=False)
    pos_film = _pos_with(wf_film, "god rays")["inputs"]["text"]
    assert "translucent layer" in pos_film
    assert "solid pure black background" not in pos_film
    assert "white background" not in _neg(wf_film)


def test_edge_weather_reflected():
    for w in ["thick fog", "dust haze", "storm vignette"]:
        wf = comfyui_build_weather_overlay_workflow(w)
        pos = _pos_with(wf, w)
        assert w in pos["inputs"]["text"]


def test_edge_style_in_prompt():
    wf = comfyui_build_weather_overlay_workflow(
        "heavy rain", style="stylized rain, painterly"
    )
    pos = _pos_with(wf, "heavy rain")
    assert "stylized rain, painterly" in pos["inputs"]["text"]


def test_edge_dims_reflected():
    wf = comfyui_build_weather_overlay_workflow("blizzard", width=1344, height=768)
    latent = _by_class(wf, "EmptyLatentImage")[0]["inputs"]
    assert latent["width"] == 1344
    assert latent["height"] == 768


def test_edge_negative_isolates_layer():
    # El negativo por defecto rechaza sujeto/objeto/escena/horizonte/profundidad/marco
    # que romperian la pelicula de cobertura total.
    wf = comfyui_build_weather_overlay_workflow("sandstorm")
    neg = _neg(wf)
    assert "solid object" in neg
    assert "landscape scene" in neg
    assert "horizon line" in neg
    assert "frame" in neg
    assert "gray background" in neg  # fondo negro plano forzado (on_black por defecto)


def test_edge_lora_reflected():
    wf = comfyui_build_weather_overlay_workflow(
        "falling snow", lora="SD15_vfx.safetensors", lora_strength=0.8
    )
    loras = _by_class(wf, "LoraLoader")
    assert len(loras) == 1
    assert loras[0]["inputs"]["lora_name"] == "SD15_vfx.safetensors"
    assert loras[0]["inputs"]["strength_model"] == 0.8


def test_error_empty_weather():
    try:
        comfyui_build_weather_overlay_workflow("  ")
        assert False
    except ValueError as e:
        assert "weather" in str(e)


def test_determinism():
    a = comfyui_build_weather_overlay_workflow(
        "heavy rain", on_black=True, lora="SD15_vfx.safetensors", seed=7
    )
    b = comfyui_build_weather_overlay_workflow(
        "heavy rain", on_black=True, lora="SD15_vfx.safetensors", seed=7
    )
    assert a == b
