"""AutoPOE2 - Mod Tier Patterns & High-Value Stat Definitions (Doc 29 / Doc 68).
=============================================================================
Định nghĩa các mẫu regex nhận diện chỉ số vật phẩm, phân hạng Tier (T1, T2, T3)
và tính điểm trọng số cho các dòng thuộc tính giá trị cao trong Path of Exile 2:
- Máu & Lá Chắn Năng Lượng (Tier 1 Life / Energy Shield).
- Cấp độ Kỹ Năng (+Skill Gems: All / Spell / Melee / Element / Chaos).
- Kháng Nguyên Tố & Hỗn Loạn (High Single & Pseudo Total Resistances).
- Sát Thương Chí Mạng (Global Critical Strike Multiplier).
- Sát Thương Vũ Khí (High Physical & Elemental DPS, Attack Speed).
- Thuộc Tính Tiện Ích Đỉnh Cao (Movement Speed >= 30%, Spell Suppression >= 12%).

Tuân thủ nghiêm ngặt:
- Rule 1: Python 3.11 Cold Path Tier 2.
- Rule 4: Module hóa độc lập trần file < 500 dòng.
- Rule 16: Google Docstrings chuẩn mực.
"""

from __future__ import annotations

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


class ItemEvaluationAction(str, Enum):
    """Quyết định phân loại vật phẩm."""
    KEEP = "KEEP"        # Giữ lại dùng / Món đồ giá trị cực cao (God Roll / 3+ T1)
    STASH = "STASH"      # Cất hòm để bán sàn hoặc chế đồ (2+ T1/T2, đồ có giá trị)
    VENDOR = "VENDOR"    # Bán NPC lấy vàng / đồ rác không có giá trị


class ModCategory(str, Enum):
    """Nhóm phân loại dòng thuộc tính."""
    LIFE = "LIFE"
    ENERGY_SHIELD = "ENERGY_SHIELD"
    SKILL_GEMS = "SKILL_GEMS"
    RESISTANCE = "RESISTANCE"
    CRITICAL = "CRITICAL"
    WEAPON_PHYS = "WEAPON_PHYS"
    WEAPON_ELE = "WEAPON_ELE"
    ATTACK_SPEED = "ATTACK_SPEED"
    CAST_SPEED = "CAST_SPEED"
    MOVE_SPEED = "MOVE_SPEED"
    SPELL_SUPPRESSION = "SPELL_SUPPRESSION"
    WAYSTONE_AFFIX = "WAYSTONE_AFFIX"
    JUNK = "JUNK"
    OTHER = "OTHER"


@dataclass
class EvaluatedMod:
    """Thuộc tính vật phẩm đã được bóc tách và định giá."""
    raw_text: str
    category: ModCategory
    name: str
    value: float = 0.0
    tier_estimate: int = 99
    score: float = 0.0
    is_tier_1: bool = False
    details: str = ""


# ==============================================================================
# BẢNG MẪU REGEX BÓC TÁCH VÀ ĐỊNH HẠNG TIERS
# ==============================================================================

RE_SKILL_GEMS = re.compile(
    r"\+(\d+)\s+to\s+Level\s+of\s+all\s+([A-Za-z\s]+?)\s+Skill\s+Gems",
    re.IGNORECASE,
)
RE_SOCKETED_GEMS = re.compile(
    r"\+(\d+)\s+to\s+Level\s+of\s+Socketed\s+([A-Za-z\s]+?)\s+Gems",
    re.IGNORECASE,
)

RE_MAX_LIFE = re.compile(r"\+(\d+)\s+to\s+maximum\s+Life", re.IGNORECASE)
RE_FLAT_ES = re.compile(r"\+(\d+)\s+to\s+maximum\s+Energy\s+Shield", re.IGNORECASE)
RE_PERCENT_ES = re.compile(r"(\d+)%\s+increased\s+Energy\s+Shield", re.IGNORECASE)

RE_FIRE_RES = re.compile(r"\+(\d+)%\s+to\s+Fire\s+Resistance", re.IGNORECASE)
RE_COLD_RES = re.compile(r"\+(\d+)%\s+to\s+Cold\s+Resistance", re.IGNORECASE)
RE_LIGHTNING_RES = re.compile(r"\+(\d+)%\s+to\s+Lightning\s+Resistance", re.IGNORECASE)
RE_CHAOS_RES = re.compile(r"\+(\d+)%\s+to\s+Chaos\s+Resistance", re.IGNORECASE)
RE_ALL_ELE_RES = re.compile(r"\+(\d+)%\s+to\s+all\s+Elemental\s+Resistances", re.IGNORECASE)

RE_CRIT_MULTI = re.compile(r"\+(\d+)%\s+to\s+Global\s+Critical\s+Strike\s+Multiplier", re.IGNORECASE)
RE_CRIT_CHANCE = re.compile(r"(\d+)%\s+increased\s+Global\s+Critical\s+Strike\s+Chance", re.IGNORECASE)

RE_MOVE_SPEED = re.compile(r"\+(\d+)%\s+increased\s+Movement\s+Speed", re.IGNORECASE)
RE_SPELL_SUPPRESS = re.compile(r"\+(\d+)%\s+chance\s+to\s+Suppress\s+Spell\s+Damage", re.IGNORECASE)

RE_PHYS_PERCENT = re.compile(r"(\d+)%\s+increased\s+Physical\s+Damage", re.IGNORECASE)
RE_PHYS_FLAT = re.compile(r"Adds\s+(\d+)\s+to\s+(\d+)\s+Physical\s+Damage", re.IGNORECASE)
RE_ATTACK_SPEED = re.compile(r"(\d+)%\s+increased\s+Attack\s+Speed", re.IGNORECASE)
RE_CAST_SPEED = re.compile(r"(\d+)%\s+increased\s+Cast\s+Speed", re.IGNORECASE)

RE_ELE_FLAT_FIRE = re.compile(r"Adds\s+(\d+)\s+to\s+(\d+)\s+Fire\s+Damage", re.IGNORECASE)
RE_ELE_FLAT_COLD = re.compile(r"Adds\s+(\d+)\s+to\s+(\d+)\s+Cold\s+Damage", re.IGNORECASE)
RE_ELE_FLAT_LIGHTNING = re.compile(r"Adds\s+(\d+)\s+to\s+(\d+)\s+Lightning\s+Damage", re.IGNORECASE)

# Waystone affixes
RE_WAYSTONE_PACK_SIZE = re.compile(r"(\d+)%\s+increased\s+Monster\s+Pack\s+Size", re.IGNORECASE)
RE_WAYSTONE_QUANTITY = re.compile(r"(\d+)%\s+increased\s+Quantity\s+of\s+Items", re.IGNORECASE)
RE_WAYSTONE_DROP_CHANCE = re.compile(r"Waystone\s+Drop\s+Chance:\s*\+?(\d+)%", re.IGNORECASE)
RE_WAYSTONE_MONSTER_RARITY = re.compile(r"Monster\s+Rarity:\s*\+?(\d+)%", re.IGNORECASE)

# Junk / Low-value mod patterns
RE_JUNK_MODS = [
    re.compile(r"(\d+)%\s+increased\s+Light\s+Radius", re.IGNORECASE),
    re.compile(r"(\d+)%\s+increased\s+Stun\s+and\s+Block\s+Recovery", re.IGNORECASE),
    re.compile(r"Reflects\s+(\d+)\s+Physical\s+Damage\s+to\s+Melee\s+Attackers", re.IGNORECASE),
    re.compile(r"\+(\d+)\s+to\s+maximum\s+Mana", re.IGNORECASE),
    re.compile(r"(\d+)%\s+increased\s+Mana\s+Regeneration\s+Rate", re.IGNORECASE),
]


def classify_single_mod_line(line_text: str) -> Optional[EvaluatedMod]:
    """Phân loại và tính điểm cho một dòng thuộc tính từ Tooltip text.

    Args:
        line_text: Chuỗi văn bản thuộc tính (đã được strip).

    Returns:
        EvaluatedMod nếu nhận diện được, hoặc None nếu là dòng rác không có ý nghĩa.
    """
    cleaned = line_text.strip()
    if not cleaned or cleaned.startswith("----") or cleaned.startswith("Item Class") or cleaned.startswith("Rarity"):
        return None

    # 1. +Skill Gems (Giá trị hàng đầu)
    m = RE_SKILL_GEMS.search(cleaned)
    if m:
        lvl = float(m.group(1))
        gem_type = m.group(2).strip()
        score = 65.0 if lvl >= 2.0 else 40.0
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.SKILL_GEMS,
            name=f"+{int(lvl)} to Level of all {gem_type} Skill Gems",
            value=lvl,
            tier_estimate=1,
            score=score,
            is_tier_1=True,
            details=f"Top-tier skill scaling (+{int(lvl)} {gem_type})",
        )

    m = RE_SOCKETED_GEMS.search(cleaned)
    if m:
        lvl = float(m.group(1))
        gem_type = m.group(2).strip()
        score = 45.0 if lvl >= 2.0 else 25.0
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.SKILL_GEMS,
            name=f"+{int(lvl)} to Level of Socketed {gem_type} Gems",
            value=lvl,
            tier_estimate=1 if lvl >= 2.0 else 2,
            score=score,
            is_tier_1=(lvl >= 2.0),
            details="Socketed skill gems bonus",
        )

    # 2. Máu (Maximum Life)
    m = RE_MAX_LIFE.search(cleaned)
    if m:
        val = float(m.group(1))
        if val >= 100.0:
            tier = 1
            score = 25.0
        elif val >= 80.0:
            tier = 2
            score = 18.0
        elif val >= 50.0:
            tier = 3
            score = 10.0
        else:
            tier = 4
            score = 3.0
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.LIFE,
            name="Maximum Life",
            value=val,
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"Life roll {int(val)} (T{tier})",
        )

    # 3. Lá Chắn Năng Lượng (Energy Shield)
    m = RE_FLAT_ES.search(cleaned)
    if m:
        val = float(m.group(1))
        tier = 1 if val >= 80.0 else (2 if val >= 50.0 else 3)
        score = 22.0 if tier == 1 else (15.0 if tier == 2 else 7.0)
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.ENERGY_SHIELD,
            name="Flat Energy Shield",
            value=val,
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"Flat ES {int(val)} (T{tier})",
        )

    m = RE_PERCENT_ES.search(cleaned)
    if m:
        val = float(m.group(1))
        tier = 1 if val >= 80.0 else (2 if val >= 50.0 else 3)
        score = 24.0 if tier == 1 else (16.0 if tier == 2 else 8.0)
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.ENERGY_SHIELD,
            name="% increased Energy Shield",
            value=val,
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"%ES {int(val)}% (T{tier})",
        )

    # 4. Kháng Nguyên Tố & Hỗn Loạn (Resistances)
    for res_name, regex, is_chaos in [
        ("Fire Resistance", RE_FIRE_RES, False),
        ("Cold Resistance", RE_COLD_RES, False),
        ("Lightning Resistance", RE_LIGHTNING_RES, False),
        ("Chaos Resistance", RE_CHAOS_RES, True),
    ]:
        m = regex.search(cleaned)
        if m:
            val = float(m.group(1))
            if is_chaos:
                tier = 1 if val >= 30.0 else (2 if val >= 20.0 else (3 if val >= 12.0 else 4))
                score = 28.0 if tier == 1 else (20.0 if tier == 2 else (12.0 if tier == 3 else 4.0))
            else:
                tier = 1 if val >= 40.0 else (2 if val >= 30.0 else (3 if val >= 20.0 else 4))
                score = 20.0 if tier == 1 else (14.0 if tier == 2 else (8.0 if tier == 3 else 2.0))
            return EvaluatedMod(
                raw_text=cleaned,
                category=ModCategory.RESISTANCE,
                name=res_name,
                value=val,
                tier_estimate=tier,
                score=score,
                is_tier_1=(tier == 1),
                details=f"{res_name} {int(val)}% (T{tier})",
            )

    m = RE_ALL_ELE_RES.search(cleaned)
    if m:
        val = float(m.group(1))
        tier = 1 if val >= 14.0 else 2
        score = 25.0 if tier == 1 else 15.0
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.RESISTANCE,
            name="All Elemental Resistances",
            value=val * 3.0,  # Quy đổi tổng 3 kháng
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"All Ele Res +{int(val)}% (equiv {int(val*3)}% total)",
        )

    # 5. Sát Thương Chí Mạng (Critical Multiplier)
    m = RE_CRIT_MULTI.search(cleaned)
    if m:
        val = float(m.group(1))
        tier = 1 if val >= 24.0 else (2 if val >= 18.0 else 3)
        score = 25.0 if tier == 1 else (18.0 if tier == 2 else 10.0)
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.CRITICAL,
            name="Global Critical Strike Multiplier",
            value=val,
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"Crit Multi +{int(val)}% (T{tier})",
        )

    # 6. Tốc Độ Di Chuyển & Né Tránh Phép (Movement Speed & Spell Suppression)
    m = RE_MOVE_SPEED.search(cleaned)
    if m:
        val = float(m.group(1))
        tier = 1 if val >= 30.0 else (2 if val >= 25.0 else 3)
        score = 30.0 if tier == 1 else (20.0 if tier == 2 else 10.0)
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.MOVE_SPEED,
            name="Movement Speed",
            value=val,
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"Movement Speed +{int(val)}% (T{tier})",
        )

    m = RE_SPELL_SUPPRESS.search(cleaned)
    if m:
        val = float(m.group(1))
        tier = 1 if val >= 14.0 else (2 if val >= 10.0 else 3)
        score = 24.0 if tier == 1 else (16.0 if tier == 2 else 8.0)
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.SPELL_SUPPRESSION,
            name="Spell Suppression",
            value=val,
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"Spell Suppression +{int(val)}% (T{tier})",
        )

    # 7. Sát Thương Vật Lý & Tốc Độ Đánh Vũ Khí (Weapon Physical & Speed)
    m = RE_PHYS_PERCENT.search(cleaned)
    if m:
        val = float(m.group(1))
        tier = 1 if val >= 120.0 else (2 if val >= 80.0 else 3)
        score = 28.0 if tier == 1 else (18.0 if tier == 2 else 8.0)
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.WEAPON_PHYS,
            name="% increased Physical Damage",
            value=val,
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"%Phys {int(val)}% (T{tier})",
        )

    m = RE_PHYS_FLAT.search(cleaned)
    if m:
        min_p = float(m.group(1))
        max_p = float(m.group(2))
        avg_p = (min_p + max_p) * 0.5
        tier = 1 if max_p >= 25.0 else (2 if max_p >= 16.0 else 3)
        score = 25.0 if tier == 1 else (16.0 if tier == 2 else 8.0)
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.WEAPON_PHYS,
            name="Flat Physical Damage",
            value=avg_p,
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"Flat Phys {int(min_p)}-{int(max_p)} (T{tier})",
        )

    m = RE_ATTACK_SPEED.search(cleaned)
    if m:
        val = float(m.group(1))
        tier = 1 if val >= 18.0 else (2 if val >= 12.0 else 3)
        score = 22.0 if tier == 1 else (14.0 if tier == 2 else 7.0)
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.ATTACK_SPEED,
            name="Attack Speed",
            value=val,
            tier_estimate=tier,
            score=score,
            is_tier_1=(tier == 1),
            details=f"Attack Speed +{int(val)}% (T{tier})",
        )

    # 8. Sát Thương Nguyên Tố Vũ Khí (Flat Elemental Damage)
    for ele_name, regex in [
        ("Flat Fire Damage", RE_ELE_FLAT_FIRE),
        ("Flat Cold Damage", RE_ELE_FLAT_COLD),
        ("Flat Lightning Damage", RE_ELE_FLAT_LIGHTNING),
    ]:
        m = regex.search(cleaned)
        if m:
            min_e = float(m.group(1))
            max_e = float(m.group(2))
            avg_e = (min_e + max_e) * 0.5
            tier = 1 if max_e >= 40.0 else (2 if max_e >= 25.0 else 3)
            score = 20.0 if tier == 1 else (12.0 if tier == 2 else 6.0)
            return EvaluatedMod(
                raw_text=cleaned,
                category=ModCategory.WEAPON_ELE,
                name=ele_name,
                value=avg_e,
                tier_estimate=tier,
                score=score,
                is_tier_1=(tier == 1),
                details=f"{ele_name} {int(min_e)}-{int(max_e)} (T{tier})",
            )

    # 9. Waystone Specific Affixes
    m = RE_WAYSTONE_PACK_SIZE.search(cleaned)
    if m:
        val = float(m.group(1))
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.WAYSTONE_AFFIX,
            name="Monster Pack Size",
            value=val,
            tier_estimate=1 if val >= 25.0 else 2,
            score=20.0 if val >= 25.0 else 12.0,
            is_tier_1=(val >= 25.0),
            details=f"Pack Size +{int(val)}%",
        )

    m = RE_WAYSTONE_DROP_CHANCE.search(cleaned)
    if m:
        val = float(m.group(1))
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.WAYSTONE_AFFIX,
            name="Waystone Drop Chance",
            value=val,
            tier_estimate=1 if val >= 50.0 else 2,
            score=25.0 if val >= 50.0 else 15.0,
            is_tier_1=(val >= 50.0),
            details=f"Waystone Drop Chance +{int(val)}%",
        )

    m = RE_WAYSTONE_MONSTER_RARITY.search(cleaned)
    if m:
        val = float(m.group(1))
        return EvaluatedMod(
            raw_text=cleaned,
            category=ModCategory.WAYSTONE_AFFIX,
            name="Monster Rarity",
            value=val,
            tier_estimate=1 if val >= 15.0 else 2,
            score=15.0 if val >= 15.0 else 8.0,
            is_tier_1=(val >= 15.0),
            details=f"Monster Rarity +{int(val)}%",
        )

    # 10. Junk Mods
    for junk_pattern in RE_JUNK_MODS:
        if junk_pattern.search(cleaned):
            return EvaluatedMod(
                raw_text=cleaned,
                category=ModCategory.JUNK,
                name="Junk Mod",
                value=0.0,
                tier_estimate=99,
                score=-5.0,
                is_tier_1=False,
                details="Low utility / vendor filler mod",
            )

    # Dòng thuộc tính khác (chưa đặc biệt hóa)
    return EvaluatedMod(
        raw_text=cleaned,
        category=ModCategory.OTHER,
        name=cleaned[:30],
        value=0.0,
        tier_estimate=4,
        score=2.0,
        is_tier_1=False,
        details="Standard modifier",
    )
