"""
Unit Test Suite for FreeExile Beggar's Storyline & Chronicle Engine.
Validates:
- Initialization of player story state.
- Unlocking journal entries on quest completion.
- Evaluation of Beggar ascent stages (Mendicant -> Sovereign Outcast).
- Narrative Act transitions (Act I -> Act V).
- Cutscene triggers on milestone quests.
- Journal reading and serialization summary.
"""

import pytest
from server.world.storyline_types import (
    StoryAct,
    BeggarAscentStage,
    PlayerStoryState,
)
from server.world.storyline_engine import (
    StorylineEngine,
    create_default_storyline_engine,
)


class TestStorylineEngine:
    @pytest.fixture
    def story_engine(self) -> StorylineEngine:
        return create_default_storyline_engine()

    def test_player_story_initialization(self, story_engine: StorylineEngine) -> None:
        player_id = "test_beggar_001"
        state = story_engine.initialize_player_story(player_id)

        assert state.player_id == player_id
        assert state.current_act == StoryAct.ACT_I_HUNGER
        assert state.current_stage == BeggarAscentStage.MENDICANT
        assert state.reputation_title == "Kẻ Ăn Mày Rách Rưới"
        assert len(state.unlocked_journal_ids) == 0
        assert len(state.completed_acts) == 0

    def test_journal_unlock_on_quest_completed(self, story_engine: StorylineEngine) -> None:
        player_id = "test_beggar_002"
        res = story_engine.on_quest_completed(player_id, "quest_norm_01_thuc_tinh_tang_kiem")

        assert "journal_01_chiec_bat_vo" in res["unlocked_journals"]
        state = story_engine.get_player_story_state(player_id)
        assert "journal_01_chiec_bat_vo" in state.unlocked_journal_ids

        entry = story_engine.get_journal("journal_01_chiec_bat_vo")
        assert entry is not None
        assert entry.title == "Chiếc Bát Vỡ Bên Bờ Đá"
        assert "Khi cơn đói vượt qua nỗi sợ" in entry.quote_highlight

    def test_cutscene_triggered_on_act1_quest(self, story_engine: StorylineEngine) -> None:
        player_id = "test_beggar_003"
        res = story_engine.on_quest_completed(player_id, "quest_norm_01_thuc_tinh_tang_kiem")

        assert "cutscene_act_1_intro" in res["triggered_cutscenes"]
        cutscene = story_engine._cutscenes.get("cutscene_act_1_intro")
        assert cutscene is not None
        assert cutscene.speaker_name == "Kẻ Hành Khất"

    def test_stage_and_act_progression_across_acts(self, story_engine: StorylineEngine) -> None:
        player_id = "test_beggar_004"

        # Act I quests
        story_engine.on_quest_completed(player_id, "quest_norm_01_thuc_tinh_tang_kiem")
        story_engine.on_quest_completed(player_id, "quest_norm_02_khai_thong_dan_dien")
        story_engine.on_quest_completed(player_id, "quest_norm_03_luyen_khi_hoa_thach")
        state = story_engine.get_player_story_state(player_id)
        assert state.current_act == StoryAct.ACT_I_HUNGER
        assert state.current_stage == BeggarAscentStage.MENDICANT

        # Act II quests -> SCAVENGER
        story_engine.on_quest_completed(player_id, "quest_norm_04_diet_u_hon_kiem_no")
        state = story_engine.get_player_story_state(player_id)
        assert state.current_stage == BeggarAscentStage.SCAVENGER
        assert state.current_act == StoryAct.ACT_II_MIASMA
        assert StoryAct.ACT_I_HUNGER in state.completed_acts

        # Act III quests -> BONE_WARRIOR
        story_engine.on_quest_completed(player_id, "quest_epic_01_phong_ma_co_tran")
        state = story_engine.get_player_story_state(player_id)
        assert state.current_stage == BeggarAscentStage.BONE_WARRIOR
        assert state.current_act == StoryAct.ACT_III_CRUCIBLE
        assert StoryAct.ACT_II_MIASMA in state.completed_acts

        # Act IV quests -> PRIMAL_HUNTER
        story_engine.on_quest_completed(player_id, "quest_epic_02_nghich_menh_dai_huyet")
        state = story_engine.get_player_story_state(player_id)
        assert state.current_stage == BeggarAscentStage.PRIMAL_HUNTER
        assert state.current_act == StoryAct.ACT_IV_TITAN_HUNT
        assert StoryAct.ACT_III_CRUCIBLE in state.completed_acts

        # Act V quests -> SOVEREIGN_OUTCAST
        story_engine.on_quest_completed(player_id, "quest_epic_04_van_gioi_than_ma_tranh_ba")
        state = story_engine.get_player_story_state(player_id)
        assert state.current_stage == BeggarAscentStage.SOVEREIGN_OUTCAST
        assert state.current_act == StoryAct.ACT_V_SOVEREIGN
        assert StoryAct.ACT_IV_TITAN_HUNT in state.completed_acts
        assert len(state.completed_acts) == 4
        assert state.reputation_title == "Bá Chủ Tối Cao Cõi Lưu Đày"

    def test_read_journal_and_chronicle_summary(self, story_engine: StorylineEngine) -> None:
        player_id = "test_beggar_005"
        story_engine.on_quest_completed(player_id, "quest_norm_01_thuc_tinh_tang_kiem")

        # Read un-unlocked journal returns None
        assert story_engine.read_journal(player_id, "journal_15_vinh_quang_dinh_phong") is None

        # Read unlocked journal succeeds
        journal = story_engine.read_journal(player_id, "journal_01_chiec_bat_vo")
        assert journal is not None
        assert journal.journal_id == "journal_01_chiec_bat_vo"

        summary = story_engine.get_chronicle_summary(player_id)
        assert summary["player_id"] == player_id
        assert summary["total_journals_unlocked"] == 1
        assert "journal_01_chiec_bat_vo" in summary["read_journal_ids"]
