"""Tests de estructura/determinismo para comfyui_build_directional_sprite_workflow (func pura, 2.5D)."""

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_directional_sprite_workflow import (
    comfyui_build_directional_sprite_workflow,
    directional_sprite_view_order,
)
from _comfyui_wf_assert import assert_api_format, class_types, node_by_ct


def test_sv3d_estructura_y_orbit_default():
    wf = comfyui_build_directional_sprite_workflow("goblin.png", directions=8, model="sv3d")
    assert_api_format(wf)
    cts = class_types(wf)
    for ct in ("LoadImage", "ImageOnlyCheckpointLoader", "SV3D_Conditioning",
               "VideoLinearCFGGuidance", "KSampler", "VAEDecode", "SaveImage"):
        assert ct in cts, f"falta nodo {ct}"
    cond = node_by_ct(wf, "SV3D_Conditioning")["inputs"]
    # video_frames default = directions; size nativa sv3d = 576.
    assert cond["video_frames"] == 8
    assert cond["width"] == 576 and cond["height"] == 576


def test_sv3d_orbit_frames_override():
    wf = comfyui_build_directional_sprite_workflow("g.png", directions=8, orbit_frames=21)
    assert node_by_ct(wf, "SV3D_Conditioning")["inputs"]["video_frames"] == 21


def test_zero123_estructura_y_azimuth():
    wf = comfyui_build_directional_sprite_workflow("g.png", directions=4, model="zero123")
    assert_api_format(wf)
    cts = class_types(wf)
    assert "StableZero123_Conditioning_Batched" in cts
    assert "SV3D_Conditioning" not in cts  # camino distinto al sv3d
    cond = node_by_ct(wf, "StableZero123_Conditioning_Batched")["inputs"]
    # batch = directions; size nativa zero123 = 256; azimuth equiespaciado 360/N.
    assert cond["batch_size"] == 4
    assert cond["width"] == 256 and cond["height"] == 256
    assert cond["azimuth_batch_increment"] == 90.0


def test_cfg_y_ckpt_default_por_modelo():
    sv3d = comfyui_build_directional_sprite_workflow("g.png", model="sv3d")
    z123 = comfyui_build_directional_sprite_workflow("g.png", model="zero123")
    assert node_by_ct(sv3d, "KSampler")["inputs"]["cfg"] == 2.5
    assert node_by_ct(z123, "KSampler")["inputs"]["cfg"] == 4.0
    assert node_by_ct(sv3d, "ImageOnlyCheckpointLoader")["inputs"]["ckpt_name"] == "3D_sv3d_p.safetensors"
    assert node_by_ct(z123, "ImageOnlyCheckpointLoader")["inputs"]["ckpt_name"] == "3D_stable_zero123.ckpt"


def test_elevation_y_seed_reflejados():
    wf = comfyui_build_directional_sprite_workflow("g.png", model="sv3d", elevation=15.0, seed=42)
    assert node_by_ct(wf, "SV3D_Conditioning")["inputs"]["elevation"] == 15.0
    assert node_by_ct(wf, "KSampler")["inputs"]["seed"] == 42


def test_view_order_helper():
    assert directional_sprite_view_order(8) == ["S", "SE", "E", "NE", "N", "NW", "W", "SW"]
    assert directional_sprite_view_order(4) == ["S", "E", "N", "W"]
    # N no canonico -> etiquetas por azimuth.
    assert directional_sprite_view_order(6) == ["az0", "az60", "az120", "az180", "az240", "az300"]


def test_errores():
    with pytest.raises(ValueError):
        comfyui_build_directional_sprite_workflow("")
    with pytest.raises(ValueError):
        comfyui_build_directional_sprite_workflow("g.png", model="turbo")
    with pytest.raises(ValueError):
        comfyui_build_directional_sprite_workflow("g.png", directions=0)


def test_determinista():
    a = comfyui_build_directional_sprite_workflow("g.png", directions=8, seed=7, elevation=15.0)
    b = comfyui_build_directional_sprite_workflow("g.png", directions=8, seed=7, elevation=15.0)
    assert a == b
