"""Tests offline para comfyui_extract_recipe_from_png (impura: destila PNG -> receta de skill).

Sin red, sin servidor: prueba los helpers puros de extraccion y el flujo de degradacion a la
`meta` de Civitai cuando el PNG no trae workflow embebido (PNG inexistente -> sin workflow).
"""

import os
import sys

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

from ml.comfyui_extract_recipe_from_png import (
    comfyui_extract_recipe_from_png,
    _slugify,
    _loras_from_prompt,
    _dims_from_prompt,
    _checkpoint_from_prompt,
    _detect_base_workflow,
    _from_civitai_meta,
)


def test_slugify():
    assert _slugify("A Red Apple!", "fb") == "a_red_apple"
    assert _slugify("", "fallback") == "fallback"
    # acota a 6 tokens.
    assert _slugify("one two three four five six seven eight", "fb").count("_") == 5


def test_loras_from_prompt():
    prompt = {"7": {"class_type": "LoraLoader",
                    "inputs": {"lora_name": "style.safetensors",
                               "strength_model": 0.8, "strength_clip": 0.7}}}
    loras = _loras_from_prompt(prompt)
    assert loras == [{"name": "style.safetensors", "strength_model": 0.8, "strength_clip": 0.7}]
    assert _loras_from_prompt({}) == []


def test_dims_y_checkpoint_from_prompt():
    prompt = {
        "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "dream.safetensors"}},
        "5": {"class_type": "EmptyLatentImage", "inputs": {"width": 832, "height": 1216}},
    }
    assert _dims_from_prompt(prompt) == {"width": 832, "height": 1216}
    assert _checkpoint_from_prompt(prompt) == "dream.safetensors"


def test_detect_base_workflow():
    assert _detect_base_workflow({"1": {"class_type": "UNETLoader", "inputs": {}}}) == "flux"
    assert _detect_base_workflow({"1": {"class_type": "CheckpointLoaderSimple", "inputs": {}}}) == "txt2img"


def test_from_civitai_meta():
    meta = {"steps": 25, "sampler": "Euler a", "Size": "832x1216", "seed": 7,
            "cfgScale": 6.5, "Model": "mymodel", "prompt": "a cat", "negativePrompt": "blurry"}
    out = _from_civitai_meta(meta)
    assert out["checkpoint"] == "mymodel"
    assert out["positive"] == "a cat" and out["negative"] == "blurry"
    assert out["params"]["steps"] == 25 and out["params"]["cfg"] == 6.5
    assert out["params"]["width"] == 832 and out["params"]["height"] == 1216


def test_flujo_fallback_civitai_meta(tmp_path):
    # PNG inexistente -> sin workflow embebido; cae a la meta de Civitai (utilizable).
    res = comfyui_extract_recipe_from_png(
        str(tmp_path / "no.png"),
        civitai_meta={"prompt": "a knight", "Model": "dream.safetensors", "steps": 20})
    assert res["ok"] is True
    assert res["has_workflow"] is False
    recipe = res["recipe"]
    assert recipe["checkpoint"] == "dream.safetensors"
    assert recipe["prompt_scaffold"]["positive"] == "a knight"
    assert recipe["provenance"]["source"] == "civitai" and recipe["score_n"] == 0


def test_slug_derivado_del_prompt(tmp_path):
    res = comfyui_extract_recipe_from_png(
        str(tmp_path / "no.png"), civitai_meta={"prompt": "Fire Goblin Warrior"})
    assert res["ok"] is True and res["slug"] == "fire_goblin_warrior"


def test_error_sin_workflow_ni_meta(tmp_path):
    res = comfyui_extract_recipe_from_png(str(tmp_path / "no.png"))
    assert res["ok"] is False and res["recipe"] == {}
    assert "no trae workflow" in res["error"]
