"""
FreeExile Zone, Instance, and Secret Chamber Types and Enums.
Strictly typed dataclasses and domain enums for world spatial architecture.
"""

from __future__ import annotations
from enum import Enum
from typing import Dict, List, Optional
from dataclasses import dataclass, field
from server.world.spatial_grid import SpatialGrid


class ZoneType(Enum):
    SANCTUARY = "SANCTUARY"            # Safe haven, zero-PvP, merchants, vault, crafting
    OPEN_WORLD = "OPEN_WORLD"          # Exploration wild zone, monsters, bosses, hazards
    DUNGEON_INSTANCE = "DUNGEON_INSTANCE"  # Isolated layered challenge (party/solo)
    SECRET_CHAMBER = "SECRET_CHAMBER"  # Cryptic one-time discovery realm with auto-collapse


class ZoneEnvironment(Enum):
    NORMAL = "NORMAL"
    SANDSTORM = "SANDSTORM"            # Reduced visibility, movement penalty
    MIASMA_TOXIC = "MIASMA_TOXIC"      # Health drain without proper antidote/dantian
    FREEZING_CHILL = "FREEZING_CHILL"  # Attack/cast speed slowed
    SCORCHING_HEAT = "SCORCHING_HEAT"  # Periodic fire damage
    VOID_CORRUPTION = "VOID_CORRUPTION"# Space distortion, unpredictable elite auras


@dataclass(slots=True, frozen=True)
class Waypoint:
    waypoint_id: str
    name: str
    zone_id: str
    x: float
    y: float
    z: float = 0.0
    is_unlocked_by_default: bool = False
    discovery_radius: float = 15.0
    safe_radius: float = 8.0


@dataclass(slots=True, frozen=True)
class ZonePortal:
    portal_id: str
    name: str
    source_zone_id: str
    source_x: float
    source_y: float
    target_zone_id: str
    target_x: float
    target_y: float
    min_level: int = 1
    required_quest_id: Optional[str] = None
    interaction_radius: float = 8.0


@dataclass(slots=True, frozen=True)
class ZoneDefinition:
    zone_id: str
    name: str
    zone_type: ZoneType
    environment: ZoneEnvironment
    min_level: int
    max_players: int
    bounds_width: float
    bounds_height: float
    default_spawn_x: float
    default_spawn_y: float
    respawn_zone_id: str
    respawn_x: float
    respawn_y: float
    max_level: int = 100
    waypoints: Dict[str, Waypoint] = field(default_factory=dict)
    portals: Dict[str, ZonePortal] = field(default_factory=dict)
    npc_ids: List[str] = field(default_factory=list)

    @property
    def display_name(self) -> str:
        """Alias for name attribute to maintain compatibility."""
        return self.name


@dataclass(slots=True)
class PlayerLocation:
    player_id: str
    zone_id: str
    x: float
    y: float
    z: float = 0.0
    instance_id: Optional[str] = None
    last_update_timestamp_ms: int = 0


@dataclass(slots=True, frozen=True)
class DungeonTemplate:
    template_id: str
    name: str
    min_level: int
    max_layers: int
    max_party_size: int
    time_limit_sec: int
    revive_lives: int
    required_quest_id: Optional[str] = None
    boss_monster_id: Optional[str] = None
    bounds_width: float = 1000.0
    bounds_height: float = 1000.0


@dataclass(slots=True)
class InstanceSession:
    instance_id: str
    template_id: str
    instance_zone_id: str
    leader_player_id: str
    member_player_ids: List[str]
    current_layer: int
    max_layers: int
    lives_remaining: int
    time_limit_sec: int
    start_timestamp_ms: int
    is_completed: bool = False
    is_failed: bool = False
    spatial_grid: SpatialGrid = field(default_factory=SpatialGrid)

    @property
    def all_players(self) -> List[str]:
        return [self.leader_player_id] + [p for p in self.member_player_ids if p != self.leader_player_id]


@dataclass(slots=True, frozen=True)
class SecretChamberTemplate:
    template_id: str
    name: str
    parent_zone_id: str
    target_objective_id: str
    lifespan_sec: int
    description: str
    bounds_width: float = 600.0
    bounds_height: float = 600.0


@dataclass(slots=True)
class SecretChamberSession:
    chamber_id: str
    template_id: str
    chamber_zone_id: str
    player_id: str
    portal_zone_id: str
    portal_x: float
    portal_y: float
    spawn_timestamp_ms: int
    collapse_timestamp_ms: int
    is_active: bool = True
    is_discovered: bool = False
    is_cleared: bool = False
    spatial_grid: SpatialGrid = field(default_factory=SpatialGrid)
