"""End-to-End Simulation: 10 Maps Closed-Loop & Faustus Currency Waterfall Cascade.
===================================================================================
Kịch bản mô phỏng kiểm thử 10 Maps khép kín toàn diện (Doc 61, 68, 69, 70):
1. Khởi tạo đồ thị Atlas 115+ nodes chuẩn mực (T1 -> T16).
2. Lần lượt chạy 10 maps liên tiếp:
   - AtlasProgressionPlanner chọn Frontier Node tối ưu theo trọng số và mở rộng biên.
   - Giả lập dọn map và nhặt loot thực tế (Gold, Alchemy, Exalted, Regal, Chaos, Divine).
   - Trở về Hideout -> Cất đồ vào Stash -> Mở sàn Faustus Currency Exchange (phím '/').
   - Thực thi thuật toán Thác Ngoại Hối (Waterfall Cascade):
     * Gom đổi currency phụ thặng dư thành Chaos Orb.
     * Tích lũy đủ Chaos chuyển đổi sang Divine Orb.
     * Khi đạt ngưỡng cao chuyển đổi sang Mirror of Kalandra.
   - Kiểm soát nghiêm ngặt bất biến INV-EXCHANGE-GOLD-TAX (quỹ vàng >= 5,000 Gold).
3. Thu thập và đối soát các chỉ số định lượng sau 10 maps.
"""

import pytest
from typing import Any, Dict, List

from src.assistant_tool.atlas.graph import (
    AtlasGraph,
    AtlasGraphNode,
    NodeProgressionState,
)
from src.assistant_tool.atlas.progression_planner import (
    AtlasProgressionPlanner,
    ProgressionStrategy,
)
from src.assistant_tool.currency_exchange.models import (
    CurrencyTier,
    ExchangeActionType,
    ExchangePortfolioConfig,
)
from src.assistant_tool.currency_exchange.portfolio_optimizer import (
    CurrencyPortfolioOptimizer,
)
from src.assistant_tool.currency_exchange.exchange_orchestrator import (
    CurrencyExchangeOrchestrator,
)


class TestClosedLoop10MapsSimulation:
    def test_full_10_maps_progression_and_currency_cascade(self):
        # =====================================================================
        # 1. KHỞI TẠO ĐỒ THỊ ATLAS 115+ NODES
        # =====================================================================
        atlas_graph = AtlasGraph.create_canonical_atlas_graph(total_target_nodes=115)
        assert atlas_graph.total_nodes >= 115, f"Tổng số nodes Atlas phải >= 115, hiện có: {atlas_graph.total_nodes}"

        initial_stats = atlas_graph.get_completion_stats()
        assert initial_stats["completed_count"] >= 1
        assert initial_stats["frontier_count"] >= 1

        # Cấu hình sàn ngoại hối & bộ tối ưu hóa thác tiền tệ
        exchange_config = ExchangePortfolioConfig(
            min_gold_reserve=5000,
            min_chaos_reserve=50,
            min_divine_reserve=2,
            cooldown_ms=0,  # 0 cooldown trong phiên mô phỏng để chạy liên tục 10 maps
        )
        optimizer = CurrencyPortfolioOptimizer(config=exchange_config)

        key_press_events: List[int] = []
        def mock_press_key(vk: int):
            key_press_events.append(vk)

        orchestrator = CurrencyExchangeOrchestrator(
            config=exchange_config,
            optimizer=optimizer,
            press_key_func=mock_press_key,
        )

        # Bảng giá thị trường tham chiếu POE2 Scout API (Doc 68)
        market_prices_in_chaos = {
            "Orb of Transmutation": 0.05,
            "Orb of Alteration": 0.15,
            "Orb of Alchemy": 0.50,
            "Orb of Scouring": 0.80,
            "Regal Orb": 1.20,
            "Vaul Orb": 1.50,
            "Exalted Orb": 12.50,
            "Divine Orb": 145.00,
            "Mirror of Kalandra": 65250.00,  # 450 Divine Orbs
        }

        # Ví tài sản ban đầu của nhân vật tại Shoreline Hideout
        character_wallet: Dict[str, int] = {
            "Orb of Alchemy": 25,
            "Orb of Scouring": 22,
            "Exalted Orb": 8,
            "Regal Orb": 15,
            "Chaos Orb": 60,
            "Divine Orb": 1,
            "Mirror of Kalandra": 0,
        }
        current_gold = 8500  # Khởi đầu với 8,500 Gold (> 5,000 Gold reserve)

        planner = AtlasProgressionPlanner(
            graph=atlas_graph,
            strategy=ProgressionStrategy.FULL_COMPLETION_RUSH,
        )

        completed_maps_log: List[Dict[str, Any]] = []
        total_gold_earned = 0
        total_gold_spent_tax = 0
        total_exchange_orders_executed = 0

        # =====================================================================
        # 2. VÒNG LẶP CHẠY 10 MAPS LIÊN TIẾP
        # =====================================================================
        current_node_id = list(atlas_graph._nodes.keys())[0]

        for map_index in range(1, 11):
            # A. Bước 1: Duyệt đồ thị Atlas chọn Frontier Node tối ưu
            decision = planner.select_next_node(current_node_id=current_node_id, current_tier_cap=16)
            assert decision is not None, f"Map {map_index}: Không tìm thấy node kế tiếp trên đồ thị Atlas!"

            chosen_node = decision.next_step_node
            assert chosen_node is not None

            # B. Bước 2: Giả lập dọn Map & Nhặt đồ rơi (Loot Drop)
            # Tùy theo tier bản đồ, nhận được lượng Gold và Currency tương ứng
            map_gold_looted = 1800 + (chosen_node.tier * 250)
            current_gold += map_gold_looted
            total_gold_earned += map_gold_looted

            # Quái vật rơi đồ: Exalted, Regal, Alchemy, và thỉnh thoảng có Divine
            character_wallet["Orb of Alchemy"] = character_wallet.get("Orb of Alchemy", 0) + 4
            character_wallet["Regal Orb"] = character_wallet.get("Regal Orb", 0) + 3
            character_wallet["Exalted Orb"] = character_wallet.get("Exalted Orb", 0) + 2
            character_wallet["Chaos Orb"] = character_wallet.get("Chaos Orb", 0) + 15

            if map_index in (4, 8):
                # May mắn nhặt được 1 Divine Orb nguyên viên từ Boss
                character_wallet["Divine Orb"] = character_wallet.get("Divine Orb", 0) + 1

            # Đánh dấu map hoàn thành có bonus -> Mở rộng biên (Frontier Expansion)
            atlas_graph.mark_node_completed(chosen_node.node_id, bonus=True)
            current_node_id = chosen_node.node_id

            # C. Bước 3: Trở về Hideout & Cất đồ vào Stash (Mô phỏng Stash)
            # Giữ an toàn tối thiểu trong túi: 20 Alchemy, 20 Scouring

            # D. Bước 4: Mở sàn Faustus Currency Exchange (Phím '/') và tối ưu Thác Tiền Tệ
            exchange_rep = orchestrator.execute_session(
                wallet=character_wallet,
                market_prices_in_chaos=market_prices_in_chaos,
                current_gold=current_gold,
                area_name="Shoreline Hideout",
                is_simulated=False,
            )

            # Cập nhật ví và trừ phí vàng nộp thuế sàn
            if exchange_rep.status == "SUCCESS":
                current_gold -= exchange_rep.gold_spent
                total_gold_spent_tax += exchange_rep.gold_spent
                total_exchange_orders_executed += exchange_rep.orders_executed

                # Cập nhật số dư currency sau các lệnh đã khớp trên sàn
                plan = optimizer.optimize_portfolio(
                    wallet=character_wallet,
                    market_prices_in_chaos=market_prices_in_chaos,
                    current_gold=current_gold + exchange_rep.gold_spent,
                )
                for ord_item in plan.orders:
                    character_wallet[ord_item.sell_currency] = max(
                        0, character_wallet.get(ord_item.sell_currency, 0) - ord_item.sell_amount
                    )
                    character_wallet[ord_item.buy_currency] = (
                        character_wallet.get(ord_item.buy_currency, 0) + ord_item.expected_buy_amount
                    )

            # =================================================================
            # E. KIỂM CHỨNG BẤT BIẾN NGHIÊM NGẶT INV-EXCHANGE-GOLD-TAX
            # =================================================================
            assert current_gold >= 5000, (
                f"Vi phạm INV-EXCHANGE-GOLD-TAX tại Map {map_index}: "
                f"Quỹ vàng bị tụt xuống {current_gold} < 5,000 Gold!"
            )

            completed_maps_log.append({
                "map_index": map_index,
                "node_name": chosen_node.name,
                "node_tier": chosen_node.tier,
                "gold_balance": current_gold,
                "gold_tax_paid": exchange_rep.gold_spent,
                "orders_count": exchange_rep.orders_executed,
                "chaos_held": character_wallet.get("Chaos Orb", 0),
                "divine_held": character_wallet.get("Divine Orb", 0),
                "mirror_held": character_wallet.get("Mirror of Kalandra", 0),
            })

        # =====================================================================
        # 3. NGHIỆM THU ĐỊNH LƯỢNG SAU 10 MAPS
        # =====================================================================
        end_stats = atlas_graph.get_completion_stats()

        # 1. Kiểm tra tiến trình Atlas
        assert len(completed_maps_log) == 10
        assert end_stats["completed_count"] >= 10
        assert end_stats["bonus_completed_count"] >= 10
        assert end_stats["frontier_count"] >= 5, "Biên mở rộng phải có ít nhất 5 frontiers tiếp theo"

        # 2. Kiểm tra phím bấm chuẩn SSoT (Rule 7)
        # Phải bấm phím '/' (0xBF) mở sàn và Spacebar (0x20) đóng panels
        assert 0xBF in key_press_events, "Chưa gửi phím '/' (VK_OEM_2) mở sàn Currency Exchange"
        assert 0x20 in key_press_events, "Chưa gửi phím Spacebar (VK_SPACE) đóng panels an toàn"

        # 3. Kiểm tra kết quả Thác Ngoại Hối
        # Sau 10 maps, currency phụ (Exalted, Regal) phải được bán bớt để tích lũy Divine
        assert character_wallet.get("Divine Orb", 0) >= 2, (
            f"Thác tiền tệ phải tích lũy được ít nhất 2 Divine Orb sau 10 maps, thực tế: {character_wallet.get('Divine Orb', 0)}"
        )
        assert current_gold >= 5000, f"Quỹ vàng kết thúc phiên phải >= 5000 Gold, thực tế: {current_gold}"
        assert total_exchange_orders_executed >= 5, "Phải thực thi ít nhất 5 lệnh giao dịch sàn ngoại hối"

        # In bao cao chi tiet cho test output (ASCII safe cho Windows console)
        print("\n========================================================")
        print("  [MO PHONG THUAT TOAN HEADLESS - KHONG PHAI LIVE GAME]")
        print("  REPORT: 10 MAPS SIMULATION & FAUSTUS WATERFALL CASCADE")
        print("========================================================")
        print(f"- Total Atlas Nodes in Graph: {end_stats['total_nodes']}")
        print(f"- Simulated Maps Completed: {end_stats['completed_count']} ({end_stats['completion_rate']}%)")
        print(f"- Simulated Frontier Reachable Nodes: {end_stats['frontier_count']}")
        print(f"- Simulated Passive Points: +{end_stats['total_atlas_passive_points']} Points")
        print(f"- Simulated Gold Looted: +{total_gold_earned} Gold")
        print(f"- Simulated Gold Tax Paid: -{total_gold_spent_tax} Gold")
        print(f"- Simulated Safe Ending Gold: {current_gold} Gold (INV-EXCHANGE-GOLD-TAX >= 5000: PASSED)")
        print(f"- Simulated Exchange Orders: {total_exchange_orders_executed} orders")
        print(f"- Final Simulated Currency: {character_wallet.get('Chaos Orb', 0)} Chaos | {character_wallet.get('Divine Orb', 0)} Divine | {character_wallet.get('Mirror of Kalandra', 0)} Mirror")
        print("========================================================\n")
