// 
// module needed to check host-agent health condition and to communicate with it
// 
use tokio::{io::Interest, net::UnixStream};
use anyhow::{Ok, Result, Error};
// to kill lint bug 
#[allow(unused_imports)]
use tokio::net::UnixListener;

/// # Fn `open_unix_socket`
/// ## opening unix-socket for host-agent communication 
/// 
/// *input*      : -
///
/// *output*     : `Ok(socket)` if socket was successfully opened | `Err(er)` if not
///
/// *initiator*  : main thread `(??)`
///
/// *managing*   : -
///
/// *depends on* : -
/// 
#[allow(dead_code)]
async fn open_unix_socket(sock_path: &str) -> Result<UnixStream, std::io::Error> {
    // "/var/run/enode/hostagent.sock"
    UnixStream::connect(sock_path).await
}

/// # Fn `ha_healthcheck`
/// ## for checking host-agent state 
/// 
/// *input*      : `&UnixStream`
///
/// *output*     : `Ok(()))` if host-agent is running | `Err(er)` if not
///
/// *initiator*  : main thread `(??)`
///
/// *managing*   : ref on unix-socket object 
///
/// *depends on* : -
/// 
#[allow(dead_code)]
async fn ha_healthcheck(socket: &UnixStream) -> Result<(), Error> {
    socket.ready(Interest::WRITABLE).await?;
    socket.writable().await?;
    socket.try_write(b"Hello HAgent")?;
    Ok(())
}

/// # Fn `ha_healthcheck`
/// ## for sending data to host-agent using unix-socket 
/// 
/// *input*      : `&UnixStream`, `&str`
///
/// *output*     : `Ok(()))` if data was sent| `Err(er)` if not
///
/// *initiator*  : main thread `(??)`
///
/// *managing*   : socket: `&UnixStream`, data: `&str`
///
/// *depends on* : -
/// 
#[allow(dead_code)]
async fn ha_send_data(socket: &UnixStream, data: &str) -> Result<(), Error > {
    socket.ready(Interest::WRITABLE).await?;
    socket.writable().await?;
    socket.try_write(data.as_bytes())?;
    Ok(())
}

#[cfg(test)]
mod hagent_unittets {
    use super::*;
    const TEST_SOCKET: &str = "./tests/examples/hagent_test.sock";

    async fn init_listener() -> UnixListener {
        let _ = std::fs::remove_file(TEST_SOCKET);
        UnixListener::bind(TEST_SOCKET).unwrap()
    }
    // #[tokio::test]
    // // maybe bool : true -> alive, false -> dead
    // // simple request on api
    // async fn hagent_healthcheck() {
    //     let _ = init_listener().await;
    //     let sock = open_unix_socket(TEST_SOCKET).await;
    //     assert!(sock.is_ok());
    //     let sock = sock.unwrap();
    //     assert!(ha_healthcheck(&sock).await.is_ok());
    // }
    #[tokio::test]
    // --Result<maybe Response>
    // one-shot func
    async fn hagent_communication_test() {
        use crate::options::structs::{ProcessMetrics, ContainerMetrics, Metrics};
        
        let procm = ProcessMetrics::new("test-prc", 15.0, 5.0);
        let contm = ContainerMetrics::new("test", 32.0, 12.0, vec![procm.process_name.clone()]);
        let metrics = Metrics::new(contm, vec![procm]);
        let metrics = &serde_json::to_string_pretty(&metrics).unwrap();

        #[allow(unused_mut)]
        let mut _list = init_listener().await;
        let sock = open_unix_socket(TEST_SOCKET).await;
        assert!(sock.is_ok());
        let sock = sock.unwrap();
        assert!(ha_healthcheck(&sock).await.is_ok());
        assert!(ha_send_data(&sock, &metrics).await.is_ok());

    }
    #[tokio::test]
    async fn open_unixsocket_test() {
        assert!(open_unix_socket("non/valid/socket/file.sock").await.is_err());
    }
}