use basic_jwt::JWTPrivateKey;
use clap::Parser;
use std::os::unix::prelude::CommandExt;
use std::process::Command;
use std::str::FromStr;
use virtweb_backend::api_tokens::TokenVerb;
use virtweb_backend::extractors::api_auth_extractor::TokenClaims;
use virtweb_backend::utils::time_utils::time;

/// cURL wrapper to query Virtweb backend API
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
    /// URL of VirtWeb
    #[arg(short('u'), long, env, default_value = "http://localhost:8000")]
    virtweb_url: String,

    /// Token ID
    #[arg(short('i'), long, env)]
    token_id: String,

    /// Token private key
    #[arg(short('t'), long, env)]
    token_key: String,

    /// Request verb
    #[arg(short('X'), long, default_value = "GET")]
    verb: String,

    /// Request URI
    uri: String,

    /// Command line arguments to pass to cURL
    #[clap(trailing_var_arg = true, allow_hyphen_values = true)]
    run: Vec<String>,
}

fn main() {
    let args = Args::parse();

    let full_url = format!("{}{}", args.virtweb_url, args.uri);
    log::debug!("Full URL: {full_url}");

    let key = JWTPrivateKey::ES384 {
        r#priv: args.token_key,
    };
    let claims = TokenClaims {
        sub: args.token_id.to_string(),
        iat: time() as usize,
        exp: time() as usize + 50,
        verb: TokenVerb::from_str(&args.verb).expect("Invalid request verb!"),
        path: args.uri,
        nonce: uuid::Uuid::new_v4().to_string(),
    };

    let jwt = key.sign_jwt(&claims).expect("Failed to sign JWT!");

    Command::new("curl")
        .args(["-X", &args.verb])
        .args(["-H", &format!("x-token-id: {}", args.token_id)])
        .args(["-H", &format!("x-token-content: {jwt}")])
        .args(args.run)
        .arg(full_url)
        .exec();
    panic!("Failed to run curl!")
}