use crate::ecs::components::Parent;
use archetype_ecs::prelude::{Entity, EntityId, GlobalTransform, LocalTransform, World};
use std::collections::HashMap;

/// Transform hierarchy propagation system
///
/// This system:
/// 1. Collects all entities with LocalTransform and their parent relationships
/// 2. Identifies root entities (entities without a Parent)
/// 3. Propagates transforms down the hierarchy: Global = ParentGlobal * Local
///
/// # Performance
/// - O(n) where n = number of entities with transforms
/// - Handles multi-level hierarchies via recursion
pub fn transform_hierarchy_system(world: &mut World) {
    // 1. Collect all local transforms and parent links
    let mut parent_map = HashMap::new();
    let mut root_entities = Vec::new();

    // Query all entities with LocalTransform and optionally Parent
    // Note: Since archetype_ecs might not support Option<&T> in queries easily,
    // we query for LocalTransform and then check for Parent component individually.
    for entity in world
        .query::<(Entity, &LocalTransform)>()
        .iter()
        .map(|(e, _)| e)
    {
        if let Some(parent) = world.get_component::<Parent>(entity) {
            parent_map.insert(entity, parent.entity);
        } else {
            root_entities.push(entity);
        }
    }

    // 2. Process roots (Global == Local)
    for root in root_entities {
        if let Some(local) = world.get_component::<LocalTransform>(root) {
            let local_mat = glam::Mat4::from_scale_rotation_translation(
                local.scale,
                local.rotation,
                local.position,
            );
            let (scale, rotation, position) = local_mat.to_scale_rotation_translation();

            let _ = world.add_component(
                root,
                GlobalTransform {
                    position,
                    rotation,
                    scale,
                },
            );

            // 3. Recursively process children
            propagate_children(world, root, &parent_map);
        }
    }
}

/// Recursively propagate parent global transform to children
fn propagate_children(
    world: &mut World,
    parent_id: EntityId,
    parent_map: &HashMap<EntityId, EntityId>,
) {
    // Get parent's global matrix
    let parent_mat = if let Some(global) = world.get_component::<GlobalTransform>(parent_id) {
        glam::Mat4::from_scale_rotation_translation(global.scale, global.rotation, global.position)
    } else {
        return;
    };

    // Find all children of this parent
    let children: Vec<EntityId> = parent_map
        .iter()
        .filter_map(|(&child, &p)| if p == parent_id { Some(child) } else { None })
        .collect();

    for child in children {
        if let Some(local) = world.get_component::<LocalTransform>(child) {
            let local_mat = glam::Mat4::from_scale_rotation_translation(
                local.scale,
                local.rotation,
                local.position,
            );
            let child_mat = parent_mat * local_mat;
            let (scale, rotation, position) = child_mat.to_scale_rotation_translation();

            let _ = world.add_component(
                child,
                GlobalTransform {
                    position,
                    rotation,
                    scale,
                },
            );

            // Recurse to grandchildren
            propagate_children(world, child, parent_map);
        }
    }
}
