"""Tests for Debug R4 Bug 2 — Seedance R2V routing predicate.

Verifies that --seedance-refs alone does NOT promote a call to R2V when
--start-frame is also present. The I2V dispatcher supports image refs via
--seedance-refs; routing such calls to R2V silently drops the start frame.

The predicate lives inline in pipeline/tools/dispatch_cli.py::main()
(around line 881; renamed from test_via_steprunner.py in CP-5 Phase 8).
We replicate it here verbatim against a SimpleNamespace to lock the
behavior. If the predicate text changes, update this test in lockstep.
"""

from __future__ import annotations

import sys
from pathlib import Path
from types import SimpleNamespace

_RECOIL_ROOT = Path(__file__).resolve().parents[3]
if str(_RECOIL_ROOT) not in sys.path:
    sys.path.insert(0, str(_RECOIL_ROOT))


def _is_seedance_r2v(args) -> bool:
    """Mirror of the predicate in dispatch_cli.main()."""
    return (
        ("seed" in (args.model or "").lower())
        and (
            args.ref_video
            or args.audio_url
            or (args.seedance_refs and not args.start_frame)
        )
    )


def _mk(model="seedance-2.0", ref_video=None, audio_url=None,
        seedance_refs=None, start_frame=None):
    return SimpleNamespace(
        model=model,
        ref_video=ref_video,
        audio_url=audio_url,
        seedance_refs=seedance_refs,
        start_frame=start_frame,
    )


def test_r2v_when_ref_video_present_no_start_frame():
    assert bool(_is_seedance_r2v(_mk(ref_video="/tmp/v.mp4"))) is True


def test_r2v_when_seedance_refs_only():
    """--seedance-refs alone (no start frame, no ref video) → R2V."""
    assert bool(_is_seedance_r2v(_mk(seedance_refs="sadie,jamie"))) is True


def test_NOT_r2v_when_start_frame_and_seedance_refs():
    """The bug: --seedance-refs + --start-frame must route to I2V, not R2V.

    _dispatch_seedance_i2v supports --seedance-refs as image refs. Promoting
    this combo to R2V drops the start frame on the floor.
    """
    args = _mk(seedance_refs="sadie,jamie", start_frame="/tmp/s.jpg")
    assert bool(_is_seedance_r2v(args)) is False


def test_r2v_when_ref_video_AND_start_frame():
    """--ref-video is an unambiguous R2V signal even with --start-frame."""
    args = _mk(ref_video="/tmp/v.mp4", start_frame="/tmp/s.jpg")
    assert bool(_is_seedance_r2v(args)) is True


def test_NOT_r2v_when_no_signals():
    assert bool(_is_seedance_r2v(_mk())) is False


def test_NOT_r2v_for_non_seedance_model():
    args = _mk(model="kling-2.5", ref_video="/tmp/v.mp4")
    assert bool(_is_seedance_r2v(args)) is False


def test_r2v_when_audio_url_only():
    """--audio-url alone (no ref-video, no start-frame) → R2V via native audio channel."""
    assert bool(_is_seedance_r2v(_mk(audio_url="/tmp/voiceover.mp3"))) is True


def test_predicate_text_in_source():
    """Lock the source predicate to the form the test mirrors. If somebody
    rewrites the inline expression in main(), this test reminds them to
    update the mirror above and re-validate.
    """
    src = (_RECOIL_ROOT / "pipeline" / "tools" / "dispatch_cli.py").read_text()
    # The R4 Bug 2 invariant: --seedance-refs without a start-frame must trigger
    # R2V, but --seedance-refs WITH --start-frame must route to I2V (not R2V) so
    # the start frame is not silently dropped.
    assert "args.seedance_refs and not args.start_frame" in src, (
        "Bug 2 fix predicate missing from dispatch_cli.py. The R4 fix "
        "requires `--seedance-refs and not args.start_frame` so I2V-with-refs "
        "is not silently routed to R2V."
    )
    # --ref-video and --audio-url are both unambiguous R2V signals.
    assert "args.ref_video" in src, "ref_video R2V signal missing from dispatch_cli.py"
    assert "args.audio_url" in src, "audio_url R2V signal missing from dispatch_cli.py"
