
use crate::utils::ffi;
use std::sync::OnceLock;

#[derive(Clone, Debug, Default)]
pub struct DllVersionInfoCached {
    pub major: u16,
    pub minor: u16,
    pub patch: u16,
    pub build: u16,
    pub build_date: String,
}

static CACHED_VERSION: OnceLock<DllVersionInfoCached> = OnceLock::new();

pub fn get_dll_version_info() -> &'static DllVersionInfoCached {
    CACHED_VERSION.get_or_init(|| {
        unsafe {
            let ptr = ffi::GetDllVersionInfo();
            if ptr.is_null() {
                return DllVersionInfoCached::default();
            }

            #[repr(C, packed)]
            struct RawVersionInfo {
                major: u16,
                minor: u16,
                patch: u16,
                build: u16,
                build_date: [u8; 32],
            }

            let raw = &*(ptr as *const RawVersionInfo);
            let date_len = raw.build_date.iter().position(|&b| b == 0).unwrap_or(32);
            let build_date = std::str::from_utf8(&raw.build_date[..date_len])
                .unwrap_or("Unknown")
                .to_string();

            DllVersionInfoCached {
                major: raw.major,
                minor: raw.minor,
                patch: raw.patch,
                build: raw.build,
                build_date,
            }
        }
    })
}

pub fn version_number() -> String {
    let info = get_dll_version_info();
    format!("{}.{}.{}.{}", info.major, info.minor, info.patch, info.build)
}

pub fn build_date() -> &'static str {
    &get_dll_version_info().build_date
}
