"""Construye el workflow ComfyUI de UN overlay de clima a pantalla completa (API format).

Un weather overlay es una CAPA de atmosfera/clima que cubre TODA la pantalla y se
superpone sobre la escena del juego con un blend mode del motor: lluvia, niebla,
nieve, rayos de sol (god rays), polvo en suspension, viñeta de tormenta. NO es un
sujeto centrado ni un efecto puntual: es una pelicula de cobertura uniforme de borde
a borde que tiñe/anima toda la vista del jugador. Por eso se genera APAISADA a
resolucion de pantalla (16:9, 1024x576 por defecto), no cuadrada.

Dos modos segun como se vaya a componer en el motor:

- `on_black=True` (defecto): la capa se genera sobre fondo NEGRO puro, con las
  particulas/estrias del clima BRILLANTES sobre negro (estrias de lluvia, copos de
  nieve, haces de luz, motas de polvo). El PNG resultante esta pensado para pasar por
  `comfyui_matting_luma_to_alpha` (brillante -> opaco, negro -> transparente) y
  blendearse con additive/screen en el motor: el negro desaparece y solo el clima
  brilla encima de la escena. Conserva el degradado/falloff que un matting binario
  (rembg) destruiria.
- `on_black=False`: la capa se genera como una pelicula TRANSLUCIDA semi-transparente
  (niebla densa, tinte de tormenta, bruma) lista para blendearse con multiply/overlay
  o un alpha global bajo. Util para climas que oscurecen/tiñen toda la vista en vez de
  añadir particulas brillantes.

Es el builder hermano de comfyui_build_decal_overlay_workflow /
comfyui_build_particle_texture_workflow / comfyui_build_vfx_spritesheet_workflow:
mismo patron PURO (dict API format) que compone funciones existentes del registry, no
reescribe el grafo. A diferencia de los builders de sprite/prop/item, este NO inyecta
Rembg: el matting de una capa de clima es luma-to-alpha (post-proceso de disco) o un
alpha global del motor, no un nodo del workflow.

Diferencia con sus hermanos (NO confundir):
  - comfyui_build_vfx_spritesheet_workflow: una SECUENCIA animada de N frames de UN
    efecto puntual (una explosion, una llamarada) via AnimateDiff. El weather overlay
    es UNA capa estatica de cobertura total (el motor la anima por scroll/loop/shader).
  - comfyui_build_decal_overlay_workflow: una mancha LOCALIZADA y recortable (sangre,
    grieta) que se pega en un punto de una superficie. El weather overlay cubre la
    pantalla ENTERA de borde a borde, no es una mancha centrada.

Cableado:

    CheckpointLoaderSimple -> [LoraLoader opcional de estilo] -> KSampler
                          -> CLIPTextEncode (prompt scaffold de capa full-screen) ...
                          -> VAEDecode -> SaveImage  (capa de clima apaisada)

Compone:
  - comfyui_build_txt2img_workflow  -> base txt2img apaisada (16:9)
  - comfyui_inject_lora             -> LoRA de estilo opcional

Pipeline despues de generar (no en este builder):
  comfyui_submit_workflow -> comfyui_wait_result -> comfyui_fetch_output_image
  -> comfyui_matting_luma_to_alpha (con on_black=True)  -> PNG RGBA para blend aditivo

class_types/inputs verificados contra /object_info del servidor (8GB lowvram):
CheckpointLoaderSimple, CLIPTextEncode, EmptyLatentImage, KSampler, VAEDecode,
SaveImage, LoraLoader.

Funcion pura: sin red, sin I/O. Determinista para los mismos argumentos.
"""
from __future__ import annotations

import os
import sys

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

# Negativo comun a cualquier capa de clima full-screen: queremos COBERTURA uniforme de
# borde a borde, SIN un sujeto/objeto solido, personaje, edificio, escena o horizonte
# que rompan la capa atmosferica; sin profundidad/marco/borde que delaten una
# composicion en vez de una pelicula de cobertura.
_WEATHER_NEGATIVE_COMMON = (
    "solid object, single subject, centered object, foreground object, "
    "character, person, creature, building, vehicle, landscape scene, "
    "horizon line, depth of field, perspective, vignette frame, frame, border, "
    "drop shadow, text, watermark, signature, logo, "
    "blurry, low quality, jpeg artifacts"
)

# Refuerzo de fondo cuando on_black=True: el fondo DEBE quedar NEGRO plano para que el
# luma-to-alpha mapee la luminancia a alpha y conserve el falloff de las particulas/
# estrias. Sin esto el modelo puede pintar una escena/cielo de fondo que arruina el
# alpha. Rechaza explicitamente fondos de otro color/texturizados.
_WEATHER_BG_NEG_ON_BLACK = (
    "gray background, white background, blue sky background, textured background, "
    "busy background, background scenery, background pattern, gradient background"
)


def comfyui_build_weather_overlay_workflow(
    weather: str,
    *,
    on_black: bool = True,
    style: str = "weather overlay, atmospheric",
    checkpoint: str = "IMG_dreamshaper_8.safetensors",
    width: int = 1024,
    height: int = 576,
    seed: int = 0,
    lora: str | None = None,
    lora_strength: float = 1.0,
    negative: str | None = None,
    steps: int = 28,
    cfg: float = 7.0,
    sampler_name: str = "dpmpp_2m",
    scheduler: str = "karras",
    filename_prefix: str = "weather_overlay",
) -> dict:
    """Construye el dict (API format) del workflow de UNA capa de clima full-screen.

    Args:
        weather: descripcion del clima/atmosfera a generar como capa (ej. "heavy
            rain", "thick fog", "falling snow", "god rays", "sun shafts", "dust
            haze", "storm vignette", "sandstorm", "ash fall", "blizzard"). Se
            inserta en un prompt scaffold de capa de cobertura total. No puede
            estar vacio.
        on_black: si True (defecto) la capa se genera sobre fondo NEGRO puro con el
            clima BRILLANTE encima (estrias de lluvia, copos, haces de luz, motas),
            pensada para extraer alpha por luminancia con
            comfyui_matting_luma_to_alpha y blendear additive/screen en el motor
            (el negro desaparece, el clima brilla sobre la escena). Si False la capa
            se genera como pelicula TRANSLUCIDA semi-transparente (niebla densa,
            tinte de tormenta, bruma) para blend multiply/overlay o alpha global.
            keyword-only.
        style: descriptor de estilo de la capa (ej. "weather overlay, atmospheric",
            "stylized rain, painterly", "photoreal fog", "anime sun rays"). Pasa el
            MISMO style + checkpoint + (lora) a todas las capas de un set para
            coherencia visual. keyword-only.
        checkpoint: checkpoint del servidor. 'IMG_dreamshaper_8.safetensors' (SD1.5,
            holgado en 8GB lowvram) por defecto; 'IMG_juggernaut_xl_v11.safetensors'
            para SDXL (mas VRAM, subir width/height a 1344x768). keyword-only.
        width: ancho de la capa en px (multiplo de 8). 1024 por defecto (16:9 con
            height 576: resolucion de pantalla apaisada). keyword-only.
        height: alto de la capa en px (multiplo de 8). 576 por defecto. keyword-only.
        seed: semilla del KSampler. Misma seed + mismos weather/style -> misma capa;
            variar seed da variantes del mismo tipo de clima. keyword-only.
        lora: LoRA de estilo opcional en models/loras. None = sin LoRA. keyword-only.
        lora_strength: fuerza del LoRA sobre model y clip. Se clampa a [0.0, 2.0].
            keyword-only.
        negative: prompt negativo. None usa el negativo por defecto pensado para una
            capa de cobertura total (sin sujeto/objeto/escena/profundidad/marco que
            rompan la pelicula atmosferica) MAS, si on_black=True, el refuerzo de
            fondo negro plano. keyword-only.
        steps, cfg, sampler_name, scheduler, filename_prefix: parametros de
            generacion. keyword-only.

    Returns:
        dict en API format listo para comfyui_submit_workflow: txt2img base apaisada
        (16:9) con prompt scaffold de capa de clima ('{weather} overlay, {style},
        full screen atmospheric layer, <particles/streaks on pure black background |
        translucent layer>, seamless coverage, game VFX, ...') + LoRA de estilo
        opcional. NO lleva Rembg: con on_black=True el PNG resultante se convierte a
        RGBA con comfyui_matting_luma_to_alpha (luma=alpha) en un paso posterior para
        blend aditivo. UNA capa; variar seed da variantes del mismo clima.

    Raises:
        ValueError: si weather esta vacio.
    """
    from ml.comfyui_build_txt2img_workflow import comfyui_build_txt2img_workflow

    if not weather or not weather.strip():
        raise ValueError(
            "comfyui_build_weather_overlay_workflow: 'weather' no puede estar vacio"
        )

    weather = weather.strip()
    lora_strength = max(0.0, min(2.0, float(lora_strength)))
    if negative is None:
        if on_black:
            neg = f"{_WEATHER_NEGATIVE_COMMON}, {_WEATHER_BG_NEG_ON_BLACK}"
        else:
            neg = _WEATHER_NEGATIVE_COMMON
    else:
        neg = negative

    # Modo de composicion: sobre negro puro (particulas/estrias brillantes -> luma->alpha
    # additive) o pelicula translucida semi-transparente. El segmento literal del scaffold
    # ('particles/streaks on pure black background' | 'translucent layer') marca la
    # intencion para el motor.
    if on_black:
        layer = (
            "particles and streaks on a solid pure black background, "
            "bright weather elements over flat pure black, glowing on black backdrop"
        )
    else:
        layer = (
            "translucent layer, semi-transparent atmospheric film, "
            "soft alpha blend over the scene"
        )

    # Prompt scaffold de capa de clima full-screen: cobertura UNIFORME de borde a borde
    # (no un sujeto centrado), apaisada a resolucion de pantalla, lista como overlay para
    # blendear en el motor. Se diferencia de un decal (mancha localizada) y de un
    # spritesheet (secuencia animada): aqui es UNA pelicula de cobertura total.
    positive = (
        f"{weather} overlay, {style}, full screen atmospheric layer, "
        f"{layer}, seamless full screen coverage, edge to edge, uniform across frame, "
        "game VFX, weather effect, high detail"
    )

    wf = comfyui_build_txt2img_workflow(
        checkpoint,
        positive,
        neg,
        steps=steps,
        cfg=cfg,
        width=width,
        height=height,
        seed=seed,
        sampler_name=sampler_name,
        scheduler=scheduler,
        filename_prefix=filename_prefix,
    )

    if lora:
        from ml.comfyui_inject_lora import comfyui_inject_lora

        wf = comfyui_inject_lora(
            wf, lora, strength_model=lora_strength, strength_clip=lora_strength
        )

    return wf


if __name__ == "__main__":
    import json

    wf = comfyui_build_weather_overlay_workflow(
        "heavy rain",
        on_black=True,
        style="weather overlay, atmospheric",
        seed=7,
    )
    print(
        json.dumps(
            {
                "nodes": list(wf),
                "classes": sorted({n["class_type"] for n in wf.values()}),
            },
            indent=2,
        )
    )
