#[allow(warnings)]
#[cfg(feature = "sys_random")]
/// Here's a markdown documentation for the `sys_random` module:
/// 
/// # System Random Module
/// 
/// This module provides cryptographically secure random number generation functionality for both Windows and Linux systems.
/// 
/// ## Features
/// 
/// - Generate cryptographically secure random bytes
/// - Generate version 4 UUIDs (random-based)
/// 
/// ## Requirements
/// 
/// Enable the `sys_random` feature to use this module.
/// 
/// ## Functions
/// 
/// ### `get_system_random_bytes(buffer: &mut [u8]) -> io::Result<()>`
/// 
/// Fills the provided buffer with cryptographically secure random bytes.
/// 
/// **Parameters:**
/// - `buffer`: A mutable byte slice to be filled with random data
/// 
/// **Returns:**
/// - `Ok(())` on success
/// - `Err(io::Error)` if the operation fails
/// 
/// **Example:**
/// ```rust
/// let mut buffer = [0u8; 32];
/// get_system_random_bytes(&mut buffer).unwrap();
/// ```
/// 
/// ### `uuid() -> String`
/// 
/// Generates a random version 4 UUID (Universally Unique Identifier) according to RFC 4122.
/// 
/// **Returns:**
/// - A string representation of the UUID in the format `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
/// 
/// **Example:**
/// ```rust
/// let id = uuid();
/// println!("Generated UUID: {}", id);
/// // Example output: "550e8400-e29b-41d4-a716-446655440000"
/// ```
/// 
/// ## Platform Support
/// 
/// ### Windows
/// Uses the CryptoAPI through:
/// - `CryptAcquireContextA`
/// - `CryptGenRandom`
/// - `CryptReleaseContext`
/// 
/// ### Linux
/// Uses the `getrandom` system call.
/// 
/// ## Examples
/// 
/// ### Basic Usage
/// ```rust
/// use your_crate::sys_random;
/// 
/// fn main() {
///     // Generate random bytes
///     let mut random_data = [0u8; 16];
///     sys_random::get_system_random_bytes(&mut random_data).unwrap();
///     
///     // Generate a UUID
///     let uuid = sys_random::uuid();
///     println!("Random UUID: {}", uuid);
/// }
/// ```
/// 
/// ### Error Handling
/// ```rust
/// use your_crate::sys_random;
/// use std::io;
/// 
/// fn get_random_data() -> io::Result<[u8; 32]> {
///     let mut buffer = [0u8; 32];
///     sys_random::get_system_random_bytes(&mut buffer)?;
///     Ok(buffer)
/// }
/// ```
/// 
/// ## Testing
/// 
/// The module includes basic tests to verify functionality:
/// ```rust
/// #[test]
/// fn test_get_system_random_bytes() {
///     let mut buffer = [0u8; 16];
///     assert!(get_system_random_bytes(&mut buffer).is_ok());
/// }
/// ```
/// 
/// ## Notes
/// 
/// - The UUID generation follows version 4 specifications (random-based)
/// - The random number generators used are cryptographically secure
/// - On Linux, this uses the `getrandom` system call which blocks if the CSPRNG hasn't been initialized yet
/// - On Windows, this uses the CryptoAPI which is available on all modern Windows versions
pub mod sys_random {
    #[cfg(target_os = "linux")]
    use libc::getrandom;
    use std::io;

    #[cfg(target_os = "windows")]

    pub fn get_system_random_bytes(buffer: &mut [u8]) -> io::Result<()> {
        use windows::{
            core::Error,
            Win32::Security::Cryptography::{
                CryptAcquireContextA, CryptGenRandom, CryptReleaseContext, CRYPT_VERIFYCONTEXT,
                PROV_RSA_FULL,
            },
        };

        let mut hprov = 0;

        // Acquire crypto context
        unsafe {
            let result = CryptAcquireContextA(
                &mut hprov,
                None, // Use default container
                None, // Use default provider
                PROV_RSA_FULL,
                CRYPT_VERIFYCONTEXT,
            );

            if !result.as_bool() {
                return Err(Error::from_win32().into());
            }
        }

        // Generate random bytes
        let result = unsafe { CryptGenRandom(hprov, buffer) };

        // Release context regardless of whether generation succeeded
        unsafe {
            CryptReleaseContext(hprov, 0);
        }

        if !result.as_bool() {
            return Err(Error::from_win32().into());
        }

        Ok(())
    }

    #[cfg(target_os = "linux")]
    pub fn get_system_random_bytes(buffer: &mut [u8]) -> io::Result<()> {
        unsafe {
            let ret = getrandom(buffer.as_mut_ptr() as *mut libc::c_void, buffer.len(), 0);
            if ret == -1 {
                return Err(io::Error::last_os_error());
            }
        }
        Ok(())
    }

    /// generate a random UUID
    /// ```ignore
    /// let s = uuid();
    /// println!("{}", s);
    /// ```
    ///
    #[cfg(target_os = "windows")]
    pub fn uuid() -> String {
        let mut bytes = [0u8; 16];
        get_system_random_bytes(&mut bytes).unwrap();
        format!(
        "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
        bytes[0], bytes[1], bytes[2], bytes[3],
        bytes[4], bytes[5],
        bytes[6], (bytes[7] & 0x0F) | 0x40, // 设置版本号为 4
        (bytes[8] & 0x3F) | 0x80, // 设置变体为 RFC 4122
        bytes[9],
        bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]
        )
    }


     /// generate a random UUID
    /// ```ignore
    /// let s = uuid();
    /// println!("{}", s);
    /// ```
    ///
    #[cfg(target_os = "linux")]
    pub fn uuid() -> String {
        let mut bytes = [0u8; 16];
        get_system_random_bytes(&mut bytes).unwrap();
        format!(
        "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
        bytes[0], bytes[1], bytes[2], bytes[3],
        bytes[4], bytes[5],
        bytes[6], (bytes[7] & 0x0F) | 0x40, // 设置版本号为 4
        (bytes[8] & 0x3F) | 0x80, // 设置变体为 RFC 4122
        bytes[9],
        bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]
        )
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn test_get_system_random_bytes() {
            let mut buffer = [0u8; 16];
            assert!(get_system_random_bytes(&mut buffer).is_ok());
        }
    }
}
#[cfg(feature = "sys_random")]
pub use sys_random::*;
