//! Serializable types for the tree domain.

use serde::{Deserialize, Serialize};

use crate::commit::types::CommitOid;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TreeInfo {
    pub oid: CommitOid,
    pub entry_count: usize,
    pub is_empty: bool,
}

impl TreeInfo {
    pub fn from_git2(tree: &git2::Tree<'_>) -> Self {
        Self {
            oid: CommitOid::from_git2(tree.id()),
            entry_count: tree.len(),
            is_empty: tree.is_empty(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TreeEntry {
    pub name: String,
    pub oid: CommitOid,
    pub kind: String,
    pub filemode: u32,
    pub is_binary: bool,
}

impl TreeEntry {
    pub fn from_git2(entry: git2::TreeEntry<'_>, repo: &git2::Repository) -> Self {
        let kind = entry
            .kind()
            .map(|k| format!("{:?}", k).to_lowercase())
            .unwrap_or_default();
        // Binary detection: check actual blob content, not just object type.
        // Blob type means "file content" in git, not "binary file".
        let is_binary = entry
            .to_object(repo)
            .ok()
            .and_then(|o| o.as_blob().map(|blob| blob.is_binary()))
            .unwrap_or(false);
        Self {
            name: entry.name().unwrap_or("").to_string(),
            oid: CommitOid::from_git2(entry.id()),
            kind,
            filemode: entry.filemode() as u32,
            is_binary,
        }
    }
}
