"""Tests offline de comfyui_apply_style_preset (traduccion preset -> kwargs, sin GPU)."""

import os
import sys

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


def test_golden_apply_gameboy_to_subject():
    p = comfyui_get_gamedev_style_preset("gameboy")
    ap = comfyui_apply_style_preset(p, "knight character")
    # El subject combina prefijo/sufijo del estilo.
    assert "knight character" in ap["subject"]
    assert "8-bit" in ap["subject"]  # del subject_suffix del gameboy
    # builder_kwargs trae las claves comunes a los builders de sujeto, listas para **spread.
    bk = ap["builder_kwargs"]
    assert set(bk) == {"style", "checkpoint", "lora", "lora_strength", "negative"}
    assert bk["checkpoint"] == "IMG_dreamshaper_8.safetensors"
    assert bk["lora"] is None
    assert "Game Boy" in bk["style"]
    # Recomendaciones y post propagados.
    assert ap["transparent"] is False
    assert ap["post"]["pixelize"]["palette"] == "game-boy"


def test_golden_kwargs_spreadable_into_builder():
    # Los builder_kwargs son exactamente los que aceptan los builders de sujeto:
    # se hace **spread sin TypeError (verifica el contrato con item_icon).
    from ml.comfyui_build_item_icon_workflow import comfyui_build_item_icon_workflow

    p = comfyui_get_gamedev_style_preset("ghibli")
    ap = comfyui_apply_style_preset(p, "magic potion")
    wf = comfyui_build_item_icon_workflow(
        ap["subject"], size=ap["size"], transparent=ap["transparent"], **ap["builder_kwargs"]
    )
    cls = sorted({n["class_type"] for n in wf.values()})
    assert "KSampler" in cls
    # El LoRA watercolor del preset aparece en el grafo.
    loras = [n for n in wf.values() if n["class_type"] == "LoraLoader"]
    assert loras and loras[0]["inputs"]["lora_name"] == "SD15_watercolor_style.safetensors"


def test_edge_style_override():
    p = comfyui_get_gamedev_style_preset("gameboy")
    ap = comfyui_apply_style_preset(p, "tree", style="custom override style")
    assert ap["builder_kwargs"]["style"] == "custom override style"


def test_edge_negative_merged_not_replaced():
    p = comfyui_get_gamedev_style_preset("gameboy")
    ap = comfyui_apply_style_preset(p, "tree", negative="extra unwanted thing")
    neg = ap["builder_kwargs"]["negative"]
    assert "extra unwanted thing" in neg
    assert "photorealistic" in neg  # del negativo del estilo, no se pierde


def test_edge_negative_dedup():
    p = comfyui_get_gamedev_style_preset("gameboy")
    # "photo" ya esta en el negativo del estilo; no debe duplicarse.
    ap = comfyui_apply_style_preset(p, "tree", negative="photo")
    assert ap["builder_kwargs"]["negative"].lower().count("photo,") + \
        ap["builder_kwargs"]["negative"].lower().endswith("photo") <= 2


def test_edge_does_not_mutate_preset():
    p = comfyui_get_gamedev_style_preset("pixel-art-retro")
    before = dict(p)
    ap = comfyui_apply_style_preset(p, "knight")
    ap["post"]["pixelize"]["colors"] = 999  # mutar el resultado
    assert p == before  # el preset original intacto
    assert p["post"]["pixelize"]["colors"] == 16


def test_error_empty_subject():
    p = comfyui_get_gamedev_style_preset("gameboy")
    try:
        comfyui_apply_style_preset(p, "   ")
        assert False, "deberia lanzar ValueError"
    except ValueError as e:
        assert "subject" in str(e)


def test_error_incomplete_preset():
    try:
        comfyui_apply_style_preset({"name": "broken"}, "knight")
        assert False, "deberia lanzar ValueError"
    except ValueError as e:
        assert "incompleto" in str(e) or "faltan" in str(e)
