# recoil/pipeline/tests/test_payload_builder.py
"""Payload builder applies declarative model rules from the extended profile."""

from pathlib import Path
from types import SimpleNamespace

import pytest


@pytest.fixture
def fake_refs():
    return [
        SimpleNamespace(role="character", path=Path("hero.jpg")),
        SimpleNamespace(role="character", path=Path("front.jpg")),
        SimpleNamespace(role="character", path=Path("profile.jpg")),
        SimpleNamespace(role="character", path=Path("back.jpg")),
        SimpleNamespace(role="character", path=Path("three_quarter.jpg")),
        SimpleNamespace(role="environment", path=Path("bar.jpg")),
    ]


def test_build_payload_caps_character_refs_at_effective_max(fake_refs):
    from recoil.pipeline._lib.payload_builder import build_payload
    shot = SimpleNamespace(shot_id="EP001_SH01", run_id=None)
    prompt = "Sadie stands in a bar"
    result = build_payload(shot=shot, refs=fake_refs, prompt=prompt, model_id="gemini-3-pro-image-preview")
    char_refs = [r for r in result["refs"] if r.role == "character"]
    assert len(char_refs) <= 5  # API hard limit


def test_build_payload_strips_sd_weighting_for_natural_language_models(fake_refs):
    from recoil.pipeline._lib.payload_builder import build_payload
    shot = SimpleNamespace(shot_id="EP001_SH01", run_id=None)
    prompt = "Sadie (very young:1.5) stands in a bar"
    result = build_payload(shot=shot, refs=fake_refs, prompt=prompt, model_id="gemini-3-pro-image-preview")
    assert "(very young:1.5)" not in result["prompt"]


def test_build_payload_converts_negatives_when_unsupported(fake_refs):
    from recoil.pipeline._lib.payload_builder import build_payload
    shot = SimpleNamespace(shot_id="EP001_SH01", run_id=None)
    prompt = "Sadie stands in a bar, no children, no text"
    result = build_payload(shot=shot, refs=fake_refs, prompt=prompt, model_id="gemini-3-pro-image-preview")
    assert "no children" not in result["prompt"]
    assert "no text" not in result["prompt"]
