use armour_core::{GetType, KeyScheme, Typ};

use crate::Key;

/// Metadata about a named tree/map collection.
#[derive(Debug, Clone, Copy)]
pub struct TreeMeta {
    pub name: &'static str,
    pub key_scheme: KeyScheme,
    pub ty: Typ,
    pub group_bits: u32,
    pub version: u16,
}

impl TreeMeta {
    /// Build `TreeMeta` from a type implementing [`CollectionMeta`].
    ///
    /// All fields are resolved at compile time from associated constants.
    ///
    /// ```ignore
    /// const META: TreeMeta = TreeMeta::of::<User>();
    /// ```
    pub const fn of<T: CollectionMeta>() -> Self {
        Self {
            name: T::NAME,
            key_scheme: <T::SelfId as Key>::KEY_SCHEME,
            ty: T::TYPE,
            group_bits: <T::SelfId as Key>::GROUP_BITS,
            version: T::VERSION,
        }
    }
}

/// Trait for types that carry enough metadata to describe an armdb collection.
///
/// Provides the constants needed to construct a [`TreeMeta`]:
/// name, version, and value type (`Typ` via [`GetType`]).
/// Key metadata (`KeyScheme`, `GROUP_BITS`) comes from the associated
/// [`SelfId`](CollectionMeta::SelfId) type via the [`Key`] trait.
///
/// # Example
///
/// ```ignore
/// use armdb::{CollectionMeta, Key, TreeMeta, impl_key_zerocopy};
/// use armour_core::{GetType, KeyScheme, KeyType};
///
/// #[derive(FromBytes, IntoBytes, Immutable, Copy, Clone)]
/// #[repr(transparent)]
/// struct UserId([u8; 8]);
///
/// impl_key_zerocopy!(UserId, KeyScheme::Typed(&[KeyType::Fuid]), group_bits = 10);
///
/// #[derive(GetType, Rapira)]
/// struct User {
///     name: String,
///     email: String,
/// }
///
/// impl CollectionMeta for User {
///     type SelfId = UserId;
///     const NAME: &'static str = "users";
///     const VERSION: u16 = 1;
/// }
///
/// const META: TreeMeta = TreeMeta::of::<User>();
/// ```
pub trait CollectionMeta: GetType {
    /// Key type for this collection. Must implement [`Key`].
    type SelfId: Key;
    /// Collection name (e.g. `"users"`).
    const NAME: &'static str;
    /// Schema version — increment on breaking changes.
    const VERSION: u16 = 0;
}
