import json
from pathlib import Path

from autoshorts.i2v_job_runner import run_i2v_clip_jobs, write_run_report


def _job(job_id="scene_01_seed_101", *, keyframe_path="keyframes/scene_01.png", output_path="clips/scene_01/seed_101.mp4"):
    return {
        "schema_version": "i2v_clip_job.v1",
        "job_id": job_id,
        "video_id": "pilot",
        "scene_id": "scene_01",
        "seed": 101,
        "status": "ready",
        "keyframe_path": keyframe_path,
        "output_path": output_path,
        "remote_image_name": "pilot_scene_01.png",
        "prompt_spec": {
            "i2v_motion_prompt": "Photorealistic video. No text, no logo, no watermark.",
            "negative_prompt": "text, logo, watermark, fake UI text",
            "comfyui": {
                "model": "wan2.2_ti2v_5B_fp16.safetensors",
                "text_encoder": "umt5_xxl_fp8_e4m3fn_scaled.safetensors",
                "vae": "wan2.2_vae.safetensors",
                "resolution": {"width": 416, "height": 736},
                "frames": 61,
                "fps": 12,
                "steps": 16,
                "cfg": 5.0,
            },
        },
    }


class RecordingClient:
    def __init__(self):
        self.calls = []

    def run_i2v_workflow(self, **kwargs):
        self.calls.append(kwargs)
        output_path = kwargs["output_path"]
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_bytes(b"mp4")
        return {"status": "success", "prompt_id": "prompt-1", "output_path": str(output_path)}


def test_runner_skips_jobs_without_keyframes_and_runs_ready_jobs(tmp_path):
    ready_keyframe = tmp_path / "keyframes/scene_01.png"
    ready_keyframe.parent.mkdir(parents=True)
    ready_keyframe.write_bytes(b"png")
    missing_keyframe = tmp_path / "keyframes/scene_02.png"
    package = {
        "schema_version": "i2v_clip_jobs.v1",
        "video": {"id": "pilot"},
        "jobs": [
            _job(keyframe_path=str(ready_keyframe), output_path=str(tmp_path / "clips/scene_01/seed_101.mp4")),
            _job("scene_02_seed_101", keyframe_path=str(missing_keyframe), output_path=str(tmp_path / "clips/scene_02/seed_101.mp4")),
        ],
    }
    client = RecordingClient()

    report = run_i2v_clip_jobs(package, client=client, limit=None, dry_run=False)

    assert report["summary"] == {"total": 2, "succeeded": 1, "skipped": 1, "failed": 0}
    assert len(client.calls) == 1
    assert report["results"][0]["status"] == "success"
    assert report["results"][1]["status"] == "skipped"
    assert report["results"][1]["reason"] == "missing_keyframe"
    assert client.calls[0]["remote_image_name"] == "pilot_scene_01.png"
    assert client.calls[0]["workflow"]["8"]["inputs"]["length"] == 61


def test_runner_dry_run_does_not_call_client_but_reports_ready(tmp_path):
    keyframe = tmp_path / "keyframes/scene_01.png"
    keyframe.parent.mkdir(parents=True)
    keyframe.write_bytes(b"png")
    package = {"schema_version": "i2v_clip_jobs.v1", "video": {"id": "pilot"}, "jobs": [_job(keyframe_path=str(keyframe))]}
    client = RecordingClient()

    report = run_i2v_clip_jobs(package, client=client, limit=1, dry_run=True)

    assert len(client.calls) == 0
    assert report["summary"] == {"total": 1, "succeeded": 0, "skipped": 1, "failed": 0}
    assert report["results"][0]["status"] == "skipped"
    assert report["results"][0]["reason"] == "dry_run_ready"


def test_write_run_report_outputs_json(tmp_path):
    report = {"schema_version": "i2v_run_report.v1", "summary": {"total": 0}, "results": []}

    path = write_run_report(report, tmp_path / "run_report.json")

    assert json.loads(path.read_text(encoding="utf-8"))["schema_version"] == "i2v_run_report.v1"
