"""
AutoPOE2 - Unit Tests for Endgame Map Scenarios & Boss Rush (Context Year: 2026)
Verifies:
1. MapScenario IntEnum definitions & codes (BOSS_RUSH, ATLAS_QUEST_RUSH, FAST_CLEAR, FULL_CLEAR).
2. AutoQuester endgame map detection, scenario transitions, and priority objective resolution.
3. CoreShmBridge binary packaging for OpCode 95 (SET_MAP_SCENARIO).
4. CoreController CLI argument generation for --map-scenario and --auto-portal-exit.
5. AutonomousLifecycleManager endgame earning scenario switching.
"""

import os
import struct
import sys
import unittest

# Ensure workspace root is in sys.path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from src.assistant_tool.auto_quester import AutoQuester, MapScenario, QuestObjective
from src.assistant_tool.core_controller import CoreController
from src.assistant_tool.core_shm_bridge import CoreShmBridge, MacroOpCode


class TestMapScenarios(unittest.TestCase):
    def setUp(self):
        self.quester = AutoQuester()

    def test_map_scenario_enum_values(self):
        """Verify MapScenario enum integer values match C++ protocol.hpp."""
        self.assertEqual(MapScenario.BOSS_RUSH.value, 0)
        self.assertEqual(MapScenario.ATLAS_QUEST_RUSH.value, 1)
        self.assertEqual(MapScenario.FAST_CLEAR.value, 2)
        self.assertEqual(MapScenario.FULL_CLEAR.value, 3)

    def test_endgame_map_detection(self):
        """Verify AutoQuester correctly detects endgame Atlas maps vs campaign zones."""
        # Endgame maps
        self.assertTrue(self.quester.is_endgame_map("Atlas Map - Arid Lake"))
        self.assertTrue(self.quester.is_endgame_map("Waystone Map Tier 5"))
        self.assertTrue(self.quester.is_endgame_map("Citadel of the Flames"))
        self.assertTrue(self.quester.is_endgame_map("Pinnacle Sanctuary"))
        self.assertTrue(self.quester.is_endgame_map("The Sacred Crypt (Waystone)"))

        # Campaign zones should NOT be detected as endgame maps
        self.assertFalse(self.quester.is_endgame_map("The Riverbank"))
        self.assertFalse(self.quester.is_endgame_map("The Ogham Farmlands"))
        self.assertFalse(self.quester.is_endgame_map("Vastiri Outskirts"))
        self.assertFalse(self.quester.is_endgame_map("Sandswept Marsh"))
        self.assertFalse(self.quester.is_endgame_map(""))

    def test_map_scenario_switching_and_status_banner(self):
        """Verify switching scenarios updates internal state and HUD status banner."""
        self.quester.set_map_scenario(MapScenario.BOSS_RUSH)
        self.assertEqual(self.quester.scenario, MapScenario.BOSS_RUSH)
        banner_boss = self.quester.get_status_banner("Atlas Map - Strand", 75)
        self.assertIn("BOSS RUSH", banner_boss)

        self.quester.set_map_scenario(MapScenario.ATLAS_QUEST_RUSH)
        self.assertEqual(self.quester.scenario, MapScenario.ATLAS_QUEST_RUSH)
        banner_quest = self.quester.get_status_banner("Atlas Map - Strand", 75)
        self.assertIn("ATLAS QUEST RUSH", banner_quest)

        self.quester.set_map_scenario(MapScenario.FAST_CLEAR)
        banner_fast = self.quester.get_status_banner("Atlas Map - Strand", 75)
        self.assertIn("FAST CLEAR", banner_fast)

        self.quester.set_map_scenario(MapScenario.FULL_CLEAR)
        banner_full = self.quester.get_status_banner("Atlas Map - Strand", 75)
        self.assertIn("FULL CLEAR", banner_full)

    def test_endgame_objective_resolution(self):
        """Verify that in an endgame map, resolve_active_objective yields targeted Boss/Arena."""
        self.quester.set_map_scenario(MapScenario.BOSS_RUSH)
        obj = self.quester.resolve_active_objective(current_area_name="Atlas Map - Mesa", area_level=80)
        self.assertIn("Boss", obj.target_name)
        self.assertEqual(obj.action_type, "BOSS_RUSH")
        self.assertEqual(obj.reward, "ATLAS_POINT")

    def test_opcode_95_serialization(self):
        """Verify CoreShmBridge binary serialization for OpCode 95 (SET_MAP_SCENARIO)."""
        bridge = CoreShmBridge()
        self.assertEqual(MacroOpCode.SET_MAP_SCENARIO.value, 95)

        # Test packet serialization with scenario=BOSS_RUSH (0) and auto_portal=True (1.0)
        scenario_code = MapScenario.BOSS_RUSH.value
        auto_portal = True
        payload_x = float(scenario_code)
        payload_y = 1.0 if auto_portal else 0.0

        # CommandPacket layout:
        # uint32_t opCode
        # float targetX
        # float targetY
        # float targetZ
        # uint32_t flags
        # uint32_t reserved[4]
        # Total size: 36 bytes
        pkt = struct.pack(
            "=IfffIIIII",
            95,
            payload_x,
            payload_y,
            0.0,
            0,
            0, 0, 0, 0
        )
        self.assertEqual(len(pkt), 36)

        # Unpack and verify invariant fields
        op, tx, ty, tz, fl, r1, r2, r3, r4 = struct.unpack("=IfffIIIII", pkt)
        self.assertEqual(op, 95)
        self.assertAlmostEqual(tx, 0.0, places=4)
        self.assertAlmostEqual(ty, 1.0, places=4)
        self.assertAlmostEqual(tz, 0.0, places=4)

    def test_core_controller_cli_args_generation(self):
        """Verify CoreController properly generates CLI arguments for map scenarios."""
        ctrl = CoreController()

        # Scenario 0 (Boss Rush) with auto portal
        cfg_boss = {
            "map_scenario": 0,
            "auto_portal_after_boss": True,
            "auto_quest": True,
            "auto_patrol": True,
        }
        cmd_boss = ctrl.build_cmd(cfg_boss)
        self.assertIn("--map-scenario", cmd_boss)
        self.assertIn("0", cmd_boss)
        self.assertIn("--boss-rush", cmd_boss)
        self.assertIn("--auto-portal-exit", cmd_boss)

        # Scenario 1 (Atlas Quest Rush) without auto portal
        cfg_quest = {
            "map_scenario": 1,
            "auto_portal_after_boss": False,
            "auto_quest": True,
            "auto_patrol": True,
        }
        cmd_quest = ctrl.build_cmd(cfg_quest)
        self.assertIn("--map-scenario", cmd_quest)
        self.assertIn("1", cmd_quest)
        self.assertIn("--atlas-quest", cmd_quest)
        self.assertIn("--no-auto-portal", cmd_quest)


if __name__ == "__main__":
    unittest.main()
