use base64::{Engine as _, engine::general_purpose::STANDARD};
use tokio::net::TcpListener;
use tonic::{Request, Response, Status, transport::Server};

pub mod echo {
    tonic::include_proto!("echo");
    pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("echo_descriptor");
}

#[derive(Default)]
pub struct EchoServiceImpl;

#[tonic::async_trait]
impl echo::echo_service_server::EchoService for EchoServiceImpl {
    async fn unary_echo(
        &self,
        request: Request<echo::EchoRequest>,
    ) -> Result<Response<echo::EchoResponse>, Status> {
        Ok(Response::new(echo::EchoResponse {
            message: request.into_inner().message,
        }))
    }
}

pub async fn spawn_unary_echo_server() -> String {
    let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
    let address = listener.local_addr().unwrap();
    let incoming = tonic::transport::server::TcpIncoming::from(listener);

    tokio::spawn(async move {
        Server::builder()
            .add_service(echo::echo_service_server::EchoServiceServer::new(
                EchoServiceImpl,
            ))
            .serve_with_incoming(incoming)
            .await
            .unwrap();
    });

    format!("http://{}", address)
}

pub fn descriptor_set_b64() -> String {
    STANDARD.encode(echo::FILE_DESCRIPTOR_SET)
}
