//! Shared Data Transfer Objects for serializing game state.
//!
//! These DTOs define the JSON wire format used between the MCP server
//! and the Tauri UI. Both crates import from here to stay in sync.
//!
//! Sub-modules:
//! - [`entity_dtos`]: Builder impls for commanders, cards, creatures, supports; utility fns.
//! - [`action_dtos`]: Action/event/combat serialization.

pub mod action_dtos;
pub mod entity_dtos;

pub use action_dtos::*;
pub use entity_dtos::*;

use serde::{Deserialize, Serialize};

// =============================================================================
// DTO Structs
// =============================================================================

/// Full game state sent to the frontend.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GameStateDto {
    pub id: String,
    pub turn: u16,
    pub phase: String,
    pub active_player: u8,

    pub player: PlayerStateDto,
    pub opponent: PlayerStateDto,

    pub is_game_over: bool,
    pub winner: Option<u8>,
    pub game_over_reason: Option<String>,
}

/// Player state (our side vs opponent side).
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlayerStateDto {
    pub life: i16,
    pub max_life: i16,
    pub essence: u8,
    pub max_essence: u8,
    pub action_points: u8,
    pub deck_count: usize,
    /// Essence extracted from opponent (total face damage dealt).
    /// In EssenceWar mode, reaching 50 wins the game.
    pub essence_extracted: u16,

    pub hand: Vec<CardDto>,
    pub creatures: Vec<Option<CreatureDto>>,
    pub supports: Vec<Option<SupportDto>>,

    /// Commander information (always present in a game).
    pub commander: Option<CommanderDto>,

    /// Active prepared/ambush effects waiting to trigger.
    pub prepared_effects: Vec<PreparedEffectDto>,
}

/// A deferred effect queued by Prepare, Ambush, or Ritual — displayed in the UI.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PreparedEffectDto {
    /// "prepare" (fires start of owner's next turn) or "ambush" (fires on enemy attack).
    pub trigger: String,
    /// Human-readable description of what happens when this fires.
    pub description: String,
}

/// Commander information for display.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CommanderDto {
    pub id: u16,
    pub name: String,
    pub faction: String,
    pub ability_description: String,
    /// Portrait path (relative to static folder).
    pub portrait_path: String,
}

/// Card in hand.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CardDto {
    pub card_id: u16,
    pub name: String,
    pub cost: u8,
    pub card_type: String,
    pub faction: String,

    // Creature stats (if applicable)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub attack: Option<u8>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub health: Option<u8>,
    pub keywords: Vec<String>,

    // Support stats (if applicable)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub durability: Option<u8>,

    // Art path (relative to assets)
    #[serde(skip_serializing_if = "Option::is_none")]
    pub art_path: Option<String>,

    /// Effect description for spell/support cards (None for creatures).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub effect_description: Option<String>,

    /// Overload cost in life (None if card doesn't support Overload).
    /// When present, the card can be played by paying this many life instead of its essence cost.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub overload_cost: Option<u8>,

    /// Activated / Prepare / Ambush abilities (empty for most cards).
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub abilities: Vec<AbilityDto>,

    /// XP threshold to level up (None if no level-up definition).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level_up_threshold: Option<u8>,

    /// Level-up trigger: "OnKill" or "OnDealDamage" (None if no level-up definition).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level_up_trigger: Option<String>,

    /// Human-readable level-up reward, e.g. "+3/+2, gains Rush" (None if no level-up).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub level_up_reward: Option<String>,
}

/// Activated ability on a creature (typically tokens).
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AbilityDto {
    /// Ability index (0-5) for action matching.
    pub index: u8,
    /// Display name (e.g., "Fungal Rot").
    pub name: String,
    /// Essence cost to activate.
    pub essence_cost: u8,
    /// Targeting type: "no_target", "enemy_creature", "enemy_player", "any", etc.
    pub targeting_type: String,
    /// Human-readable effect description.
    pub description: String,
}

/// Creature on board.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreatureDto {
    pub instance_id: u32,
    pub card_id: u16,
    pub name: String,
    pub slot: u8,
    pub faction: String,

    pub attack: i8,
    pub base_attack: u8,
    pub health: i8,
    pub max_health: i8,

    pub keywords: Vec<String>,
    pub can_attack: bool,
    pub is_exhausted: bool,
    pub has_flanking: bool,

    /// Current level (0 = base, 1 = leveled up).
    pub level: u8,
    /// XP progress toward next level-up threshold.
    pub level_progress: u8,
    /// XP threshold to level up (0 if this creature has no level-up definition).
    pub level_threshold: u8,

    pub art_path: Option<String>,

    /// Activated abilities (empty for most creatures, populated for tokens with abilities).
    pub abilities: Vec<AbilityDto>,
}

/// Support on board.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SupportDto {
    pub card_id: u16,
    pub name: String,
    pub slot: u8,
    pub faction: String,

    pub durability: u8,

    pub art_path: Option<String>,

    /// Human-readable description of what this support does.
    pub effect_description: String,
}

/// Action information for the UI.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ActionInfo {
    pub index: u16,
    pub action_type: String,
    pub description: String,

    // For highlighting
    pub source_slot: Option<u8>,
    pub target_slot: Option<u8>,
    pub hand_index: Option<u8>,
    pub card_id: Option<u16>,

    /// For use_ability actions: which ability (0-5).
    pub ability_index: Option<u8>,
}

/// A single step in combat resolution (for Tier-3 log display).
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CombatStepDto {
    pub phase: String,
    pub description: String,
    pub damage_dealt: u8,
    pub healing: u8,
    pub death: Option<String>,
}

/// Full combat trace for one attack action (for Tier-3 log display).
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CombatTraceDto {
    pub attacker_slot: u8,
    pub attacker_attack: i8,
    pub attacker_health: i8,
    pub defender_slot: u8,
    pub defender_attack: Option<i8>,
    pub defender_health: Option<i8>,
    pub is_face_attack: bool,
    pub steps: Vec<CombatStepDto>,
    pub attacker_died: bool,
    pub defender_died: bool,
    pub face_damage: u8,
    pub attacker_healed: u8,
}

/// Game state update after an action.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GameStateUpdate {
    pub state: GameStateDto,
    pub last_action: Option<ActionInfo>,
    pub events: Vec<GameEventDto>,
    /// Detailed combat trace for Attack actions (None for all other action types).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub combat_trace: Option<CombatTraceDto>,
}

/// Game event for animation/sound triggers.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GameEventDto {
    pub event_type: String,
    pub data: serde_json::Value,
}

/// Result of a completed game.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GameResultDto {
    pub winner: Option<u8>,
    pub reason: String,
    pub final_turn: u16,
    pub player_final_life: i16,
    pub opponent_final_life: i16,
}
