# game_state.py : structures de donnees broadcastees au client a chaque tick

from dataclasses import dataclass, field


@dataclass
class ProjectileState:
    id: str
    owner_id: str
    x: float
    y: float
    vx: float
    vy: float
    damage: int
    radius: float
    ttl: float

    def to_dict(self):
        # vx/vy/damage/ttl : info serveur, pas envoyes au client
        return {
            "id":     self.id,
            "owner":  self.owner_id,
            "x":      self.x,
            "y":      self.y,
            "radius": self.radius,
        }


@dataclass
class EnemyState:
    id: str
    type: str
    x: float
    y: float
    hp: int
    max_hp: int
    attack_cooldown: float = 0.0
    is_boss: bool = False
    frozen_timer: float = 0.0  # gel du sort divin Seris
    data: dict = field(default_factory=dict)  # interne au boss (phases, charge), pas broadcast

    def to_dict(self):
        return {
            "id":         self.id,
            "type":       self.type,
            "x":          self.x,
            "y":          self.y,
            "hp":         self.hp,
            "max_hp":     self.max_hp,
            "is_boss":    self.is_boss,
            "frozen":     self.frozen_timer > 0,
            "is_charging": self.data.get("is_charging", False) if self.is_boss else False,
        }


@dataclass
class PlayerState:
    id: str
    class_name: str
    username: str
    x: float
    y: float
    hp: int
    max_hp: int
    alive: bool

    revive_progress: float = 0.0

    cooldowns: dict = field(default_factory=lambda: {
        "attack": 0,
        "ability_1": 0,
        "ability_2": 0,
        "displacement": 0,
    })

    # buffs actifs : {"type": "...", "timer": float, ...}
    # types : invulnerable, intangible, flying, casting, damage_mult, speed_mult, combat_buff, divine_freeze_dps
    buffs: list = field(default_factory=list)

    souls: int = 0
    enemies_killed: int = 0

    # upgrade_id -> nb stacks (damage_up, cooldown_down, hp_up, speed_up)
    upgrades: dict = field(default_factory=dict)

    def to_dict(self):
        return {
            "id": self.id,
            "class": self.class_name,
            "username": self.username,
            "x": self.x,
            "y": self.y,
            "hp": self.hp,
            "max_hp": self.max_hp,
            "alive": self.alive,
            "revive_progress": self.revive_progress,
            "cooldowns": self.cooldowns,
            "buffs": self.buffs,
            "souls": self.souls,
            "enemies_killed": self.enemies_killed,
            "upgrades": self.upgrades,
        }


@dataclass
class AoeZone:
    id: str
    owner_id: str
    zone_type: str
    x: float
    y: float
    radius: float
    damage_per_tick: int
    ticks_remaining: int
    max_ticks: int

    def to_dict(self):
        return {
            "id":    self.id,
            "type":  self.zone_type,
            "x":     self.x,
            "y":     self.y,
            "radius": self.radius,
            "ticks": self.ticks_remaining,
            "max_ticks": self.max_ticks,
        }


@dataclass
class SoulgateState:
    hp: int
    max_hp: int

    def to_dict(self):
        return {"hp": self.hp, "max_hp": self.max_hp}


@dataclass
class WaveState:
    number: int
    phase: int
    enemies_remaining: int
    state: str  # combat | preparation | boss | victory
    prep_timer: float = 0.0
    boss_hp: int = 0
    boss_max_hp: int = 0
    boss_name: str = ""

    def to_dict(self):
        return {
            "number": self.number,
            "phase": self.phase,
            "enemies_remaining": self.enemies_remaining,
            "state": self.state,
            "prep_timer": self.prep_timer,
            "boss_hp": self.boss_hp,
            "boss_max_hp": self.boss_max_hp,
            "boss_name": self.boss_name,
        }


@dataclass
class GameState:
    tick: int
    players: list
    enemies: list
    projectiles: list
    soulgate: SoulgateState
    wave: WaveState
    effects: list
    aoe_zones: list = field(default_factory=list)

    def to_dict(self):
        return {
            "type": "game_state",
            "tick": self.tick,
            "players": [p.to_dict() for p in self.players],
            "enemies": [e.to_dict() for e in self.enemies],
            "projectiles": [p.to_dict() for p in self.projectiles],
            "aoe_zones": [z.to_dict() for z in self.aoe_zones],
            "soulgate": self.soulgate.to_dict(),
            "wave": self.wave.to_dict(),
            "effects": self.effects,
        }
