use crate::sched::{
    alive_check_client::AliveCheckClient, alive_check_server, auth_server, data_server,
    AliveCheckRequest, AliveCheckResponse, DataRequest, DataResponse, LoginRequest, LoginResponse,
    LogoutRequest, LogoutResponse,
};
use log::{debug, info};

#[derive(Debug, Default)]
pub struct DataService {}

#[tonic::async_trait]
impl data_server::Data for DataService {
    async fn data(
        &self,
        request: tonic::Request<DataRequest>,
    ) -> Result<tonic::Response<DataResponse>, tonic::Status> {
        info!("Got a request: {:#?}", request);
        let input = request.get_ref();
        let data = vec![];

        let res = DataResponse {
            node_id: input.node_id.clone(),
            hashmap_id: input.hashmap_id.clone(),
            uuid: input.uuid.clone(),
            length: data.len().to_string(),
            data,
        };
        debug!("{:?}", &res);
        Ok(tonic::Response::new(res))
    }
}

async fn data_client() {
    todo!()
}

#[derive(Debug, Default)]
pub struct AuthService {}

#[tonic::async_trait]
impl auth_server::Auth for AuthService {
    async fn login(
        &self,
        request: tonic::Request<LoginRequest>,
    ) -> Result<tonic::Response<LoginResponse>, tonic::Status> {
        info!("Got a login request: {:#?}", request);
        let input = request.get_ref();
        let res = LoginResponse {
            node_id: input.node_id.clone(),
        };

        Ok(tonic::Response::new(res))
    }
    async fn logout(
        &self,
        request: tonic::Request<LogoutRequest>,
    ) -> Result<tonic::Response<LogoutResponse>, tonic::Status> {
        info!("Got a logout request: {:#?}", request);
        let input = request.get_ref();
        let res = LogoutResponse {
            node_id: input.node_id.clone(),
        };
        Ok(tonic::Response::new(res))
    }
}

async fn login(node_id: String) -> tonic::Request<LoginRequest> {
    let req = LoginRequest { node_id };
    tonic::Request::new(req)
}

// async fn logout(node_id: String) -> tonic::Request<LoginRequest> {}

#[derive(Debug, Default, Clone)]
pub struct AliveCheckService {}

#[tonic::async_trait]
impl alive_check_server::AliveCheck for AliveCheckService {
    async fn alive_check(
        &self,
        request: tonic::Request<AliveCheckRequest>,
    ) -> Result<tonic::Response<AliveCheckResponse>, tonic::Status> {
        info!("Got an Alive Check request: {:#?}", request);
        let input = request.get_ref();
        let res = AliveCheckResponse {
            node_id: input.node_id.clone(),
        };

        Ok(tonic::Response::new(res))
    }
}
// In this case the head node operates as a grpc client
async fn alive_check(node_id: String) -> Result<AliveCheckResponse, Box<dyn std::error::Error>> {
    let mut client = AliveCheckClient::connect("http://[::1]:50051").await?;

    let req = tonic::Request::new(AliveCheckRequest { node_id });

    let response = client.alive_check(req).await?;

    Ok(response.get_ref().clone())
}