"""Tests for Faustus Order Queue Manager & Auto-Restock Cycle (Chu Kỳ 8).
======================================================================
Kiem thu toan dien:
- Khoi tao va quan tri 10 slots dat lenh san Faustus.
- Xu ly day slot va tu choi lenh vuot han muc.
- Mo phong khop lenh va tu dong nhan tien te (Claim Completed Trades).
- Tu dong phat hien thieu hut Waystone <= 3 va sinh lenh restock (INV-WAYSTONE-RESTOCK-MIN).
- Rang buoc an toan Vang (INV-EXCHANGE-GOLD-TAX) va du tru Chaos (INV-EXCHANGE-RESERVE-SAFE).
- In bang quan tri 10 slots tuan thu Rule 5: [MO PHONG THUAT TOAN HEADLESS - KHONG PHAI LIVE GAME].
"""

import pytest
from src.assistant_tool.currency_exchange.models import (
    ExchangeActionType,
    ExchangeOrder,
    ExchangeOrderStatus,
    ExchangePortfolioConfig,
)
from src.assistant_tool.currency_exchange.faustus_order_manager import (
    ClaimTradeResult,
    FaustusOrderManager,
    FaustusOrderSlot,
)


class TestFaustusOrderManager:
    def test_slots_initialization_and_capacity(self):
        """Kiem tra khoi tao 10 slots san Faustus o trang thai trong."""
        manager = FaustusOrderManager()
        assert manager.MAX_SLOTS == 10
        assert manager.occupied_slots_count == 0
        assert manager.available_slots_count == 10
        assert manager.get_first_empty_slot() == 0
        for s in manager.slots:
            assert s.is_empty is True

    def test_submit_order_success_and_overflow(self):
        """Kiem tra nop 10 lenh thanh cong va tu choi lenh thu 11 khi het slot."""
        manager = FaustusOrderManager()

        # Nop 10 lenh
        for i in range(10):
            order = ExchangeOrder(
                order_id=f"order_{i}",
                action_type=ExchangeActionType.SELL_TO_CHAOS,
                sell_currency="Orb of Alchemy",
                sell_amount=20,
                buy_currency="Chaos Orb",
                expected_buy_amount=10,
                market_rate=0.5,
                estimated_gold_tax=500,
            )
            success, msg, slot_id = manager.submit_order(order)
            assert success is True
            assert slot_id == i
            assert order.status == ExchangeOrderStatus.SUBMITTED

        assert manager.occupied_slots_count == 10
        assert manager.available_slots_count == 0
        assert manager.get_first_empty_slot() is None

        # Nop lenh thu 11 -> Bi tu choi vi day 10/10
        overflow_order = ExchangeOrder(
            order_id="order_overflow",
            action_type=ExchangeActionType.CONVERT_CHAOS_TO_DIVINE,
            sell_currency="Chaos Orb",
            sell_amount=145,
            buy_currency="Divine Orb",
            expected_buy_amount=1,
            market_rate=1.0 / 145.0,
            estimated_gold_tax=250,
        )
        success, msg, slot_id = manager.submit_order(overflow_order)
        assert success is False
        assert slot_id is None
        assert overflow_order.status == ExchangeOrderStatus.CANCELLED
        assert "10/10 slots" in msg

    def test_simulate_fill_and_claim_trades(self):
        """Kiem tra mo phong khop lenh va tu dong claim giai phong slot."""
        manager = FaustusOrderManager()

        # Nop 2 lenh
        o1 = ExchangeOrder(
            order_id="o1",
            action_type=ExchangeActionType.CONVERT_CHAOS_TO_DIVINE,
            sell_currency="Chaos Orb",
            sell_amount=145,
            buy_currency="Divine Orb",
            expected_buy_amount=1,
            market_rate=1.0 / 145.0,
            estimated_gold_tax=250,
        )
        o2 = ExchangeOrder(
            order_id="o2",
            action_type=ExchangeActionType.SELL_TO_CHAOS,
            sell_currency="Orb of Alteration",
            sell_amount=100,
            buy_currency="Chaos Orb",
            expected_buy_amount=15,
            market_rate=0.15,
            estimated_gold_tax=500,
        )

        manager.submit_order(o1)
        manager.submit_order(o2)
        assert manager.occupied_slots_count == 2

        # Mo phong khop ca 2 lenh
        manager.simulate_order_fill(slot_id=0, filled_amount=1)
        manager.simulate_order_fill(slot_id=1, filled_amount=15)

        assert manager.slots[0].is_ready_to_claim is True
        assert manager.slots[1].is_ready_to_claim is True

        # Thuc thi claim toan bo
        claimed = manager.claim_all_completed_trades()
        assert len(claimed) == 2

        # Kiem tra ket qua nhan
        c1 = claimed[0]
        assert c1.claimed_currency == "Divine Orb"
        assert c1.claimed_amount == 1
        assert c1.freed_slot_id == 0

        c2 = claimed[1]
        assert c2.claimed_currency == "Chaos Orb"
        assert c2.claimed_amount == 15
        assert c2.freed_slot_id == 1

        # Kiem tra ca 2 slots da duoc giai phong
        assert manager.occupied_slots_count == 0
        assert manager.available_slots_count == 10
        assert manager.slots[0].is_empty is True
        assert manager.slots[1].is_empty is True

    def test_waystone_restock_min_trigger(self):
        """Kiem tra bat bien INV-WAYSTONE-RESTOCK-MIN: restock khi Waystones <= 3."""
        manager = FaustusOrderManager(waystone_price_in_chaos=10.0)

        # Case 1: Waystones = 5 (> 3) -> Khong restock
        order_none = manager.check_and_generate_waystone_restock(
            total_waystones_owned=5,
            available_chaos=200,
            current_gold=15000,
            target_tier=16,
            buy_count=5,
        )
        assert order_none is None

        # Case 2: Waystones = 2 (<= 3) va du Chaos + Gold -> Sinh lenh restock
        order_restock = manager.check_and_generate_waystone_restock(
            total_waystones_owned=2,
            available_chaos=200,
            current_gold=15000,
            target_tier=16,
            buy_count=5,
        )
        assert order_restock is not None
        assert order_restock.sell_currency == "Chaos Orb"
        assert order_restock.sell_amount == 50  # 5 * 10 = 50 Chaos
        assert order_restock.buy_currency == "Waystone (Tier 16)"
        assert order_restock.expected_buy_amount == 5
        assert order_restock.estimated_gold_tax == 250  # 5 * 50 = 250 Gold

        # Case 3: Thieu Chaos (Chi co 70 Chaos, reserve 50 -> con 20 < 50) -> Tu choi
        order_low_chaos = manager.check_and_generate_waystone_restock(
            total_waystones_owned=1,
            available_chaos=70,
            current_gold=15000,
            target_tier=16,
            buy_count=5,
        )
        assert order_low_chaos is None

        # Case 4: Thieu Gold (Chi co 5100 Gold, tru thue 250 con 4850 < 5000) -> Tu choi
        order_low_gold = manager.check_and_generate_waystone_restock(
            total_waystones_owned=1,
            available_chaos=200,
            current_gold=5100,
            target_tier=16,
            buy_count=5,
        )
        assert order_low_gold is None

    def test_format_ascii_order_board_rule5_compliant(self, capsys):
        """
        Mo phong quan tri 10 slots va in bang trang thai Rule 5:
        [MO PHONG THUAT TOAN HEADLESS - KHONG PHAI LIVE GAME]
        """
        manager = FaustusOrderManager()

        o1 = ExchangeOrder(
            order_id="ord_active_1",
            action_type=ExchangeActionType.CONVERT_CHAOS_TO_DIVINE,
            sell_currency="Chaos Orb",
            sell_amount=145,
            buy_currency="Divine Orb",
            expected_buy_amount=1,
            market_rate=1.0 / 145.0,
            estimated_gold_tax=250,
        )
        o2 = ExchangeOrder(
            order_id="ord_active_2",
            action_type=ExchangeActionType.SELL_TO_CHAOS,
            sell_currency="Orb of Alchemy",
            sell_amount=50,
            buy_currency="Chaos Orb",
            expected_buy_amount=25,
            market_rate=0.5,
            estimated_gold_tax=1250,
        )
        manager.submit_order(o1)
        manager.submit_order(o2)

        # Slot 0 khop hoan toan
        manager.simulate_order_fill(slot_id=0, filled_amount=1)

        board_str = manager.format_ascii_order_board()
        print("\n" + board_str)

        # Kiem tra chuoi Rule 5
        assert "[MO PHONG THUAT TOAN HEADLESS - KHONG PHAI LIVE GAME]" in board_str
        assert "(Occupied): 2 / 10" in board_str
        assert "(Available): 8 / 10" in board_str
        assert "READY TO CLAIM" in board_str

    def test_cancel_expired_orders_ttl(self):
        """Kiem tra quy tac Time-To-Live (TTL = 1 Map ~ 180s): tu dong huy lenh treo de thu hoi von."""
        from datetime import datetime, timedelta

        manager = FaustusOrderManager()
        order = ExchangeOrder(
            order_id="ord_stuck_ttl",
            action_type=ExchangeActionType.CONVERT_CHAOS_TO_DIVINE,
            sell_currency="Chaos Orb",
            sell_amount=150,
            buy_currency="Divine Orb",
            expected_buy_amount=1,
            market_rate=1.0 / 150.0,
            estimated_gold_tax=300,
        )
        ok, msg, slot_id = manager.submit_order(order)
        assert ok is True
        assert slot_id == 0

        # Mo phong thoi gian troi qua 200s (> 180s TTL)
        t_sub = datetime.now()
        t_future = t_sub + timedelta(seconds=200)

        # Chay cancel_expired_orders
        cancelled = manager.cancel_expired_orders(max_ttl_sec=180.0, now=t_future)
        assert len(cancelled) == 1
        assert cancelled[0][0] == 0  # slot_id
        assert cancelled[0][1] == "ord_stuck_ttl"
        assert "het han TTL" in cancelled[0][2]

        # Slot 0 phai duoc giai phong ve trong
        assert manager.slots[0].is_empty is True
        assert manager.occupied_slots_count == 0
        assert order.status == ExchangeOrderStatus.CANCELLED


