"""AutoPOE2 - Atlas Knowledge Base & Special Node Catalog (Doc 65).
===================================================================
Single Source of Truth (SSoT) về toàn bộ các chủng loại Node trên cây bản đồ Atlas (POE2 v0.5.5+):
- Phân loại rõ rệt giữa Map cày thường, Tháp Tiền Thân, Đền Thờ Trung Tâm, và các Node Nhiệm Vụ Atlas.
- Cung cấp tri thức về điều kiện kích hoạt: nhận Waystone, nhận Tablet, hay Direct Traverse.
- Hỗ trợ chiến lược thông minh: Cày Map kiếm tiền (Farm Waystones) vs Đi làm Quest cộng điểm Atlas (Atlas Quest Rush).

Tuân thủ nghiêm ngặt:
- Rule 4: Module hóa, tách biệt trách nhiệm, trần file < 500 dòng.
- Rule 8: Bất biến kiến trúc INV-ATLAS-FARM-NODE & INV-ATLAS-QUEST-PROG.
"""

from __future__ import annotations

import re
from dataclasses import dataclass, field
from enum import Enum
from typing import Any, Dict, List, Optional, Tuple


class AtlasNodeType(str, Enum):
    """Phân loại các loại Node trên cây Atlas POE2 v0.5.5+."""
    REGULAR_WAYSTONE_MAP = "REGULAR_WAYSTONE_MAP"       # Bản đồ cày thông thường (Tier 1-16, cắm Waystone)
    PRECURSOR_TOWER = "PRECURSOR_TOWER"                 # Tháp Tiền Thân (cắm 1-3 Precursor Tablets, không cắm Waystone)
    WELL_OF_SOULS = "WELL_OF_SOULS"                     # Đền Thờ Trung Tâm & Heart of the Well (Direct Traverse / Sanctuary, không cắm Waystone/Tablet)
    QUEST_ENIGMA_CHAMBER = "QUEST_ENIGMA_CHAMBER"       # Enigma Chamber ("Legacy of the Precursors", mở khóa Tháp & +1 Atlas Point)
    QUEST_CORRUPTED_NEXUS = "QUEST_CORRUPTED_NEXUS"     # Corrupted Nexus ("Doryani's Science", +1 Atlas Passive Point)
    QUEST_GREAT_BEAST = "QUEST_GREAT_BEAST"             # Great Beast Lair ("Hilda's Hunting", Beastcrafting & +1 Atlas Point)
    QUEST_WITHERED_WILLOW = "QUEST_WITHERED_WILLOW"     # The Withered Willow ("Strange Reflection", Reflection mechanic)
    QUEST_KINGSMARCH_RUINS = "QUEST_KINGSMARCH_RUINS"   # Ruins of Kingsmarch ("The Grand Expedition", Expedition mechanic)
    CITADEL_BOSS = "CITADEL_BOSS"                       # Thành Lũy Boss Tối Cao (Citadel Guardians / Arbiter)
    TRIAL_OF_SEKHEMAS = "TRIAL_OF_SEKHEMAS"             # Đấu Trường Sekhema (4th Ascendancy & Relics)
    TRIAL_OF_CHAOS = "TRIAL_OF_CHAOS"                   # Đấu Trường Hỗn Mang (The Trialmaster / Inscribed Ultimatum)
    GATEWAY_CHECKPOINT = "GATEWAY_CHECKPOINT"           # Cửa ải / Cổng thành chia cắt phân khu Atlas (Western/Eastern Gateway)
    NOTABLE_PASSIVE_SHRINE = "NOTABLE_PASSIVE_SHRINE"   # Đền thờ điểm nội tại Atlas (không cắm Waystone)
    BURNING_MONOLITH = "BURNING_MONOLITH"               # Đấu trường Cột Lửa Cổ Đại (The Burning Monolith / Arbiter of Ash)
    ORIGIN_TOWER = "ORIGIN_TOWER"                       # Quần thể Tháp Cội Nguồn Ancient Fortress (v0.5.5+)
    PRECURSOR_REACTOR = "PRECURSOR_REACTOR"             # Đấu trường Lò Phản Ứng Tiền Thân (Arbiter of Divinity, v0.5.5+)
    PATRIARCH_HALL = "PATRIARCH_HALL"                   # Sảnh Tộc Trưởng (Ancient Fortress Wing, v0.5.5+)
    MATRIARCH_HALL = "MATRIARCH_HALL"                   # Sảnh Nữ Trưởng (Ancient Fortress Wing, v0.5.5+)
    UNIQUE_MAP = "UNIQUE_MAP"                           # 8 Bản đồ Độc Bản (Untainted, Zen, Kamasa, Phaaryl, Lake, Cave, Wildwood, Castaway)
    LEAGUE_PINNACLE_ARENA = "LEAGUE_PINNACLE_ARENA"     # Đấu trường mùa giải (Simulacrum, Domain of Timeless Conflict, Xesht)
    UNKNOWN = "UNKNOWN"


@dataclass(frozen=True)
class AtlasNodeProfile:
    """Hồ sơ tri thức đặc tính của một Node trên Atlas."""
    node_type: AtlasNodeType
    canonical_name: str
    aliases: Tuple[str, ...] = ()
    accepts_waystone: bool = False
    accepts_tablet: bool = False
    is_quest_node: bool = False
    quest_title: str = ""
    atlas_points_reward: int = 0
    activation_type: str = "SOCKET_WAYSTONE"  # "SOCKET_WAYSTONE" | "SOCKET_TABLET" | "DIRECT_TRAVERSE" | "SPECIAL_KEY"
    description: str = ""


# Bảng SSoT Tri Thức Danh Mục Các Node Đặc Biệt Trên Atlas POE2 v0.5.5+
_SPECIAL_NODES_CATALOG: Dict[AtlasNodeType, AtlasNodeProfile] = {
    AtlasNodeType.WELL_OF_SOULS: AtlasNodeProfile(
        node_type=AtlasNodeType.WELL_OF_SOULS,
        canonical_name="The Well of Souls",
        aliases=("WELL OF SOULS", "THE WELL OF SOULS", "WELL OF SOUL", "SOULS", "HEART OF THE WELL", "HEART OF WELL"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="DIRECT_TRAVERSE",
        description="Đền thờ trung tâm Atlas & Chế tác Hư Hoại (Heart of the Well). Không có khay Waystone/Tablet, mở cổng trực tiếp bằng nút Traverse.",
    ),
    AtlasNodeType.PRECURSOR_TOWER: AtlasNodeProfile(
        node_type=AtlasNodeType.PRECURSOR_TOWER,
        canonical_name="Precursor Tower",
        aliases=("PRECURSOR TOWER", "TOWER", "TOWERS", "TABLET TOWER"),
        accepts_waystone=False,
        accepts_tablet=True,
        is_quest_node=False,
        activation_type="SOCKET_TABLET",
        description="Tháp Tiền Thân. Nhận 1-3 Precursor Tablets để lan tỏa hào quang ảnh hưởng lên các map lân cận.",
    ),
    AtlasNodeType.QUEST_ENIGMA_CHAMBER: AtlasNodeProfile(
        node_type=AtlasNodeType.QUEST_ENIGMA_CHAMBER,
        canonical_name="Enigma Chamber",
        aliases=("ENIGMA CHAMBER", "WESTERN ENIGMA CHAMBER", "EASTERN ENIGMA CHAMBER", "ENIGMA"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=True,
        quest_title="Legacy of the Precursors",
        atlas_points_reward=1,
        activation_type="DIRECT_TRAVERSE",
        description="Nhiệm vụ Giải Mã Tiền Thân. Hoàn thành mở khóa các Precursor Towers và nhận +1 Điểm Nội Tại Atlas.",
    ),
    AtlasNodeType.QUEST_CORRUPTED_NEXUS: AtlasNodeProfile(
        node_type=AtlasNodeType.QUEST_CORRUPTED_NEXUS,
        canonical_name="Corrupted Nexus",
        aliases=("CORRUPTED NEXUS", "DORYANI'S SCIENCE", "NEXUS"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=True,
        quest_title="Doryani's Science",
        atlas_points_reward=1,
        activation_type="DIRECT_TRAVERSE",
        description="Nhiệm vụ Nghiên Cứu Doryani. Khảo sát cụm Hư Hoại và đánh bại thực thể biến dị nhận +1 Điểm Atlas.",
    ),
    AtlasNodeType.QUEST_GREAT_BEAST: AtlasNodeProfile(
        node_type=AtlasNodeType.QUEST_GREAT_BEAST,
        canonical_name="Great Beast Lair",
        aliases=("GREAT BEAST", "HILDA'S HUNTING", "SECOND GREAT BEAST", "FIRST GREAT BEAST"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=True,
        quest_title="Hilda's Hunting",
        atlas_points_reward=1,
        activation_type="DIRECT_TRAVERSE",
        description="Nhiệm vụ Thợ Săn Hilda. Tiêu diệt Quái Thú Cổ Đại mở khóa Beastcrafting và nhận +1 Điểm Atlas.",
    ),
    AtlasNodeType.QUEST_WITHERED_WILLOW: AtlasNodeProfile(
        node_type=AtlasNodeType.QUEST_WITHERED_WILLOW,
        canonical_name="The Withered Willow",
        aliases=("WITHERED WILLOW", "THE WITHERED WILLOW", "STRANGE REFLECTION"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=True,
        quest_title="Strange Reflection",
        atlas_points_reward=1,
        activation_type="DIRECT_TRAVERSE",
        description="Nhiệm vụ Tấm Gương Kỳ Lạ. Khám phá Cây Liễu Khô Héo nhận +1 Điểm Kỹ Năng Atlas.",
    ),
    AtlasNodeType.QUEST_KINGSMARCH_RUINS: AtlasNodeProfile(
        node_type=AtlasNodeType.QUEST_KINGSMARCH_RUINS,
        canonical_name="Ruins of Kingsmarch",
        aliases=("RUINS OF KINGSMARCH", "KINGSMARCH", "THE GRAND EXPEDITION"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=True,
        quest_title="The Grand Expedition",
        atlas_points_reward=1,
        activation_type="DIRECT_TRAVERSE",
        description="Nhiệm vụ Thám Hiểm Kingsmarch. Khảo sát tàn tích nhận cơ chế Expedition và +1 Điểm Atlas.",
    ),
    AtlasNodeType.CITADEL_BOSS: AtlasNodeProfile(
        node_type=AtlasNodeType.CITADEL_BOSS,
        canonical_name="Citadel",
        aliases=("CITADEL", "IRON CITADEL", "COPPER CITADEL", "STONE CITADEL"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="SPECIAL_KEY",
        description="Thành Lũy Boss Tối Cao. Khiêu chiến Thủ Hộ Giả mở khóa Tier 16 và mảnh chìa khóa Pinnacle.",
    ),
    AtlasNodeType.TRIAL_OF_SEKHEMAS: AtlasNodeProfile(
        node_type=AtlasNodeType.TRIAL_OF_SEKHEMAS,
        canonical_name="Trial of the Sekhemas",
        aliases=("TRIAL OF THE SEKHEMAS", "SEKHEMAS", "SEKHEMA", "TRIAL OF SEKHEMA"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=True,
        quest_title="Trial of the Sekhemas",
        atlas_points_reward=0,
        activation_type="SPECIAL_KEY",
        description="Đấu trường thử thách Sekhema. Nhận điểm Thăng hoa thứ 4 (Ascendancy 4th) hoặc Relics quý giá.",
    ),
    AtlasNodeType.GATEWAY_CHECKPOINT: AtlasNodeProfile(
        node_type=AtlasNodeType.GATEWAY_CHECKPOINT,
        canonical_name="Gateway Checkpoint",
        aliases=("GATEWAY", "WESTERN GATEWAY", "EASTERN GATEWAY", "NORTHERN GATEWAY", "SOUTHERN GATEWAY"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="DIRECT_TRAVERSE",
        description="Cửa ải / Cổng thành phân khu Atlas. Không nhận Waystone hay Tablet.",
    ),
    AtlasNodeType.NOTABLE_PASSIVE_SHRINE: AtlasNodeProfile(
        node_type=AtlasNodeType.NOTABLE_PASSIVE_SHRINE,
        canonical_name="Notable Passive Shrine",
        aliases=("SHRINE", "PASSIVE SHRINE", "NOTABLE SHRINE", "ALTAR"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="DIRECT_TRAVERSE",
        description="Đền thờ điểm nội tại Atlas. Mở giao diện Atlas Passive Skills, không cắm Waystone.",
    ),
    AtlasNodeType.BURNING_MONOLITH: AtlasNodeProfile(
        node_type=AtlasNodeType.BURNING_MONOLITH,
        canonical_name="The Burning Monolith",
        aliases=("BURNING MONOLITH", "THE BURNING MONOLITH", "BURNING", "MONOLITH", "ARBITER OF ASH"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="SPECIAL_KEY",
        description="Đấu trường Boss Cột Lửa Cổ Đại (Arbiter of Ash). Kích hoạt bằng 3 Crisis Fragments.",
    ),
    AtlasNodeType.ORIGIN_TOWER: AtlasNodeProfile(
        node_type=AtlasNodeType.ORIGIN_TOWER,
        canonical_name="Origin Tower",
        aliases=("ORIGIN TOWER", "THE ORIGIN TOWER", "ANCIENT FORTRESS", "ORIGIN"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="SPECIAL_KEY",
        description="Quần thể Tháp Cội Nguồn Ancient Fortress (v0.5.5+). Đấu trường Apex Boss tối thượng.",
    ),
    AtlasNodeType.PRECURSOR_REACTOR: AtlasNodeProfile(
        node_type=AtlasNodeType.PRECURSOR_REACTOR,
        canonical_name="Precursor Reactor",
        aliases=("PRECURSOR REACTOR", "THE PRECURSOR REACTOR", "REACTOR", "ARBITER OF DIVINITY"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="SPECIAL_KEY",
        description="Lò Phản Ứng Tiền Thân. Đấu trường Arbiter of Divinity, nạp Origin Spark & Origin Cradle.",
    ),
    AtlasNodeType.PATRIARCH_HALL: AtlasNodeProfile(
        node_type=AtlasNodeType.PATRIARCH_HALL,
        canonical_name="Patriarch Hall",
        aliases=("PATRIARCH HALL", "THE PATRIARCH HALL", "PATRIARCH"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="DIRECT_TRAVERSE",
        description="Sảnh Tộc Trưởng trong quần thể Tháp Cội Nguồn (Boss rớt Origin Spark).",
    ),
    AtlasNodeType.MATRIARCH_HALL: AtlasNodeProfile(
        node_type=AtlasNodeType.MATRIARCH_HALL,
        canonical_name="Matriarch Hall",
        aliases=("MATRIARCH HALL", "THE MATRIARCH HALL", "MATRIARCH"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="DIRECT_TRAVERSE",
        description="Sảnh Nữ Trưởng trong quần thể Tháp Cội Nguồn (Boss rớt Origin Cradle).",
    ),
    AtlasNodeType.TRIAL_OF_CHAOS: AtlasNodeProfile(
        node_type=AtlasNodeType.TRIAL_OF_CHAOS,
        canonical_name="Trial of Chaos",
        aliases=("TRIAL OF CHAOS", "THE TRIAL OF CHAOS", "TRIALMASTER", "CHAOS TRIAL"),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="SPECIAL_KEY",
        description="Đấu trường Thử Thách Hỗn Mang (The Trialmaster / Inscribed Ultimatum).",
    ),
    AtlasNodeType.LEAGUE_PINNACLE_ARENA: AtlasNodeProfile(
        node_type=AtlasNodeType.LEAGUE_PINNACLE_ARENA,
        canonical_name="League Pinnacle Arena",
        aliases=(
            "SIMULACRUM", "DOMAIN OF TIMELESS CONFLICT", "TIMELESS CONFLICT",
            "XESHT", "KING IN THE MISTS", "THE BODACH", "OLROTH",
        ),
        accepts_waystone=False,
        accepts_tablet=False,
        is_quest_node=False,
        activation_type="SPECIAL_KEY",
        description="Đấu trường Boss Tối Cao cơ chế mùa giải (Simulacrum, Timeless Conflict, Xesht, Bodach).",
    ),
    AtlasNodeType.UNIQUE_MAP: AtlasNodeProfile(
        node_type=AtlasNodeType.UNIQUE_MAP,
        canonical_name="Unique Map",
        aliases=(
            "UNTAINTED PARADISE", "MOMENT OF ZEN", "VAULTS OF KAMASA",
            "PHAARYL MEGALITH", "THE FRACTURED LAKE", "FRACTURED LAKE",
            "THE SILENT CAVE", "SILENT CAVE", "VIRIDIAN WILDWOOD", "CASTAWAY",
        ),
        accepts_waystone=True,
        accepts_tablet=False,
        is_quest_node=False,
        atlas_points_reward=2,
        activation_type="SOCKET_WAYSTONE",
        description="Bản đồ Độc Bản (8 Unique Maps POE2). Thưởng +2 Atlas points lần đầu, cấm chạy trong farm_whitelist tự hành.",
    ),
}
 
# Bảng danh mục alias sắp xếp theo độ dài giảm dần (Longest Match First)
# Ngăn chặn xung đột giữa các từ khóa ngắn (như TOWER) với các cụm từ cụ thể (như ORIGIN TOWER)
_SORTED_ALIAS_CATALOG: List[Tuple[str, AtlasNodeProfile]] = sorted(
    [
        (alias, profile)
        for profile in _SPECIAL_NODES_CATALOG.values()
        for alias in profile.aliases
    ],
    key=lambda item: len(item[0]),
    reverse=True,
)


class AtlasKnowledgeBase:
    """Hạt nhân Tri Thức Atlas (Atlas Knowledge Engine).
    
    Cung cấp các phương thức thẩm định loại Node, kiểm tra tương thích Waystone/Tablet
    và định hướng hành vi cho các tầng điều phối tự hành.
    """

    @staticmethod
    def classify_node(name_or_text: str) -> AtlasNodeProfile:
        """Phân loại một Node trên Atlas dựa trên chuỗi OCR văn bản hoặc tên node."""
        if not name_or_text:
            return AtlasKnowledgeBase._create_regular_map_profile("Unknown Map")

        text_upper = name_or_text.upper().strip()

        # 1. Kiểm tra đối soát với Danh mục Node Đặc Biệt (Longest Match First)
        for alias, profile in _SORTED_ALIAS_CATALOG:
            if alias in text_upper:
                return profile

        # 2. Kiểm tra từ khóa Tháp Tiền Thân cụ thể
        if "PRECURSOR TOWER" in text_upper or "TABLET TOWER" in text_upper:
            return _SPECIAL_NODES_CATALOG[AtlasNodeType.PRECURSOR_TOWER]

        # 3. Mặc định là Bản đồ Cày Thông Thường (Regular Waystone Map)
        return AtlasKnowledgeBase._create_regular_map_profile(name_or_text.strip())

    @staticmethod
    def _create_regular_map_profile(name: str) -> AtlasNodeProfile:
        return AtlasNodeProfile(
            node_type=AtlasNodeType.REGULAR_WAYSTONE_MAP,
            canonical_name=name,
            aliases=(name.upper(),),
            accepts_waystone=True,
            accepts_tablet=False,
            is_quest_node=False,
            quest_title="",
            atlas_points_reward=1,
            activation_type="SOCKET_WAYSTONE",
            description="Bản đồ cày thông thường (Tier 1-16). Cắm 1 Waystone để mở 6 cổng Portal.",
        )

    @staticmethod
    def accepts_waystone(name_or_text: str) -> bool:
        """Kiểm tra xem node này có cho phép nạp Waystone hay không."""
        profile = AtlasKnowledgeBase.classify_node(name_or_text)
        return profile.accepts_waystone

    @staticmethod
    def accepts_tablet(name_or_text: str) -> bool:
        """Kiểm tra xem node này có cho phép nạp Precursor Tablet hay không."""
        profile = AtlasKnowledgeBase.classify_node(name_or_text)
        return profile.accepts_tablet

    @staticmethod
    def is_quest_node(name_or_text: str) -> bool:
        """Kiểm tra xem node này có phải là mục tiêu nhiệm vụ mở điểm Atlas hay không."""
        profile = AtlasKnowledgeBase.classify_node(name_or_text)
        return profile.is_quest_node

    @staticmethod
    def is_unique_map(name_or_text: str) -> bool:
        """Kiểm tra xem node có phải là 1 trong 8 bản đồ độc bản Unique Maps hay không."""
        profile = AtlasKnowledgeBase.classify_node(name_or_text)
        return profile.node_type == AtlasNodeType.UNIQUE_MAP

    @staticmethod
    def is_forbidden_for_waystone_farming(name_or_text: str) -> bool:
        """Kiểm tra xem node có bị cấm trong chu trình cày Waystone tự động hay không (INV-ATLAS-FARM-NODE).
        
        Bất biến kiến trúc SSoT:
        1. Node không nhận Waystone (accepts_waystone == False): BẮT BUỘC cấm (Well of Souls/Heart of the Well,
           Burning Monolith, Origin Tower, Precursor Reactor, Trials, Shrines, Gateways...).
        2. Unique Maps (8 bản đồ độc bản): BẮT BUỘC cấm trong farm_whitelist để tránh lãng phí bản đồ
           độc bản không lặp lại hoặc vướng cơ chế không có quái / không có đồ / 10 boss liên tục.
        3. Citadel Bosses: BẮT BUỘC cấm trong cày thường để bảo vệ tính mạng nhân vật (one-life challenge).
        4. The Burning Monolith (Arbiter of Ash): Tuyệt đối cấm trong farm Waystone (INV-ATLAS-FARM-NODE).
        """
        if not name_or_text:
            return False
        profile = AtlasKnowledgeBase.classify_node(name_or_text)
        if not profile.accepts_waystone:
            return True
        if profile.node_type in (
            AtlasNodeType.UNIQUE_MAP,
            AtlasNodeType.CITADEL_BOSS,
            AtlasNodeType.BURNING_MONOLITH,
        ):
            return True
        text_upper = name_or_text.upper().strip()
        if "HIDEOUT" in text_upper or "TOWN" in text_upper:
            return True
        if "BURNING MONOLITH" in text_upper or "ARBITER OF ASH" in text_upper:
            return True
        return False

    @staticmethod
    def get_all_quest_nodes() -> List[AtlasNodeProfile]:
        """Trả về toàn bộ danh sách các Node nhiệm vụ mở điểm Atlas."""
        return [p for p in _SPECIAL_NODES_CATALOG.values() if p.is_quest_node]
