use std::net::SocketAddr;

use clap::{Parser, Subcommand};

use crate::{api, state::State};

#[derive(Parser)]
#[command(author, version, about, long_about = None, subcommand_required = true)]
pub struct Command {
    #[command(subcommand)]
    command: Option<Commands>,
}

#[derive(Subcommand)]
enum Commands {
    Serve {
        #[arg(env = "SERVICE_HOST", long, default_value = "127.0.0.1:3000")]
        host: SocketAddr,
    },
}

impl Command {
    pub async fn execute() -> anyhow::Result<()> {
        let cmd = Command::parse();

        match cmd.command {
            Some(Commands::Serve { host }) => {
                tracing::info!("Starting service");

                let state = State::new().await?;
                let app = api::create_router(state);

                tracing::info!("listening on {}", host);
                let listener = tokio::net::TcpListener::bind(host).await?;
                axum::serve(listener, app.into_make_service()).await?;
            }
            None => {
                // This shouldn't happen due to subcommand_required = true
                anyhow::bail!("No command provided");
            }
        }

        Ok(())
    }
}
