use serde::{Deserialize, Serialize};

use crate::entity::EntityId;
use crate::math::{Color, Quat, Transform, Vec3};

/// Valeur d'un champ de composant, sérialisable.
///
/// Couvre tous les types supportés par l'Inspector (voir features.md).
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ComponentValue {
    Bool(bool),
    F32(f32),
    F64(f64),
    I32(i32),
    U32(u32),
    String(String),
    Vec3(Vec3),
    Quat(Quat),
    Transform(Transform),
    Color(Color),
    Entity(EntityId),
    /// Liste ordonnée (ex: tableau de Vec3).
    List(Vec<ComponentValue>),
    /// Struct ou map de champs nommés.
    Map(Vec<(String, ComponentValue)>),
}

impl ComponentValue {
    /// Nom lisible du variant, pour l'affichage dans l'Inspector.
    pub fn type_name(&self) -> &'static str {
        match self {
            ComponentValue::Bool(_) => "bool",
            ComponentValue::F32(_) => "f32",
            ComponentValue::F64(_) => "f64",
            ComponentValue::I32(_) => "i32",
            ComponentValue::U32(_) => "u32",
            ComponentValue::String(_) => "String",
            ComponentValue::Vec3(_) => "Vec3",
            ComponentValue::Quat(_) => "Quat",
            ComponentValue::Transform(_) => "Transform",
            ComponentValue::Color(_) => "Color",
            ComponentValue::Entity(_) => "Entity",
            ComponentValue::List(_) => "List",
            ComponentValue::Map(_) => "Map",
        }
    }
}

/// Accès aux composants des entités de la scène.
///
/// Implémenté par `BevyEngine` via `bevy_reflect` en Jalon 2.
pub trait ComponentStore {
    /// Noms des composants attachés à cette entité.
    fn component_names(&self, entity: EntityId) -> Vec<String>;

    /// Vérifie si l'entité a un composant donné.
    fn has_component(&self, entity: EntityId, component: &str) -> bool;

    /// Lit la valeur d'un composant sous forme de `ComponentValue`.
    fn component(&self, entity: EntityId, component: &str) -> Option<ComponentValue>;

    /// Modifie la valeur d'un composant. Retourne `false` si le composant n'existe pas.
    fn set_component(
        &mut self,
        entity: EntityId,
        component: &str,
        value: ComponentValue,
    ) -> bool;

    /// Ajoute un composant. Retourne `false` si déjà présent.
    fn add_component(
        &mut self,
        entity: EntityId,
        component: &str,
        value: ComponentValue,
    ) -> bool;

    /// Supprime un composant. Retourne `false` si absent.
    fn remove_component(&mut self, entity: EntityId, component: &str) -> bool;
}
