//! Système exclusif qui itère le vrai World du jeu pour répondre à GetEntities.
//!
//! Flux :
//! 1. `handle_debug_messages` (Update) reçoit `GetEntities` → pose `PendingGetEntities(true)`.
//! 2. `send_entity_list` (Last, exclusif) lit le flag, itère les entités, envoie `EntityList`.
//!
//! L'accès exclusif (`&mut World`) est nécessaire pour lire plusieurs composants
//! sans conflit d'emprunt.

use bevy::prelude::*;
use san_motor::debug_protocol::{DebugEntity, GameToEditor};

use crate::DebugChannel;

/// Ressource interne : signale qu'un GetEntities est en attente.
#[derive(Resource, Default)]
pub struct PendingGetEntities(pub bool);

/// Système exclusif (Last) : si GetEntities est en attente, itère les entités du jeu
/// et envoie la liste à l'éditeur via le canal TCP.
///
/// Inclut toute entité ayant un [`Name`] ou un [`Transform`].
pub fn send_entity_list(world: &mut World) {
    // Lire + réinitialiser le flag
    let pending = world.resource::<PendingGetEntities>().0;
    if !pending {
        return;
    }
    world.resource_mut::<PendingGetEntities>().0 = false;

    // Collecter les entités pertinentes
    let mut q = world.query::<bevy::prelude::EntityRef>();
    let mut entities: Vec<DebugEntity> = Vec::new();
    for entity_ref in q.iter(world) {
        let name = entity_ref
            .get::<Name>()
            .map(|n| n.as_str().to_string());
        let position = entity_ref
            .get::<Transform>()
            .map(|t| [t.translation.x, t.translation.y, t.translation.z]);

        if name.is_some() || position.is_some() {
            entities.push(DebugEntity {
                id: entity_ref.id().to_bits(),
                name,
                position,
            });
        }
    }

    // Envoyer la réponse via le canal (le thread TCP s'en charge)
    let channel = world.resource::<DebugChannel>();
    let _ = channel.tx.send(GameToEditor::EntityList { entities });
}
