"""Build executable Wan2.2 I2V clip jobs from prompt plans."""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any


NATIVE_WAN22_CLIENT_ID = "autoshorts-i2v"


def _video_slug(prompt_plan: dict[str, Any]) -> str:
    return prompt_plan["video"]["id"]


def _scene_keyframe_path(keyframe_root: Path, video_slug: str, scene_id: str) -> Path:
    return keyframe_root / video_slug / f"{scene_id}.png"


def _scene_output_path(output_root: Path, video_slug: str, scene_id: str, seed: int) -> Path:
    return output_root / video_slug / scene_id / f"seed_{seed}.mp4"


def build_i2v_clip_jobs(
    prompt_plan: dict[str, Any],
    keyframe_root: Path,
    output_root: Path,
    seeds: list[int],
) -> list[dict[str, Any]]:
    """Create seeded clip jobs for each Wan2.2 I2V scene."""
    video_slug = _video_slug(prompt_plan)
    jobs: list[dict[str, Any]] = []
    for scene in prompt_plan["scenes"]:
        for seed in seeds:
            scene_id = scene["scene_id"]
            keyframe_path = _scene_keyframe_path(keyframe_root, video_slug, scene_id)
            output_path = _scene_output_path(output_root, video_slug, scene_id, seed)
            jobs.append(
                {
                    "schema_version": "i2v_clip_job.v1",
                    "job_id": f"{scene_id}_seed_{seed}",
                    "video_id": video_slug,
                    "scene_id": scene_id,
                    "purpose": scene["purpose"],
                    "seed": seed,
                    "status": "ready" if keyframe_path.exists() else "needs_keyframe",
                    "keyframe_path": str(keyframe_path),
                    "output_path": str(output_path),
                    "remote_image_name": f"{video_slug}_{scene_id}.png",
                    "prompt_spec": scene,
                    "review": {
                        "human_review_required": True,
                        "criteria": [
                            "subject clear in first 0.5s",
                            "motion supports retention beat",
                            "no baked text/logos/watermarks",
                            "no distracting deformation/flicker",
                            "clean space remains for captions",
                        ],
                    },
                }
            )
    return jobs


def _filename_prefix(job: dict[str, Any]) -> str:
    return f"autoshorts_{job['video_id']}_{job['scene_id']}_seed_{job['seed']}"


def build_native_wan22_i2v_workflow(job: dict[str, Any], uploaded_image_name: str) -> dict[str, Any]:
    """Build an API-format native ComfyUI Wan2.2 I2V workflow for a clip job."""
    spec = job["prompt_spec"]
    comfy = spec["comfyui"]
    width = int(comfy["resolution"]["width"])
    height = int(comfy["resolution"]["height"])
    return {
        "1": {
            "class_type": "UNETLoader",
            "inputs": {"unet_name": comfy["model"], "weight_dtype": "default"},
        },
        "2": {
            "class_type": "CLIPLoader",
            "inputs": {"clip_name": comfy["text_encoder"], "type": "wan", "device": "default"},
        },
        "3": {
            "class_type": "CLIPTextEncode",
            "inputs": {"clip": ["2", 0], "text": spec["i2v_motion_prompt"]},
        },
        "4": {
            "class_type": "CLIPTextEncode",
            "inputs": {"clip": ["2", 0], "text": spec["negative_prompt"]},
        },
        "5": {"class_type": "VAELoader", "inputs": {"vae_name": comfy["vae"]}},
        "6": {"class_type": "LoadImage", "inputs": {"image": uploaded_image_name}},
        "7": {
            "class_type": "ImageScale",
            "inputs": {
                "image": ["6", 0],
                "upscale_method": "lanczos",
                "width": width,
                "height": height,
                "crop": "disabled",
            },
        },
        "8": {
            "class_type": "Wan22ImageToVideoLatent",
            "inputs": {
                "vae": ["5", 0],
                "width": width,
                "height": height,
                "length": int(comfy["frames"]),
                "batch_size": 1,
                "start_image": ["7", 0],
            },
        },
        "9": {
            "class_type": "KSampler",
            "inputs": {
                "model": ["1", 0],
                "seed": int(job["seed"]),
                "steps": int(comfy["steps"]),
                "cfg": float(comfy["cfg"]),
                "sampler_name": "uni_pc",
                "scheduler": "simple",
                "positive": ["3", 0],
                "negative": ["4", 0],
                "latent_image": ["8", 0],
                "denoise": 1.0,
            },
        },
        "10": {"class_type": "VAEDecode", "inputs": {"samples": ["9", 0], "vae": ["5", 0]}},
        "11": {"class_type": "CreateVideo", "inputs": {"images": ["10", 0], "fps": float(comfy["fps"])}},
        "12": {
            "class_type": "SaveVideo",
            "inputs": {
                "video": ["11", 0],
                "filename_prefix": _filename_prefix(job),
                "format": "mp4",
                "codec": "h264",
            },
        },
    }


def write_i2v_clip_jobs(
    prompt_plan: dict[str, Any],
    output_file: Path,
    keyframe_root: Path,
    generated_clip_root: Path,
    seeds: list[int],
) -> Path:
    """Write a clip-job package JSON."""
    output_file.parent.mkdir(parents=True, exist_ok=True)
    package = {
        "schema_version": "i2v_clip_jobs.v1",
        "video": prompt_plan["video"],
        "strategy": prompt_plan["strategy"],
        "keyframe_root": str(keyframe_root),
        "generated_clip_root": str(generated_clip_root),
        "jobs": build_i2v_clip_jobs(prompt_plan, keyframe_root, generated_clip_root, seeds),
    }
    output_file.write_text(json.dumps(package, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
    return output_file
