//! External asset import helpers (FBX sidecar folders, etc.).

use std::fs;
use std::path::{Path, PathBuf};

/// Copies an FBX file and its sibling `.fbm` embedded-texture folder when present.
pub fn copy_fbx_with_sidecar(source: &Path, dest_dir: &Path) -> Result<(), String> {
    let Some(file_name) = source.file_name() else {
        return Err("FBX import path has no file name".into());
    };
    fs::create_dir_all(dest_dir)
        .map_err(|err| format!("could not create {}: {err}", dest_dir.display()))?;
    let dest = dest_dir.join(file_name);
    fs::copy(source, &dest).map_err(|err| {
        format!(
            "could not copy {} to {}: {err}",
            source.display(),
            dest.display()
        )
    })?;

    if let Some(fbm_dir) = fbm_sidecar_dir(source) {
        if fbm_dir.is_dir() {
            let dest_fbm = dest_dir.join(fbm_dir.file_name().unwrap_or_default());
            copy_dir_recursive(&fbm_dir, &dest_fbm)?;
        }
    }
    Ok(())
}

fn fbm_sidecar_dir(source: &Path) -> Option<PathBuf> {
    let stem = source.file_stem()?.to_str()?;
    let parent = source.parent()?;
    Some(parent.join(format!("{stem}.fbm")))
}

fn copy_dir_recursive(source: &Path, dest: &Path) -> Result<(), String> {
    fs::create_dir_all(dest)
        .map_err(|err| format!("could not create {}: {err}", dest.display()))?;
    for entry in fs::read_dir(source).map_err(|err| err.to_string())? {
        let entry = entry.map_err(|err| err.to_string())?;
        let src_path = entry.path();
        let dest_path = dest.join(entry.file_name());
        if src_path.is_dir() {
            copy_dir_recursive(&src_path, &dest_path)?;
        } else {
            fs::copy(&src_path, &dest_path).map_err(|err| {
                format!(
                    "could not copy {} to {}: {err}",
                    src_path.display(),
                    dest_path.display()
                )
            })?;
        }
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::fbm_sidecar_dir;
    use std::path::Path;

    #[test]
    fn fbm_sidecar_path() {
        assert_eq!(
            fbm_sidecar_dir(Path::new("/tmp/Character.fbx")),
            Some(Path::new("/tmp/Character.fbm").to_path_buf())
        );
    }
}
