import asyncio

from services.rpg_plot import (
    prune_beats_for_done_quests,
    process_arc_beats,
    should_advance_arc_keywords,
    pop_matching_beats,
    dice_outcome_to_beat_trigger,
)


def test_prune_removes_beat_when_quest_done():
    arc = {
        "beats": [
            {"id": "b2", "title": "Highway Howl", "trigger": "event_driven:travel", "choices": []},
        ]
    }
    quests = [{"title": "Highway Howl", "status": "done"}]
    arc, removed = prune_beats_for_done_quests(arc, quests)
    assert removed[0]["title"] == "Highway Howl"
    assert arc["beats"] == []


def test_stuck_recovery_fires_when_no_active_quests():
    arc = {
        "beats": [
            {"id": "b3", "title": "New Beat", "trigger": "event_driven:rest", "choices": [{"id": "a", "label": "A"}]},
        ]
    }
    quests = [{"title": "Old", "status": "done"}]

    async def run():
        return await process_arc_beats(arc, quests, "hello")

    arc2, fired, pruned, mode = asyncio.run(run())
    assert mode == "stuck_recovery"
    assert fired[0]["title"] == "New Beat"
    assert arc2["beats"] == []


def test_dice_outcome_maps_to_after_fail():
    assert dice_outcome_to_beat_trigger("failure") == "event_driven:after_fail"
    assert dice_outcome_to_beat_trigger("critical failure") == "event_driven:after_fail"
    assert dice_outcome_to_beat_trigger("success") == "event_driven:after_success"


def test_after_fail_beat_fires_on_dice_failure():
    arc = {
        "beats": [
            {
                "id": "b_fail",
                "title": "Dust Yourself Off",
                "trigger": "event_driven:after_fail",
                "injection": "The stumble leaves you both shaken.",
                "choices": [{"id": "a", "label": "Try again"}],
            },
            {
                "id": "b_ok",
                "title": "Victory Lap",
                "trigger": "event_driven:after_success",
                "choices": [],
            },
        ]
    }

    async def run():
        return await process_arc_beats(
            arc, [], "продолжаем разговор", last_dice_outcome="failure"
        )

    arc2, fired, _, mode = asyncio.run(run())
    assert mode == "after_dice"
    assert fired[0]["id"] == "b_fail"
    assert len(arc2["beats"]) == 1
    assert arc2["beats"][0]["id"] == "b_ok"


def test_keyword_fallback_travel():
    arc = {
        "beats": [
            {"id": "b2", "title": "Highway Howl", "trigger": "event_driven:travel", "choices": []},
        ]
    }
    trig = should_advance_arc_keywords("едем на стадион")
    assert trig == "event_driven:travel"
    arc, fired = pop_matching_beats(arc, trig, max_beats=1)
    assert fired[0]["title"] == "Highway Howl"
