""" Chat Message Data Models. This module defines the data structures for player-NPC chat messages, stored in the Appwrite chat_messages collection for unlimited conversation history. """ from dataclasses import dataclass, field, asdict from datetime import datetime from enum import Enum from typing import Dict, Any, Optional import uuid class MessageContext(Enum): """ Context type for chat messages. Indicates the type of interaction that generated this message, useful for filtering and quest/faction tracking. """ DIALOGUE = "dialogue" # General conversation QUEST_OFFERED = "quest_offered" # Quest offering dialogue QUEST_COMPLETED = "quest_completed" # Quest completion dialogue SHOP = "shop" # Merchant transaction LOCATION_REVEALED = "location_revealed" # New location discovered through chat LORE = "lore" # Lore/backstory reveals @dataclass class ChatMessage: """ Represents a single message exchange between a player and an NPC. This is the core data model for the chat log system. Each message represents a complete exchange: what the player said and how the NPC responded. Stored in: Appwrite chat_messages collection Indexed by: character_id, npc_id, timestamp, session_id, context Attributes: message_id: Unique identifier (UUID) character_id: Player's character ID npc_id: NPC identifier player_message: What the player said to the NPC npc_response: NPC's reply timestamp: When the message was created (ISO 8601) session_id: Game session reference (optional, for session-based queries) location_id: Where conversation happened (optional) context: Type of interaction (dialogue, quest, shop, etc.) metadata: Extensible JSON field for quest_id, faction_id, item_id, etc. is_deleted: Soft delete flag (for privacy/moderation) """ message_id: str character_id: str npc_id: str player_message: str npc_response: str timestamp: str # ISO 8601 format context: MessageContext session_id: Optional[str] = None location_id: Optional[str] = None metadata: Dict[str, Any] = field(default_factory=dict) is_deleted: bool = False @staticmethod def create( character_id: str, npc_id: str, player_message: str, npc_response: str, context: MessageContext = MessageContext.DIALOGUE, session_id: Optional[str] = None, location_id: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None ) -> "ChatMessage": """ Factory method to create a new ChatMessage with auto-generated ID and timestamp. Args: character_id: Player's character ID npc_id: NPC identifier player_message: What the player said npc_response: NPC's reply context: Type of interaction (default: DIALOGUE) session_id: Optional game session reference location_id: Optional location where conversation happened metadata: Optional extensible metadata (quest_id, faction_id, etc.) Returns: New ChatMessage instance with generated ID and current timestamp """ return ChatMessage( message_id=str(uuid.uuid4()), character_id=character_id, npc_id=npc_id, player_message=player_message, npc_response=npc_response, timestamp=datetime.utcnow().isoformat() + "Z", context=context, session_id=session_id, location_id=location_id, metadata=metadata or {}, is_deleted=False ) def to_dict(self) -> Dict[str, Any]: """ Convert ChatMessage to dictionary for JSON serialization. Returns: Dictionary representation with MessageContext converted to string """ data = asdict(self) data["context"] = self.context.value # Convert enum to string return data @staticmethod def from_dict(data: Dict[str, Any]) -> "ChatMessage": """ Create ChatMessage from dictionary (Appwrite document). Args: data: Dictionary from Appwrite document Returns: ChatMessage instance """ # Convert context string to enum if isinstance(data.get("context"), str): data["context"] = MessageContext(data["context"]) return ChatMessage(**data) def to_preview(self) -> Dict[str, str]: """ Convert to lightweight preview format for character.npc_interactions.recent_messages. Returns: Dictionary with only player_message, npc_response, timestamp """ return { "player_message": self.player_message, "npc_response": self.npc_response, "timestamp": self.timestamp } @dataclass class ConversationSummary: """ Summary of all messages with a specific NPC. Used for the "conversations list" UI to show all NPCs the character has talked to. Attributes: npc_id: NPC identifier npc_name: NPC display name (fetched from NPC data) last_message_timestamp: When the last message was sent message_count: Total number of messages exchanged recent_preview: Short preview of most recent NPC response """ npc_id: str npc_name: str last_message_timestamp: str message_count: int recent_preview: str def to_dict(self) -> Dict[str, Any]: """Convert to dictionary for JSON serialization.""" return asdict(self)