abpilot-cli 0.1.0

ABPilot Cli
use abpilot_cc_sdk::{AbpilotClient, AuthMethod};
use crate::config::load_config;
use std::path::Path;
use tokio::fs;

pub async fn list() -> Result<(), Box<dyn std::error::Error>> {
    let config = load_config()?;
    
    let mut client = AbpilotClient::new();
    client.mp_mut().set_auth(AuthMethod::api_key(config.apikey));
    
    let apps = client.mp().list_apps().await?;
    
    if apps.is_empty() {
        println!("No apps found");
    } else {
        println!("Apps:");
        for app in apps {
            println!("  - {} (ID: {})", app.name, app.app_id);
        }
    }
    
    Ok(())
}

pub async fn create(name: String) -> Result<(), Box<dyn std::error::Error>> {
    let config = load_config()?;
    
    let mut client = AbpilotClient::new();
    client.mp_mut().set_auth(AuthMethod::api_key(config.apikey));
    
    let app = client.mp().create_app(&name).await?;
    
    println!("✓ App created:");
    println!("  Name: {}", app.name);
    println!("  App ID: {}", app.app_id);
    if let Some(secret) = app.secret {
        println!("  Secret: {}", secret);
    }
    
    Ok(())
}

pub async fn delete(app_id: String) -> Result<(), Box<dyn std::error::Error>> {
    let config = load_config()?;
    
    let mut client = AbpilotClient::new();
    client.mp_mut().set_auth(AuthMethod::api_key(config.apikey));
    
    client.mp().delete_app(&app_id).await?;
    
    println!("✓ App deleted: {}", app_id);
    
    Ok(())
}

pub async fn reset_secret(app_id: String) -> Result<(), Box<dyn std::error::Error>> {
    let config = load_config()?;
    
    let mut client = AbpilotClient::new();
    client.mp_mut().set_auth(AuthMethod::api_key(config.apikey));
    
    let app = client.mp().reset_app_secret(&app_id).await?;
    
    println!("✓ App secret reset:");
    println!("  App ID: {}", app.app_id);
    if let Some(secret) = app.secret {
        println!("  New Secret: {}", secret);
    }
    
    Ok(())
}

pub async fn upload(app_id: String, files: Vec<String>) -> Result<(), Box<dyn std::error::Error>> {
    let config = load_config()?;
    
    let mut client = AbpilotClient::new();
    client.mp_mut().set_auth(AuthMethod::api_key(config.apikey));
    
    println!("Getting upload URLs for {} files...", files.len());
    let file_refs: Vec<&str> = files.iter().map(|s| s.as_str()).collect();
    let urls = client.mp().get_app_upload_urls(&app_id, &file_refs).await?;
    
    let http_client = reqwest::Client::new();
    
    for (file_path, upload_url) in files.iter().zip(urls.iter()) {
        let path = Path::new(file_path);
        if !path.exists() {
            eprintln!("✗ File not found: {}", file_path);
            continue;
        }
        
        println!("Uploading {}...", file_path);
        let content = fs::read(path).await?;
        
        let response = http_client
            .put(upload_url)
            .header("Content-Type", "application/octet-stream")
            .body(content)
            .send()
            .await?;
        
        if response.status().is_success() {
            println!("✓ Uploaded: {}", file_path);
        } else {
            let status = response.status();
            let body = response.text().await.unwrap_or_default();
            eprintln!("✗ Failed to upload {}: {} - {}", file_path, status, body);
        }
    }
    
    Ok(())
}

pub async fn download(app_id: String, files: Vec<String>) -> Result<(), Box<dyn std::error::Error>> {
    let config = load_config()?;
    
    let mut client = AbpilotClient::new();
    client.mp_mut().set_auth(AuthMethod::api_key(config.apikey));
    
    println!("Getting download URLs for {} files...", files.len());
    let file_refs: Vec<&str> = files.iter().map(|s| s.as_str()).collect();
    let urls = client.mp().get_app_download_urls(&app_id, &file_refs).await?;
    
    let http_client = reqwest::Client::new();
    
    for (file_path, download_url) in files.iter().zip(urls.iter()) {
        println!("Downloading {}...", file_path);
        
        let response = http_client
            .get(download_url)
            .send()
            .await?;
        
        if response.status().is_success() {
            let content = response.bytes().await?;
            let path = Path::new(file_path);
            
            if let Some(parent) = path.parent() {
                fs::create_dir_all(parent).await?;
            }
            
            fs::write(path, content).await?;
            println!("✓ Downloaded: {}", file_path);
        } else {
            eprintln!("✗ Failed to download {}: {}", file_path, response.status());
        }
    }
    
    Ok(())
}