//! 版本信息
//!
//! 提供 SDK 和 DLL 版本信息查询。
//! 对应 C# `Static/VersionInfo.cs`。

/// SDK 主版本号
pub const MAJOR_VERSION: u16 = 0;

/// SDK 次版本号 (由 build.rs 从 minor_version.txt 读取)
pub const MINOR_VERSION: u16 = 18;

/// SDK 构建号 (由 build.rs 从 build_number.txt 读取)
pub const BUILD_NUMBER: u16 = 102;

/// 获取 SDK 版本字符串
pub fn version() -> String {
    format!("{}.{}.{}", MAJOR_VERSION, MINOR_VERSION, BUILD_NUMBER)
}

/// DLL 版本信息
#[derive(Debug, Clone, Default)]
pub struct DllVersion {
    /// 主版本号
    pub major: u16,
    /// 次版本号
    pub minor: u16,
    /// 补丁号
    pub patch: u16,
    /// 构建号
    pub build: u16,
    /// 构建日期
    pub build_date: String,
}

impl std::fmt::Display for DllVersion {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}.{}.{}.{}", self.major, self.minor, self.patch, self.build)
    }
}

/// 获取 DLL 版本信息
pub fn dll_version() -> Option<DllVersion> {
    let ptr = unsafe { crate::utils::ffi::GetDllVersionInfo() };
    if ptr.is_null() {
        return None;
    }
    // packed 结构体不能直接创建引用，需要 read_unaligned 避免 UB
    let info = unsafe { std::ptr::read_unaligned(ptr) };
    let build_date_raw = unsafe { std::ptr::addr_of!(info.build_date).read_unaligned() };
    let null_pos = build_date_raw.iter().position(|&b| b == 0).unwrap_or(build_date_raw.len());
    let build_date = String::from_utf8_lossy(&build_date_raw[..null_pos]).to_string();

    Some(DllVersion {
        major: unsafe { std::ptr::addr_of!(info.major).read_unaligned() },
        minor: unsafe { std::ptr::addr_of!(info.minor).read_unaligned() },
        patch: unsafe { std::ptr::addr_of!(info.patch).read_unaligned() },
        build: unsafe { std::ptr::addr_of!(info.build).read_unaligned() },
        build_date,
    })
}
