//! Système exclusif qui applique les mises à jour live envoyées par l'éditeur
//! (`SetEntityProperties`) directement sur les composants Bevy du jeu.
//!
//! Stratégie :
//! - `Transform` / `Visibility` : recherche l'entité par son composant `Name`,
//!   puis écrase le composant Bevy correspondant.
//! - `PlayerController` : met à jour la resource [`crate::PlayerControllerLive`]
//!   (lue par le `player_movement_system` généré).

use bevy::prelude::*;
use san_motor::debug_protocol::LiveProp;
use std::collections::HashMap;

use crate::{PendingEntityProps, PlayerControllerLive};

/// Système `Last` exclusif — applique toutes les propriétés live en attente.
pub fn apply_live_entity_properties(world: &mut World) {
    // Drainer la file avant d'emprunter le world pour les queries
    let updates: Vec<(String, Vec<LiveProp>)> = {
        let mut res = world.resource_mut::<PendingEntityProps>();
        std::mem::take(&mut res.0)
    };

    if updates.is_empty() {
        return;
    }

    // Index nom → entité (un seul passage)
    let name_map: HashMap<String, Entity> = {
        let mut q = world.query::<(Entity, &Name)>();
        q.iter(world)
            .map(|(e, n)| (n.as_str().to_string(), e))
            .collect()
    };

    for (entity_name, props) in updates {
        for prop in props {
            match prop {
                LiveProp::Transform { translation, rotation, scale } => {
                    let Some(&entity) = name_map.get(&entity_name) else { continue };
                    let new_t = Transform {
                        translation: Vec3::from(translation),
                        rotation: Quat::from_array(rotation),
                        scale: Vec3::from(scale),
                    };
                    if let Some(mut t) = world.get_mut::<Transform>(entity) {
                        *t = new_t;
                    }
                }
                LiveProp::Visibility { hidden } => {
                    let Some(&entity) = name_map.get(&entity_name) else { continue };
                    let new_v = if hidden { Visibility::Hidden } else { Visibility::Inherited };
                    if let Some(mut v) = world.get_mut::<Visibility>(entity) {
                        *v = new_v;
                    }
                }
                LiveProp::PlayerController { speed, sprint_speed, jump_height, gravity } => {
                    // Pas besoin de chercher par nom : resource globale
                    if let Some(mut live) = world.get_resource_mut::<PlayerControllerLive>() {
                        live.speed = Some(speed);
                        live.sprint_speed = Some(sprint_speed);
                        live.jump_height = Some(jump_height);
                        live.gravity = Some(gravity);
                    }
                }
            }
        }
    }
}
