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 worlds = client.mp().list_worlds().await?;
    
    if worlds.is_empty() {
        println!("No worlds found");
    } else {
        println!("Worlds:");
        for world in worlds {
            println!("  - {} (ID: {})", world.name, world.world_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 world = client.mp().create_world(&name).await?;
    
    println!("✓ World created:");
    println!("  Name: {}", world.name);
    println!("  World ID: {}", world.world_id);
    if let Some(secret) = world.secret {
        println!("  Secret: {}", secret);
    }
    
    Ok(())
}

pub async fn delete(world_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_world(&world_id).await?;
    
    println!("✓ World deleted: {}", world_id);
    
    Ok(())
}

pub async fn get(world_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 world = client.mp().get_world(&world_id).await?;
    
    println!("World Details:");
    println!("  Name: {}", world.name);
    println!("  World ID: {}", world.world_id);
    
    Ok(())
}

pub async fn reset_secret(world_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 world = client.mp().reset_world_secret(&world_id).await?;
    
    println!("✓ World secret reset:");
    println!("  World ID: {}", world.world_id);
    if let Some(secret) = world.secret {
        println!("  New Secret: {}", secret);
    }
    
    Ok(())
}

pub async fn upload(world_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_world_upload_urls(&world_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(world_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_world_download_urls(&world_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(())
}