"""Test #7 from BUILD_SPEC EP001-render-rootcause-fix.

dispatch._validate_payload raises PayloadValidationError when the
payload contract is violated.
"""

from __future__ import annotations

import pytest

from recoil.pipeline.core.dispatch import (
    PayloadValidationError,
    _validate_payload,
)


# ── Test #7 — dispatch._validate_payload raises on contract violation ──

def test_validate_payload_video_i2v_rejects_legacy_image_key():
    """SYNTHESIS §8 test #7 (variant a).

    A video_i2v payload with the legacy `image` base64 key but no
    `start_frame` raises PayloadValidationError mentioning 'start_frame'.
    """
    payload = {
        "shot_id": "EP001_SH02",
        "prompt": "x",
        "model": "seeddance-2.0",
        "image": "base64-bytes-here",
    }
    with pytest.raises(PayloadValidationError) as exc_info:
        _validate_payload("video_i2v", payload)
    assert "start_frame" in str(exc_info.value)


def test_validate_payload_video_i2v_rejects_missing_file(tmp_path):
    """A video_i2v payload whose start_frame points at a missing file raises."""
    bogus = tmp_path / "nonexistent.png"
    payload = {
        "shot_id": "EP001_SH02",
        "prompt": "x",
        "model": "seeddance-2.0",
        "start_frame": bogus,
    }
    with pytest.raises(PayloadValidationError) as exc_info:
        _validate_payload("video_i2v", payload)
    assert "does not exist" in str(exc_info.value)


def test_validate_payload_video_i2v_accepts_valid_start_frame(tmp_path):
    sf = tmp_path / "start.png"
    sf.write_bytes(b"x")
    payload = {
        "shot_id": "EP001_SH02",
        "prompt": "x",
        "model": "seeddance-2.0",
        "start_frame": sf,
    }
    # No raise.
    _validate_payload("video_i2v", payload)


def test_validate_payload_video_i2v_allows_t2v_no_start_frame():
    """video_i2v modality without start_frame and without legacy image key
    is permitted — that's the t2v path."""
    payload = {
        "shot_id": "EP001_SH50",
        "prompt": "an empty room",
        "model": "seeddance-2.0",
    }
    _validate_payload("video_i2v", payload)


def test_validate_payload_r2v_multi_warns_on_zero_refs(caplog):
    """r2v_multi with zero reference_images logs a WARNING (not hard-block)."""
    import logging
    payload = {
        "shot_id": "EP001_SH33",
        "prompt": "x [0s-5s] wide shot",
        "model": "seeddance-2.0",
        "reference_images": [],
    }
    with caplog.at_level(logging.WARNING, logger="recoil.pipeline.core.dispatch"):
        _validate_payload("r2v_multi", payload)
    assert any("zero reference_images" in r.message for r in caplog.records), (
        f"expected warning not logged; records: {[r.message for r in caplog.records]}"
    )


def test_validate_payload_r2v_multi_silent_with_refs(caplog):
    import logging
    payload = {
        "shot_id": "EP001_SH33",
        "prompt": "x",
        "model": "seeddance-2.0",
        "reference_images": ["/tmp/hero.png"],
    }
    with caplog.at_level(logging.WARNING, logger="recoil.pipeline.core.dispatch"):
        _validate_payload("r2v_multi", payload)
    assert not any("zero reference_images" in r.message for r in caplog.records)
