partiri-cli 0.1.6

partiri CLI — Deploy and manage services on Partiri Cloud
use inquire::Select;
use owo_colors::OwoColorize;

use crate::client::{ApiClient, WorkspaceSecret};
use crate::config::PartiriConfig;
use crate::error::Result;
use crate::output::{print_info, print_success, print_warning};

pub fn run(client: &ApiClient, mut config: PartiriConfig) -> Result<()> {
    println!("\n{}\n", "  partiri service token".bold().cyan());

    // Determine which secret type to list based on the configured source
    let has_registry = config
        .service
        .registry_url
        .as_ref()
        .map(|s| !s.is_empty())
        .unwrap_or(false);
    let source_kind = if has_registry {
        "registry"
    } else {
        "repository"
    };

    // Show the currently linked token if any
    if let Some(id) = &config.service.fk_service_secret {
        print_info(&format!("Current token: {}", id));
    } else {
        print_info("No authentication token is currently linked.");
    }

    // Fetch secrets scoped to the service's workspace
    let secrets = if has_registry {
        client.list_registry_secrets(&config.fk_workspace)?
    } else {
        client.list_repository_secrets(&config.fk_workspace)?
    };

    if secrets.is_empty() {
        print_warning(&format!(
            "No {} secrets found in workspace {}.\n  Create one in the Partiri dashboard first.",
            source_kind, config.fk_workspace
        ));
        return Ok(());
    }

    // Build option list — first entry lets the user clear the token
    let mut labels: Vec<String> = vec!["-- none (clear token) --".to_string()];
    labels.extend(secrets.iter().map(secret_label));

    let choice = Select::new(&format!("Select {} token:", source_kind), labels.clone())
        .prompt()
        .map_err(|_| "Cancelled.")?;

    if choice == labels[0] {
        // User chose to clear the token
        config.service.fk_service_secret = None;
        config.save()?;
        print_success("Authentication token cleared.");
    } else {
        let idx = labels
            .iter()
            .position(|l| l == &choice)
            .ok_or("Selected token not found in list")?;
        // idx 0 is "none", so secret index is idx - 1
        let secret_id = secrets[idx - 1].id.clone();
        config.service.fk_service_secret = Some(secret_id.clone());
        config.save()?;
        print_success(&format!("Token {} linked.", secret_id));
    }

    print_info("Run 'partiri service push' to apply the change to Partiri.");
    Ok(())
}

fn secret_label(s: &WorkspaceSecret) -> String {
    let name = s.name.as_deref().unwrap_or("unnamed");
    match s.provider.as_deref() {
        Some(p) => format!("{} [{}] ({})", name, p, s.id),
        None => format!("{} ({})", name, s.id),
    }
}