"""REC-212 regression: build_smart_prompt must fail loud when its versioned
system-prompt file (flash_to_nbp_v1.0.txt) is missing, instead of proceeding
to the Flash call with an empty system instruction (silent output degradation).

Mirrors the existing guards on the sibling Flash builders at
keyframe_context.py:116 (flash_scene_dna) and :230 (flash_moodboard_to_text),
which already return {"success": False, "error": "...not found"} on a missing
prompt file. build_smart_prompt (the flash_to_nbp keyframe path) lacked that
guard until this fix.
"""

from unittest.mock import patch

from recoil.pipeline._lib import keyframe_context


def _minimal_shot():
    return {"shot_id": "EP001_SH01", "prompt_data": {}, "asset_data": {}, "routing_data": {}}


def test_build_smart_prompt_fails_loud_on_missing_prompt_file():
    """Missing flash_to_nbp_v1.0.txt → {"error": ...} and NO Flash call."""
    with patch.object(keyframe_context, "load_prompt_file", return_value="") as mock_load, \
         patch.object(keyframe_context, "_call_flash_text") as mock_flash:
        result = keyframe_context.build_smart_prompt(
            shot=_minimal_shot(),
            all_shots=[],
            bible={},
            episode=1,
            project="test_project",
        )

    # Fails loud with the function's documented {"error": str} failure shape.
    assert "error" in result, f"expected an error dict, got: {result}"
    assert "flash_to_nbp_v1.0.txt" in result["error"]
    # The bug this guards: proceeding into the Flash call with an empty system
    # instruction. The Flash text call must NOT have been reached.
    mock_flash.assert_not_called()
    mock_load.assert_called_once_with("flash_to_nbp_v1.0.txt")


def test_build_smart_prompt_proceeds_when_prompt_file_present():
    """Non-empty prompt file → the guard does NOT short-circuit; Flash IS called."""
    with patch.object(keyframe_context, "load_prompt_file", return_value="SYSTEM PROMPT BODY"), \
         patch.object(
             keyframe_context,
             "_call_flash_text",
             return_value={"success": True, "text": "refined prompt", "cost": 0.0},
         ) as mock_flash:
        keyframe_context.build_smart_prompt(
            shot=_minimal_shot(),
            all_shots=[],
            bible={},
            episode=1,
            project="test_project",
        )

    # Guard did not trip: the Flash call was reached with a non-empty system prompt.
    mock_flash.assert_called_once()
    system_instruction = mock_flash.call_args.args[0]
    assert system_instruction, "system_instruction passed to Flash must be non-empty"
