/// Asynchronous utilities for working with Tokio runtime and async operations
///
/// Provides functionality for:
/// - Blocking on async operations
/// - Running system commands asynchronously
///
/// # Examples
///
/// ```ignore
/// #[allow(warnings)]
/// fn main() {
/// // Block on an async operation
/// asyncrs::block_on(async {
///     let output = asyncrs::command("echo hello").await;
///     println!("{}", String::from_utf8_lossy(&output.stdout));
/// });
///     let rt = doe::asyncrs::runtime::Builder::new_multi_thread()
///         .enable_all()
///         .build()
///         .unwrap();
///     rt.block_on(run());
///     rt.block_on(async {
///         run().await;
///     });
/// }
///
/// async fn run() {}
///
/// ```
#[allow(warnings)]
#[cfg(feature = "asyncrs")]
pub mod asyncrs {
    pub use tokio;
    pub use tokio::runtime::Runtime;
    pub use tokio::*;

    use crate::Vector;

    /// Trait for blocking on async operations
    ///
    /// Provides a method to block the current thread until a future completes
    use std::future::Future;

    pub trait BlockOn: Future + Send + 'static {
        /// Runs the future to completion on a new multi‑threaded Tokio runtime,
        /// blocking the current thread until it finishes.
        ///
        /// # Panics
        ///
        /// ```ignore
        ///     use doe::asyncrs::BlockOn;
        ///     
        ///     fn main() {
        ///         run().block_on();
        ///     }
        ///     
        ///     async fn run() {
        ///         println!("start");
        ///         use doe::httprs::*;
        ///         let headers = r#"
        ///     POST /api/v3/translate HTTP/1.1
        ///     Host: demo.com
        ///     Connection: keep-alive
        ///     Content-Length: 271
        ///     Accept-Language: zh-CN,zh;q=0.9
        ///         "#.to_headers();
        ///         let client = doe::httprs::async_client().await;
        ///         let resp = client.post("https://demo.com/api/v3/translate")
        ///             .headers(headers)
        ///             .body(doe::json::json!({"content":"由于","unionid":"ozM5_0WbKEDN6WmhHAphhBoVCUGE","openid":"o7jUU0dPlvcvDQwnfAcTPEuMxrD8","source_flag":"wxd511b28a58c8d268","source":"汉维翻译小程序大号"}).to_string())
        ///             .send().await.unwrap().text().await.unwrap();
        ///         std::fs::write("resp.json", resp).unwrap();
        ///     }
        /// ```
        ///
        /// Panics if a new Tokio runtime cannot be created.
        fn block_on(self) -> Self::Output
        where
            Self: Sized,
        {
            let rt = tokio::runtime::Builder::new_multi_thread()
                .enable_all()
                .build()
                .unwrap();
            rt.block_on(self)
        }
    }

    // Blanket implementation: every future that is Send + 'static
    // automatically gets the .block_on() method.
    impl<F, T> BlockOn for F where F: Future<Output = T> + Send + 'static {}

    /// Blocks the current thread on the given future, executing it to completion
    ///
    /// Creates a new Tokio runtime and uses it to run the provided future
    ///
    /// # Arguments
    ///
    /// * `future` - A future that will be blocked on
    ///
    /// # Panics
    ///
    /// Panics if unable to create a new Tokio runtime
    pub fn block_on<F, T>(future: F) -> T
    where
        F: std::future::Future<Output = T> + Send + 'static,
    {
        let rt = tokio::runtime::Builder::new_multi_thread()
            .enable_all()
            .build()
            .unwrap();
        rt.block_on(future)
    }

    /// Executes a system command asynchronously
    ///
    /// # Arguments
    ///
    /// * `command` - The command to execute, can be a string or byte slice
    ///
    /// # Returns
    ///
    /// Returns a `std::process::Output` containing the command's output
    ///
    /// # Panics
    ///
    /// Panics if unable to spawn the child process
    ///
    /// # Example
    ///
    /// ```
    /// use doe::asyncrs;
    ///
    /// asyncrs::block_on(async {
    ///     let output = asyncrs::command("echo hello").await;
    ///     println!("{}", String::from_utf8_lossy(&output.stdout));
    /// });
    /// ```
    pub async fn command(command: impl AsRef<[u8]>) -> std::process::Output {
        use std::process::Stdio;
        use tokio::process::Command;
        let command = command.as_ref().to_string_lossy().to_string();
        let exe = command.split(" ").into_iter().nth(0).unwrap();
        let other = command.split(" ").into_iter().skip(1).collect::<Vec<_>>();
        let child = Command::new(exe)
            .args(other)
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
            .expect("Failed to spawn child process");
        let output = child
            .wait_with_output()
            .await
            .expect("Failed to wait on child");
        output
    }
}
#[cfg(feature = "asyncrs")]
pub use asyncrs::*;
