firecloud-cli 0.2.0

Command-line interface for FireCloud P2P messaging and file sharing
use anyhow::{Context, Result};
use colored::Colorize;
use dialoguer::{Select, Input, Confirm};
use std::path::PathBuf;
use crate::config::FireCloudConfig;

pub async fn run(data_dir: PathBuf) -> Result<()> {
    println!("\n{}", "⚙️  Modify Storage Provider Settings".bold().cyan());
    println!("{}", "".repeat(50).dimmed());
    
    // Load configuration
    let config_path = data_dir.join("config.toml");
    let mut config = FireCloudConfig::load(&config_path)
        .unwrap_or_default();
    
    // Check current status
    let current_quota = config.storage_quota;
    
    if let Some(quota) = current_quota {
        println!("\n{} Current Status: {}", "".green(), "Storage Provider Active".bold());
        println!("  Current Quota: {}", format_size(quota).yellow());
    } else {
        println!("\n{} Current Status: {}", "".blue(), "Not a Storage Provider".dimmed());
    }
    
    // Menu options
    let options = if current_quota.is_some() {
        vec![
            "Increase Storage Quota",
            "Decrease Storage Quota",
            "Disable Storage Sharing",
            "Cancel",
        ]
    } else {
        vec![
            "Enable Storage Sharing",
            "Cancel",
        ]
    };
    
    let selection = Select::new()
        .with_prompt("What would you like to do?")
        .items(&options)
        .default(0)
        .interact_opt()?;
    
    match selection {
        Some(idx) => {
            match options[idx] {
                "Enable Storage Sharing" => {
                    enable_storage_sharing(&mut config, &config_path).await?;
                }
                "Increase Storage Quota" => {
                    modify_quota(&mut config, &config_path, true).await?;
                }
                "Decrease Storage Quota" => {
                    modify_quota(&mut config, &config_path, false).await?;
                }
                "Disable Storage Sharing" => {
                    disable_storage_sharing(&mut config, &config_path).await?;
                }
                "Cancel" => {
                    println!("\n{} Operation cancelled", "".yellow());
                }
                _ => {}
            }
        }
        None => {
            println!("\n{} Operation cancelled", "".yellow());
        }
    }
    
    Ok(())
}

async fn enable_storage_sharing(config: &mut FireCloudConfig, config_path: &PathBuf) -> Result<()> {
    println!("\n{}", "Enable Storage Sharing".bold());
    
    let quota_str: String = Input::new()
        .with_prompt("How much storage would you like to provide? (e.g., 10GB, 500MB)")
        .default("10GB".to_string())
        .interact_text()?;
    
    let quota_bytes = parse_size(&quota_str)
        .context("Invalid storage size format")?;
    
    config.storage_quota = Some(quota_bytes);
    config.save(config_path)
        .context("Failed to save configuration")?;
    
    println!("\n{} Storage sharing enabled!", "".green());
    println!("  Quota: {}", format_size(quota_bytes).yellow());
    println!("\n{} Next: View your dashboard with {}", 
             "".blue(), 
             "firecloud usage".cyan());
    
    Ok(())
}

async fn modify_quota(config: &mut FireCloudConfig, config_path: &PathBuf, increase: bool) -> Result<()> {
    let current = config.storage_quota.unwrap_or(0);
    
    let action = if increase { "Increase" } else { "Decrease" };
    println!("\n{} Storage Quota", action.bold());
    println!("  Current: {}", format_size(current).dimmed());
    
    let new_quota_str: String = Input::new()
        .with_prompt("New quota (e.g., 20GB, 1TB)")
        .default(format_size(current))
        .interact_text()?;
    
    let new_quota = parse_size(&new_quota_str)
        .context("Invalid storage size format")?;
    
    // Validate
    if !increase && new_quota < current {
        let confirm = Confirm::new()
            .with_prompt(format!(
                "Warning: Decreasing quota may affect stored chunks. Continue?"
            ))
            .default(false)
            .interact()?;
        
        if !confirm {
            println!("\n{} Operation cancelled", "".yellow());
            return Ok(());
        }
    }
    
    config.storage_quota = Some(new_quota);
    config.save(config_path)
        .context("Failed to save configuration")?;
    
    println!("\n{} Quota updated!", "".green());
    println!("  Old: {}", format_size(current).dimmed());
    println!("  New: {}", format_size(new_quota).yellow());
    
    Ok(())
}

async fn disable_storage_sharing(config: &mut FireCloudConfig, config_path: &PathBuf) -> Result<()> {
    println!("\n{}", "Disable Storage Sharing".bold().yellow());
    
    let confirm = Confirm::new()
        .with_prompt("Are you sure? This will stop accepting new chunks.")
        .default(false)
        .interact()?;
    
    if !confirm {
        println!("\n{} Operation cancelled", "".yellow());
        return Ok(());
    }
    
    config.storage_quota = None;
    config.save(config_path)
        .context("Failed to save configuration")?;
    
    println!("\n{} Storage sharing disabled", "".green());
    println!("  Existing chunks will remain until manually deleted");
    println!("\n{} To re-enable later, run: {}", 
             "".blue(), 
             "firecloud mod".cyan());
    
    Ok(())
}

/// Parse size string like "10GB", "500MB" to bytes
fn parse_size(s: &str) -> Result<u64> {
    let s = s.trim().to_uppercase();
    
    let (num_str, multiplier) = if s.ends_with("TB") {
        (&s[..s.len()-2], 1_000_000_000_000u64)
    } else if s.ends_with("GB") {
        (&s[..s.len()-2], 1_000_000_000u64)
    } else if s.ends_with("MB") {
        (&s[..s.len()-2], 1_000_000u64)
    } else if s.ends_with("KB") {
        (&s[..s.len()-2], 1_000u64)
    } else if s.ends_with('B') {
        (&s[..s.len()-1], 1u64)
    } else {
        (s.as_str(), 1u64)
    };
    
    let num: f64 = num_str.trim().parse()
        .context("Invalid number in size specification")?;
    
    Ok((num * multiplier as f64) as u64)
}

/// Format bytes to human-readable string
fn format_size(bytes: u64) -> String {
    const KB: u64 = 1_000;
    const MB: u64 = 1_000_000;
    const GB: u64 = 1_000_000_000;
    const TB: u64 = 1_000_000_000_000;
    
    if bytes >= TB {
        format!("{:.2} TB", bytes as f64 / TB as f64)
    } else if bytes >= GB {
        format!("{:.2} GB", bytes as f64 / GB as f64)
    } else if bytes >= MB {
        format!("{:.2} MB", bytes as f64 / MB as f64)
    } else if bytes >= KB {
        format!("{:.2} KB", bytes as f64 / KB as f64)
    } else {
        format!("{} B", bytes)
    }
}