"""Tests for content filter soften-prompt retry logic."""

import json
from unittest.mock import patch, MagicMock


def test_needs_softening_detects_content_filter_keywords():
    from recoil.pipeline._lib.prompt_soften import needs_softening

    assert needs_softening("Content_Filter violation detected")
    assert needs_softening("Request blocked by safety_blocked policy")
    assert needs_softening("prohibited content found in prompt")
    assert needs_softening("content_policy triggered")
    assert needs_softening("Your request was BLOCKED_PROMPT by the model")
    assert needs_softening("responsible_ai filter applied")
    assert not needs_softening("Generation successful")
    assert not needs_softening("Image rendered at 1080x1920")


def test_needs_softening_detects_http_400():
    from recoil.pipeline._lib.prompt_soften import needs_softening

    assert needs_softening("", http_status=400)


def test_needs_softening_case_insensitive():
    from recoil.pipeline._lib.prompt_soften import needs_softening

    assert needs_softening("CONTENT_FILTER error")
    assert needs_softening("content_filter error")
    assert needs_softening("Content_Filter error")


def test_soften_prompt_calls_gemini_flash(monkeypatch):
    """soften_prompt uses google.genai to call Gemini Flash."""
    from recoil.pipeline._lib.prompt_soften import soften_prompt

    mock_client = MagicMock()
    mock_response = MagicMock()
    mock_response.text = (
        "Alice walks cautiously through the aftermath of the confrontation"
    )
    mock_client.models.generate_content.return_value = mock_response

    with (
        patch(
            "recoil.pipeline._lib.prompt_soften._get_genai_client",
            return_value=mock_client,
        ),
        patch(
            "recoil.pipeline._lib.prompt_soften._get_audit_log_path",
            return_value=MagicMock(
                parent=MagicMock(),
                open=MagicMock(),
                exists=MagicMock(return_value=False),
            ),
        ),
    ):
        # Use a tmpdir-friendly approach: mock the audit log path
        import tempfile
        from pathlib import Path

        with tempfile.TemporaryDirectory() as tmpd:
            log_path = Path(tmpd) / "soften_log.jsonl"
            with patch(
                "recoil.pipeline._lib.prompt_soften._get_audit_log_path",
                return_value=log_path,
            ):
                result = soften_prompt(
                    original_prompt="Alice fights through the blood-soaked warehouse",
                    shot_id="EP001_SH03",
                    model="kling-v3",
                )

    assert result is not None
    assert "aftermath" in result or "cautiously" in result
    mock_client.models.generate_content.assert_called_once()


def test_soften_prompt_returns_none_on_genai_failure():
    """If Gemini Flash fails, soften_prompt returns None (escalate to review queue)."""
    from recoil.pipeline._lib.prompt_soften import soften_prompt
    import tempfile
    from pathlib import Path

    with tempfile.TemporaryDirectory() as tmpd:
        log_path = Path(tmpd) / "soften_log.jsonl"
        with (
            patch(
                "recoil.pipeline._lib.prompt_soften._get_genai_client",
                side_effect=RuntimeError("API down"),
            ),
            patch(
                "recoil.pipeline._lib.prompt_soften._get_audit_log_path",
                return_value=log_path,
            ),
        ):
            result = soften_prompt(
                original_prompt="violent scene",
                shot_id="EP001_SH03",
                model="kling-v3",
            )

    assert result is None


def test_soften_prompt_logs_to_audit_file(tmp_path):
    """Softening attempts are logged to feedback/soften_log.jsonl."""
    from recoil.pipeline._lib.prompt_soften import soften_prompt

    mock_client = MagicMock()
    mock_response = MagicMock()
    mock_response.text = "softened version"
    mock_client.models.generate_content.return_value = mock_response

    log_path = tmp_path / "soften_log.jsonl"
    with (
        patch(
            "recoil.pipeline._lib.prompt_soften._get_genai_client",
            return_value=mock_client,
        ),
        patch(
            "recoil.pipeline._lib.prompt_soften._get_audit_log_path",
            return_value=log_path,
        ),
    ):
        soften_prompt("original", shot_id="SH01", model="kling-v3")

    assert log_path.exists()
    entry = json.loads(log_path.read_text().strip())
    assert entry["shot_id"] == "SH01"
    assert entry["original_prompt"] == "original"
    assert entry["softened_prompt"] == "softened version"


def test_soften_prompt_logs_failure_to_audit_file(tmp_path):
    """Failed softening attempts are also logged."""
    from recoil.pipeline._lib.prompt_soften import soften_prompt

    log_path = tmp_path / "soften_log.jsonl"
    with (
        patch(
            "recoil.pipeline._lib.prompt_soften._get_genai_client",
            side_effect=RuntimeError("down"),
        ),
        patch(
            "recoil.pipeline._lib.prompt_soften._get_audit_log_path",
            return_value=log_path,
        ),
    ):
        result = soften_prompt("original", shot_id="SH01", model="kling-v3")

    assert result is None
    assert log_path.exists()
    entry = json.loads(log_path.read_text().strip())
    assert entry["success"] is False
    assert entry["softened_prompt"] is None


def test_is_model_soften_eligible():
    """Only models with requires_content_filter_soften_retry=True are eligible."""
    from recoil.pipeline._lib.prompt_soften import is_model_soften_eligible

    # NBP should be eligible (profile has requires_content_filter_soften_retry: true)
    assert is_model_soften_eligible("gemini-3-pro-image-preview") is True
    # Flash should not be eligible
    assert is_model_soften_eligible("gemini-3.1-flash-image-preview") is False


def test_soften_prompt_returns_none_on_empty_response(tmp_path):
    """If Gemini returns empty text, soften_prompt returns None."""
    from recoil.pipeline._lib.prompt_soften import soften_prompt

    mock_client = MagicMock()
    mock_response = MagicMock()
    mock_response.text = "   "  # whitespace-only
    mock_client.models.generate_content.return_value = mock_response

    log_path = tmp_path / "soften_log.jsonl"
    with (
        patch(
            "recoil.pipeline._lib.prompt_soften._get_genai_client",
            return_value=mock_client,
        ),
        patch(
            "recoil.pipeline._lib.prompt_soften._get_audit_log_path",
            return_value=log_path,
        ),
    ):
        result = soften_prompt("original", shot_id="SH01", model="kling-v3")

    assert result is None
