use std::ptr;

use encoding_rs::GB18030;
use std::borrow::Cow;

pub fn copy_str_to_i8_array(dst: &mut [i8], src: &str) {
    // 确保目标数组至少有一个元素用于放置 '\0'
    if dst.is_empty() {
        return;
    }

    // 获取源字符串的字节表示
    let bytes = src.as_bytes();

    // 计算要复制的长度,取源字符串长度和目标缓冲区长度减一的最小值
    let len = usize::min(bytes.len(), dst.len() - 1);

    unsafe {
        ptr::copy_nonoverlapping(bytes.as_ptr(), dst.as_mut_ptr() as *mut u8, len);
    }

    // 使用 '\0' 截断
    dst[len] = 0;

    // 如果目标缓冲区比源字符串长,则剩余部分保持未初始化或保持原值。
}

#[macro_export]
macro_rules! print_rsp_info {
    ($p:expr) => {
        if let Some(p) = $p {
            println!(
                "ErrorID[{}] Message[{}]",
                p.ErrorID,
                gb18030_cstr_i8_to_str(&p.ErrorMsg).unwrap().to_string()
            );
        }
    };
}

/// 将 `&[std::os::raw::c_char]` 转换为 `Cow<str>`
/// - 如果输入为 ASCII,返回 `Cow::Borrowed`。
/// - 如果输入为 GB18030,解码后返回 `Cow::Owned`。
/// - 如果解码失败,返回 `Err`。
pub fn gb18030_cstr_i8_to_str<'a>(
    c_chars: &'a [std::os::raw::c_char],
) -> Result<Cow<'a, str>, String> {
    // 找到 '\0' 的位置以截断
    let len = c_chars
        .iter()
        .position(|&c| c == 0)
        .unwrap_or(c_chars.len());
    let bytes = &c_chars[..len];

    // 转换为 &[u8]
    let bytes = unsafe { &*(bytes as *const [std::os::raw::c_char] as *const [u8]) };

    // 快速路径:检测是否是 ASCII
    if bytes.is_ascii() {
        return std::str::from_utf8(bytes)
            .map(Cow::Borrowed)
            .map_err(|e| format!("Invalid UTF-8: {}", e));
    }

    // 非 ASCII 的情况:使用 GB18030 解码
    let (decoded, _, had_errors) = GB18030.decode(bytes);
    if had_errors {
        return Err("Failed to decode GB18030 string".to_string());
    }

    Ok(Cow::Owned(decoded.into_owned()))
}