"""Tests for Auto-Gem Leveling & Real-Time Net Worth Estimator.
=============================================================
Kiểm thử toàn diện:
1. GemAutoLeveler:
   - Tính toán tọa độ icon dấu cộng (+) theo độ phân giải 1080p và 1440p.
   - Khóa an toàn sinh tồn (INV-GEM-LEVEL-SAFE-COMBAT):
     * Hoãn thăng cấp khi đang trong giao tranh (in_combat == True).
     * Hoãn thăng cấp khi quái vật ở cự ly quá gần (<= 30.0u).
     * Cho phép thăng cấp an toàn khi cự ly > 30.0u ngoài giao tranh hoặc trong Hideout.
     * Kiểm tra cooldown giãn cách 500ms và callback click chuột tuyệt đối.
2. NetWorthEstimator:
   - Phân loại danh mục tài sản (High Currency, Crafting, Materials, Gems, Maps).
   - Quy đổi chính xác tổng tài sản sang Chaos Orb và Divine Orb theo giá thị trường.
   - Tích hợp tài sản từ Ví (Wallet) và Hòm đồ (Stash).
   - Định dạng bảng báo cáo ASCII và Markdown sau map.

Tuân thủ nghiêm ngặt Rule 5:
Dán nhãn [MÔ PHỎNG THUẬT TOÁN HEADLESS - KHÔNG PHẢI LIVE GAME] trên toàn bộ đầu ra CLI.
"""

import pytest
from typing import Any, Dict, List, Tuple

from src.assistant_tool.gem_auto_leveler import (
    GemAutoLeveler,
    GemLevelerConfig,
    GemLevelUpStatus,
    GemPlusIconLocation,
)
from src.assistant_tool.currency_exchange.net_worth_estimator import (
    NetWorthEstimator,
    NetWorthReport,
    NetWorthCategory,
)


class TestGemAutoLeveler:
    def test_icon_coordinate_scaling(self):
        """Kiểm tra độ chính xác tọa độ icon dấu cộng (+) trên 1080p và 1440p."""
        leveler_1440p = GemAutoLeveler(screen_w=2560, screen_h=1440)
        x0, y0 = leveler_1440p.get_icon_coordinates(slot_index=0)
        x1, y1 = leveler_1440p.get_icon_coordinates(slot_index=1)

        assert x0 == 2500.0
        assert y0 == 350.0
        assert x1 == 2500.0
        assert y1 == 350.0 + 52.0

        leveler_1080p = GemAutoLeveler(screen_w=1920, screen_h=1080)
        x0_1080, y0_1080 = leveler_1080p.get_icon_coordinates(slot_index=0)
        assert x0_1080 == 1875.0
        assert y0_1080 == 262.0

    def test_safety_interlock_deferred_in_combat(self):
        """Kiểm tra bất biến INV-GEM-LEVEL-SAFE-COMBAT: Hoãn khi đang combat."""
        leveler = GemAutoLeveler()
        res = leveler.process_leveling_cycle(
            nearest_monster_distance=50.0,
            in_combat=True,  # Đang giao tranh
            is_safe_area=False,
            simulated_ready_count=2,
        )

        assert res["status"] == GemLevelUpStatus.DEFERRED_IN_COMBAT.value
        assert res["gems_leveled"] == 0
        assert "giao tranh" in res["reason"]

    def test_safety_interlock_deferred_monster_proximity(self):
        """Kiểm tra bất biến INV-GEM-LEVEL-SAFE-COMBAT: Hoãn khi quái vật <= 30u."""
        leveler = GemAutoLeveler()
        res = leveler.process_leveling_cycle(
            nearest_monster_distance=22.5,  # Quá gần (< 30u)
            in_combat=False,
            is_safe_area=False,
            simulated_ready_count=2,
        )

        assert res["status"] == GemLevelUpStatus.DEFERRED_PROXIMITY.value
        assert res["gems_leveled"] == 0
        assert "quá gần" in res["reason"]

    def test_safe_leveling_in_hideout(self):
        """Kiểm tra thăng cấp an toàn 100% khi ở Hideout hoặc Town."""
        clicked_positions = []
        def mock_click(x, y):
            clicked_positions.append((x, y))

        leveler = GemAutoLeveler(click_callback=mock_click)
        res = leveler.process_leveling_cycle(
            nearest_monster_distance=0.0,
            in_combat=False,
            is_safe_area=True,  # Đang ở Hideout
            simulated_ready_count=2,
            now_ms=10000,
        )

        assert res["status"] == GemLevelUpStatus.SUCCESS_LEVELED.value
        assert res["gems_leveled"] == 2
        assert len(clicked_positions) == 2
        assert clicked_positions[0] == (2500.0, 350.0)
        assert clicked_positions[1] == (2500.0, 402.0)

    def test_safe_leveling_in_map_when_clear(self):
        """Kiểm tra thăng cấp an toàn trong Map khi cự ly quái vật > 30u và ngoài giao tranh."""
        clicked_positions = []
        leveler = GemAutoLeveler(click_callback=lambda x, y: clicked_positions.append((x, y)))

        res = leveler.process_leveling_cycle(
            nearest_monster_distance=45.0,  # An toàn (> 30u)
            in_combat=False,
            is_safe_area=False,
            simulated_ready_count=1,
            now_ms=20000,
        )

        assert res["status"] == GemLevelUpStatus.SUCCESS_LEVELED.value
        assert res["gems_leveled"] == 1
        assert len(clicked_positions) == 1

    def test_cooldown_gating(self):
        """Kiểm tra khóa giãn cách 500ms chống spam click."""
        leveler = GemAutoLeveler()
        res1 = leveler.process_leveling_cycle(
            is_safe_area=True,
            simulated_ready_count=1,
            now_ms=1000,
        )
        assert res1["status"] == GemLevelUpStatus.SUCCESS_LEVELED.value

        # Lần gọi tiếp theo sau 200ms (< 500ms)
        res2 = leveler.process_leveling_cycle(
            is_safe_area=True,
            simulated_ready_count=1,
            now_ms=1200,
        )
        assert res2["status"] == GemLevelUpStatus.COOLDOWN_ACTIVE.value
        assert res2["gems_leveled"] == 0


class TestNetWorthEstimator:
    def test_calculate_net_worth_wallet_only(self):
        """Kiểm tra tính toán tài sản ròng từ ví cá nhân."""
        estimator = NetWorthEstimator()

        wallet = {
            "Chaos Orb": 120,          # 120 C
            "Divine Orb": 3,           # 3 * 145 = 435 C
            "Exalted Orb": 10,         # 10 * 12.5 = 125 C
            "Orb of Alchemy": 50,      # 50 * 0.5 = 25 C
            "Orb of Scouring": 20,     # 20 * 0.8 = 16 C
            "Mirror of Kalandra": 0,
        }

        report = estimator.calculate_net_worth(
            wallet=wallet,
            current_gold=18500,
        )

        # Tổng Chaos kỳ vọng: 120 + 435 + 125 + 25 + 16 = 721.0 Chaos
        assert report.total_net_worth_chaos == 721.0
        # 721.0 / 145 = 4.97 Divine
        assert report.total_net_worth_divine == pytest.approx(4.97, abs=0.02)
        assert report.liquid_chaos == 120
        assert report.liquid_divine == 3
        assert report.gold_balance == 18500

    def test_calculate_net_worth_with_stash_items(self):
        """Kiểm tra tổng hợp tài sản kết hợp giữa ví và kho đồ Stash."""
        estimator = NetWorthEstimator()

        wallet = {"Chaos Orb": 50, "Divine Orb": 1} # 50 + 145 = 195 C
        stash_items = [
            {"name": "Divine Orb", "count": 2},            # 2 * 145 = 290 C
            {"name": "Greater Jeweller's Orb", "count": 20}, # 20 * 2.5 = 50 C
            {"name": "Perfect Jeweller's Orb", "count": 2},  # 2 * 35 = 70 C
            {"name": "Exalted Orb", "count": 4},           # 4 * 12.5 = 50 C
        ]

        report = estimator.calculate_net_worth(
            wallet=wallet,
            stash_items=stash_items,
            current_gold=25000,
        )

        # Tổng: 195 + 290 + 50 + 70 + 50 = 655.0 Chaos
        assert report.total_net_worth_chaos == 655.0
        assert report.total_net_worth_divine == pytest.approx(4.52, abs=0.02)
        assert "High Currency" in report.categories
        assert "Crafting Currency" in report.categories

    def test_report_formatting_ascii_and_markdown(self):
        """Kiểm tra chuỗi định dạng bảng báo cáo ASCII và Markdown."""
        estimator = NetWorthEstimator()
        wallet = {"Chaos Orb": 200, "Divine Orb": 5}
        report = estimator.calculate_net_worth(wallet=wallet, current_gold=12000)

        ascii_rep = report.format_ascii_summary()
        assert "CHARACTER NET WORTH BREAKDOWN" in ascii_rep
        assert "Total Net Worth" in ascii_rep
        assert "Gold Reserve" in ascii_rep

        md_table = report.format_markdown_table()
        assert "| Danh Mục Tài Sản |" in md_table
        assert "| **TỔNG CỘNG TÀI SẢN** |" in md_table

        # In bao cao ra terminal voi nhan chuan Rule 5
        print("\n========================================================")
        print("  [MO PHONG THUAT TOAN HEADLESS - KHONG PHAI LIVE GAME]")
        print("  VERIFIED: AUTO-GEM LEVELING & NET WORTH ESTIMATOR DOD")
        print("========================================================")
        print(ascii_rep)
        print("========================================================\n")
