"""
FreeExile Meridian Passive Tree Types & Data Contracts (Server-Authoritative).
Defines Acupoints (Tiểu Huyệt, Trung Huyệt, Keystone, Jewel Socket),
Linh Thạch (Jewels), and persistent progression states for Huyết Cốt Ma Đồ.
"""

from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
from typing import Dict, List, Optional, Set, Tuple


class MeridianNodeType(str, Enum):
    ORIGIN = "ORIGIN"            # Khởi Nguyên (Gốc Đản Trung)
    VESSEL = "VESSEL"            # Tiểu Huyệt căn bản (Minor Node)
    MAJOR = "MAJOR"              # Trung Huyệt / Cực Huyệt (Notable Node)
    KEYSTONE = "KEYSTONE"        # Nghịch Mệnh Đại Huyệt (Keystone)
    JEWEL_SOCKET = "JEWEL_SOCKET"# Linh Cốt Khảm Tọa (Jewel Socket)


class MeridianElement(str, Enum):
    KIM = "KIM"
    MOC = "MOC"
    THUY = "THUY"
    HOA = "HOA"
    THO = "THO"
    UNIVERSAL = "UNIVERSAL"


@dataclass(slots=True, frozen=True)
class MeridianStatBonus:
    """Immutable stat modifiers granted by an individual acupoint or aggregated tree."""
    hp: int = 0
    mp: int = 0
    dps: float = 0.0
    dps_mult: float = 0.0
    crit_rate: float = 0.0
    crit_dmg: float = 0.0
    armor: int = 0
    evasion: float = 0.0
    life_leech: float = 0.0
    armor_pen: float = 0.0
    attack_speed: float = 0.0
    resist: float = 0.0
    dmg_reduction: float = 0.0

    def combine(self, other: MeridianStatBonus) -> MeridianStatBonus:
        """Combines two stat bonuses into a single aggregated bonus."""
        return MeridianStatBonus(
            hp=self.hp + other.hp,
            mp=self.mp + other.mp,
            dps=round(self.dps + other.dps, 2),
            dps_mult=round(self.dps_mult + other.dps_mult, 4),
            crit_rate=round(self.crit_rate + other.crit_rate, 4),
            crit_dmg=round(self.crit_dmg + other.crit_dmg, 4),
            armor=self.armor + other.armor,
            evasion=round(self.evasion + other.evasion, 4),
            life_leech=round(self.life_leech + other.life_leech, 4),
            armor_pen=round(self.armor_pen + other.armor_pen, 4),
            attack_speed=round(self.attack_speed + other.attack_speed, 4),
            resist=round(self.resist + other.resist, 2),
            dmg_reduction=round(self.dmg_reduction + other.dmg_reduction, 4),
        )


@dataclass(slots=True, frozen=True)
class JewelItemDef:
    """Immutable definition of a Linh Thạch (Jewel) socketable into Ma Đồ."""
    jewel_id: str
    name: str
    rarity: str  # NORMAL, MAGIC, RARE, UNIQUE
    element: MeridianElement
    icon: str
    stats: MeridianStatBonus
    lore: str
    stat_display: Tuple[str, ...] = ()


@dataclass(slots=True, frozen=True)
class MeridianNodeDef:
    """Immutable definition of an acupoint on the Huyết Cốt Ma Đồ constellation."""
    node_id: str
    name: str
    meridian: str
    title: str
    node_type: MeridianNodeType
    element: MeridianElement
    cluster: str
    lore: str
    stats: MeridianStatBonus
    x: float = 0.0
    y: float = 0.0
    stat_display: Tuple[str, ...] = ()


@dataclass(slots=True)
class PlayerMeridianState:
    """Server-authoritative state for a player's meridian passive progression."""
    player_id: str
    available_points: int = 5
    spent_points: int = 0
    unlocked_nodes: Set[str] = field(default_factory=set)
    socketed_jewels: Dict[str, JewelItemDef] = field(default_factory=dict)
    last_updated_at: float = 0.0


@dataclass(slots=True, frozen=True)
class MeridianUnlockResult:
    """Result of an authoritative meridian acupoint allocation request."""
    success: bool
    node_id: str
    message: str
    available_points: int
    unlocked_nodes: Tuple[str, ...]
    aggregated_stats: MeridianStatBonus


@dataclass(slots=True, frozen=True)
class MeridianResetResult:
    """Result of a meridian tree refund/reset action (Tẩy Tủy Hoàn Điểm)."""
    success: bool
    refunded_points: int
    available_points: int
    message: str


@dataclass(slots=True, frozen=True)
class MeridianSocketResult:
    """Result of socketing a Linh Thạch (Jewel) into an unlocked socket."""
    success: bool
    socket_id: str
    jewel_id: str
    message: str
    aggregated_stats: MeridianStatBonus


@dataclass(slots=True, frozen=True)
class MeridianUnsocketResult:
    """Result of removing a Linh Thạch (Jewel) from an acupoint socket."""
    success: bool
    socket_id: str
    removed_jewel_id: str
    message: str
    aggregated_stats: MeridianStatBonus
