use archetype_ecs::prelude::{EntityId, LocalTransform};

use crate::core::player::AnimationPlayer;

/// Handle to a skeleton asset
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct SkeletonHandle(pub u32);

/// Handle to an animation clip asset
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct AnimationClipHandle(pub u32);

/// Animation playback controller
#[derive(Clone, Debug)]
pub struct Animator {
    pub skeleton: SkeletonHandle,
    pub current_clip: AnimationClipHandle,
    pub player: AnimationPlayer,
}

impl Animator {
    pub fn new(skeleton: SkeletonHandle, clip: AnimationClipHandle) -> Self {
        Self {
            skeleton,
            current_clip: clip,
            player: AnimationPlayer::new(),
        }
    }
}

/// Component marking an entity as a bone joint
#[derive(Clone, Copy, Debug)]
pub struct BoneJoint {
    pub bone_index: usize,
    pub skeleton: SkeletonHandle,
}

/// Component linking a mesh to a skeleton
#[derive(Clone, Debug)]
pub struct SkinnedMesh {
    pub skeleton: SkeletonHandle,
    pub mesh_handle: u32,
    pub bone_entities: Vec<EntityId>, // Links joints to entities
    pub joint_offset: u32,            // Offset into global joint SSBO
}

/// Component for storing computed skinning matrices for the GPU
#[derive(Clone, Debug)]
pub struct JointPalette {
    pub matrices: Vec<glam::Mat4>,
}

impl JointPalette {
    pub fn new(count: usize) -> Self {
        Self {
            matrices: vec![glam::Mat4::IDENTITY; count],
        }
    }
}

/// Component for blending between two animation clips
#[derive(Clone, Copy, Debug)]
pub struct AnimationBlend {
    pub from_clip: AnimationClipHandle,
    pub to_clip: AnimationClipHandle,
    pub blend_time: f32,
    pub blend_duration: f32,
}

impl AnimationBlend {
    pub fn new(from: AnimationClipHandle, to: AnimationClipHandle, duration: f32) -> Self {
        Self {
            from_clip: from,
            to_clip: to,
            blend_time: 0.0,
            blend_duration: duration,
        }
    }

    pub fn weight(&self) -> f32 {
        if self.blend_duration <= 0.0 {
            1.0
        } else {
            (self.blend_time / self.blend_duration).clamp(0.0, 1.0)
        }
    }
}

// Local Transform struct removed, using archetype_ecs::prelude::LocalTransform
// Instead, we can provide a compatibility alias if needed, but better to use native types.
pub type Transform = LocalTransform;

/// Parent-child relationship component
#[derive(Clone, Copy, Debug)]
pub struct Parent {
    pub entity: EntityId,
}
