"""genconfig_to_sdcpp_args — convierte GenerationConfig a args CLI para stable-diffusion.cpp."""

from __future__ import annotations

import sys
import os

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

from generation_config import GenerationConfig

# Mapa de SamplerName (dominio ml) a flags de sd-cli (stable-diffusion.cpp).
# Referencia: https://github.com/leejet/stable-diffusion.cpp#usage
_SAMPLER_MAP: dict[str, str] = {
    "euler":      "euler",
    "euler_a":    "euler_a",
    "dpm++2m":    "dpmpp2m",
    "dpm++2m_v2": "dpmpp2mv2",
    "heun":       "heun",
    "dpm2":       "dpm2",
    "lcm":        "lcm",
}


def genconfig_to_sdcpp_args(cfg: GenerationConfig) -> list[str]:
    """Convierte un GenerationConfig a la lista de args CLI para stable-diffusion.cpp.

    Genera los argumentos necesarios para invocar `sd` (sd-cli) de
    stable-diffusion.cpp. El mapa _SAMPLER_MAP traduce los SamplerName
    canonicos del dominio ml a los identificadores de sdcpp.

    Los LoRAs se pasan como repeticiones del par --lora "path:weight".
    Si un LoRA no tiene path definido, se omite silenciosamente.

    El modelo se resuelve priorizando cfg.model.path; si es None usa cfg.model.name
    (puede ser un nombre de hub o un path relativo segun la configuracion de sdcpp).

    Args:
        cfg: Parametros de generacion validados. Debe ser instancia de GenerationConfig.

    Returns:
        Lista de strings con los argumentos CLI en el orden esperado por sd-cli.
        Listo para: subprocess.run(["sd"] + args, ...) o similar.
    """
    model_path = cfg.model.path if cfg.model.path else cfg.model.name
    sampler_flag = _SAMPLER_MAP.get(cfg.sampler, cfg.sampler)

    args: list[str] = [
        "--prompt",          cfg.prompt,
        "--negative-prompt", cfg.negative_prompt or "",
        "--seed",            str(cfg.seed),
        "--steps",           str(cfg.steps),
        "--cfg-scale",       str(cfg.cfg_scale),
        "--sampling-method", sampler_flag,
        "-W",                str(cfg.width),
        "-H",                str(cfg.height),
        "-m",                model_path,
    ]

    # Aplanar LoRAs: cada uno genera un par --lora "path:weight"
    for lora in cfg.loras:
        if lora.path:
            args += ["--lora", f"{lora.path}:{lora.weight}"]

    return args
