"""
Location data models for the world exploration system.

This module defines Location and Region dataclasses that represent structured
game world data. Locations are loaded from YAML files and provide rich context
for AI narrative generation.
"""

from dataclasses import dataclass, field
from typing import Dict, List, Any, Optional

from app.models.enums import LocationType


@dataclass
class Location:
    """
    Represents a defined location in the game world.

    Locations are persistent world entities with NPCs, quests, and connections
    to other locations. They are loaded from YAML files at runtime.

    Attributes:
        location_id: Unique identifier (e.g., "crossville_tavern")
        name: Display name (e.g., "The Rusty Anchor Tavern")
        location_type: Type of location (town, tavern, wilderness, dungeon, etc.)
        region_id: Parent region this location belongs to
        description: Full description for AI narrative context
        lore: Optional historical/background information
        ambient_description: Atmospheric details for AI narration
        available_quests: Quest IDs that can be discovered at this location
        npc_ids: List of NPC IDs present at this location
        discoverable_locations: Location IDs that can be revealed from here
        is_starting_location: Whether this is a valid origin starting point
        tags: Additional metadata tags for filtering/categorization
    """

    location_id: str
    name: str
    location_type: LocationType
    region_id: str
    description: str
    lore: Optional[str] = None
    ambient_description: Optional[str] = None
    available_quests: List[str] = field(default_factory=list)
    npc_ids: List[str] = field(default_factory=list)
    discoverable_locations: List[str] = field(default_factory=list)
    is_starting_location: bool = False
    tags: List[str] = field(default_factory=list)

    def to_dict(self) -> Dict[str, Any]:
        """
        Serialize location to dictionary for JSON responses.

        Returns:
            Dictionary containing all location data
        """
        return {
            "location_id": self.location_id,
            "name": self.name,
            "location_type": self.location_type.value,
            "region_id": self.region_id,
            "description": self.description,
            "lore": self.lore,
            "ambient_description": self.ambient_description,
            "available_quests": self.available_quests,
            "npc_ids": self.npc_ids,
            "discoverable_locations": self.discoverable_locations,
            "is_starting_location": self.is_starting_location,
            "tags": self.tags,
        }

    def to_story_dict(self) -> Dict[str, Any]:
        """
        Serialize location for AI narrative context.

        Returns a trimmed version with only narrative-relevant data
        to reduce token usage in AI prompts.

        Returns:
            Dictionary containing story-relevant location data
        """
        return {
            "name": self.name,
            "type": self.location_type.value,
            "description": self.description,
            "ambient": self.ambient_description,
            "lore": self.lore,
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Location':
        """
        Deserialize location from dictionary.

        Args:
            data: Dictionary containing location data (from YAML or JSON)

        Returns:
            Location instance
        """
        # Handle location_type - can be string or LocationType enum
        location_type = data.get("location_type", "town")
        if isinstance(location_type, str):
            location_type = LocationType(location_type)

        return cls(
            location_id=data["location_id"],
            name=data["name"],
            location_type=location_type,
            region_id=data["region_id"],
            description=data["description"],
            lore=data.get("lore"),
            ambient_description=data.get("ambient_description"),
            available_quests=data.get("available_quests", []),
            npc_ids=data.get("npc_ids", []),
            discoverable_locations=data.get("discoverable_locations", []),
            is_starting_location=data.get("is_starting_location", False),
            tags=data.get("tags", []),
        )

    def __repr__(self) -> str:
        """String representation of the location."""
        return f"Location({self.location_id}, {self.name}, {self.location_type.value})"


@dataclass
class Region:
    """
    Represents a geographical region containing multiple locations.

    Regions group related locations together for organizational purposes
    and can contain region-wide lore or events.

    Attributes:
        region_id: Unique identifier (e.g., "crossville")
        name: Display name (e.g., "Crossville Province")
        description: Region overview and atmosphere
        location_ids: List of all location IDs in this region
    """

    region_id: str
    name: str
    description: str
    location_ids: List[str] = field(default_factory=list)

    def to_dict(self) -> Dict[str, Any]:
        """
        Serialize region to dictionary.

        Returns:
            Dictionary containing all region data
        """
        return {
            "region_id": self.region_id,
            "name": self.name,
            "description": self.description,
            "location_ids": self.location_ids,
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Region':
        """
        Deserialize region from dictionary.

        Args:
            data: Dictionary containing region data

        Returns:
            Region instance
        """
        return cls(
            region_id=data["region_id"],
            name=data["name"],
            description=data["description"],
            location_ids=data.get("location_ids", []),
        )

    def __repr__(self) -> str:
        """String representation of the region."""
        return f"Region({self.region_id}, {self.name}, {len(self.location_ids)} locations)"
