Documentation
use poem::{handler, http::uri::Uri, listener::TcpListener, Route, Server};
use poem_openapi::{param::Query, payload::PlainText, OpenApi, OpenApiService};

struct Api;

#[OpenApi]
impl Api {
    #[oai(path = "/hello", method = "get")]
    async fn index(&self, name: Query<Option<String>>) -> PlainText<String> {
        match name.0 {
            Some(name) => PlainText(format!("hello, {name}!")),
            None => PlainText("hello!".to_string()),
        }
    }
}

#[derive(clap::Parser)]
pub struct Options {
    #[clap(long, env = "HOST", default_value = "127.0.0.1")]
    /// Set host
    host: String,
    #[clap(short = 'p', long, env = "PORT", default_value = "8080")]
    /// Set listening port
    port: String,
}

impl Options {
    fn host(&self) -> String {
        self.host.clone()
    }
    fn port(&self) -> String {
        self.port.clone()
    }
    fn hostport(&self) -> String {
        format!("{}:{}", self.host(), self.port())
    }
    fn url(&self) -> String {
        format!("http://{}", self.hostport())
    }
    fn addr(&self) -> std::net::SocketAddr {
        self.hostport().parse().unwrap()
    }
    pub async fn run(&mut self) -> Result<(), std::io::Error> {
        dbg!(self.url());
        let api_service = OpenApiService::new(Api, "Hello World", "1.0").server("/api");
        let ui = api_service.swagger_ui();
        let app = Route::new().nest("/api", api_service).nest("/", ui);
        Server::new(TcpListener::bind(self.addr())).run(app).await
    }
}

#[handler]
pub fn hello(uri: &Uri) -> String {
    let rpath = uri.path();
    format!("hello, {}", rpath)
}