wme-cli 0.1.3

CLI tool for the Wikimedia Enterprise API
use anyhow::Result;
use tracing::info;

use crate::client::map_client_error;
use crate::commands::GlobalOpts;
use crate::output::{format_table, OutputHandler};
use crate::util::build_params;

/// List all project codes
pub async fn project_codes(opts: &GlobalOpts) -> Result<()> {
    info!("Listing project codes");

    let client = opts.build_client().await?;

    let params = build_params(opts)?;
    let codes = client
        .metadata()
        .list_project_codes_with_params(params.as_ref())
        .await
        .map_err(map_client_error)?;

    let output = OutputHandler::new(opts.output);

    // Format as table if requested
    if matches!(opts.output, crate::output::OutputFormat::Table) {
        let headers = vec!["Code", "Name"];
        let rows: Vec<Vec<String>> = codes
            .iter()
            .map(|code| vec![code.identifier.clone(), code.name.clone()])
            .collect();
        output.output_raw(&format_table(&headers, &rows));
    } else {
        // Convert to serde_json::Value for consistent output
        let json_value = serde_json::to_value(&codes)?;
        output.output(&json_value)?;
    }

    Ok(())
}

/// Get specific project code info
pub async fn project_codes_get(code: &str, opts: &GlobalOpts) -> Result<()> {
    info!("Getting project code info: {}", code);

    let client = opts.build_client().await?;

    let params = build_params(opts)?;
    let project_code = client
        .metadata()
        .get_project_code_with_params(code, params.as_ref())
        .await
        .map_err(map_client_error)?;

    let output = OutputHandler::new(opts.output);
    let json_value = serde_json::to_value(&project_code)?;
    output.output(&json_value)?;

    Ok(())
}

/// List all languages
pub async fn languages(opts: &GlobalOpts) -> Result<()> {
    info!("Listing languages");

    let client = opts.build_client().await?;

    let params = build_params(opts)?;
    let languages = client
        .metadata()
        .list_languages_with_params(params.as_ref())
        .await
        .map_err(map_client_error)?;

    let output = OutputHandler::new(opts.output);

    // Format as table if requested
    if matches!(opts.output, crate::output::OutputFormat::Table) {
        let headers = vec!["Identifier", "Name"];
        let rows: Vec<Vec<String>> = languages
            .iter()
            .map(|lang| {
                vec![
                    lang.identifier.clone().unwrap_or_default(),
                    lang.name.clone().unwrap_or_default(),
                ]
            })
            .collect();
        output.output_raw(&format_table(&headers, &rows));
    } else {
        let json_value = serde_json::to_value(&languages)?;
        output.output(&json_value)?;
    }

    Ok(())
}

/// Get specific language info
pub async fn languages_get(identifier: &str, opts: &GlobalOpts) -> Result<()> {
    info!("Getting language info: {}", identifier);

    let client = opts.build_client().await?;

    let params = build_params(opts)?;
    let language = client
        .metadata()
        .get_language_with_params(identifier, params.as_ref())
        .await
        .map_err(map_client_error)?;

    let output = OutputHandler::new(opts.output);
    let json_value = serde_json::to_value(&language)?;
    output.output(&json_value)?;

    Ok(())
}

/// List all projects
pub async fn projects(opts: &GlobalOpts) -> Result<()> {
    info!("Listing projects");

    let client = opts.build_client().await?;

    let params = build_params(opts)?;
    let projects = client
        .metadata()
        .list_projects_with_params(params.as_ref())
        .await
        .map_err(map_client_error)?;

    let output = OutputHandler::new(opts.output);

    // Format as table if requested
    if matches!(opts.output, crate::output::OutputFormat::Table) {
        let headers = vec!["Identifier", "Code", "Name", "URL"];
        let rows: Vec<Vec<String>> = projects
            .iter()
            .map(|proj| {
                vec![
                    proj.identifier.clone(),
                    proj.code.clone().unwrap_or_default(),
                    proj.name.clone().unwrap_or_default(),
                    proj.url.clone().unwrap_or_default(),
                ]
            })
            .collect();
        output.output_raw(&format_table(&headers, &rows));
    } else {
        let json_value = serde_json::to_value(&projects)?;
        output.output(&json_value)?;
    }

    Ok(())
}

/// Get specific project info
pub async fn projects_get(identifier: &str, opts: &GlobalOpts) -> Result<()> {
    info!("Getting project info: {}", identifier);

    let client = opts.build_client().await?;

    let params = build_params(opts)?;
    let project = client
        .metadata()
        .get_project_with_params(identifier, params.as_ref())
        .await
        .map_err(map_client_error)?;

    let output = OutputHandler::new(opts.output);
    let json_value = serde_json::to_value(&project)?;
    output.output(&json_value)?;

    Ok(())
}

/// List all namespaces
pub async fn namespaces(opts: &GlobalOpts) -> Result<()> {
    info!("Listing namespaces");

    let client = opts.build_client().await?;

    let params = build_params(opts)?;
    let namespaces = client
        .metadata()
        .list_namespaces_with_params(params.as_ref())
        .await
        .map_err(map_client_error)?;

    let output = OutputHandler::new(opts.output);

    // Format as table if requested
    if matches!(opts.output, crate::output::OutputFormat::Table) {
        let headers = vec!["ID", "Name", "Description"];
        let rows: Vec<Vec<String>> = namespaces
            .iter()
            .map(|ns| {
                vec![
                    ns.identifier.to_string(),
                    ns.name.clone().unwrap_or_default(),
                    ns.description.clone().unwrap_or_default(),
                ]
            })
            .collect();
        output.output_raw(&format_table(&headers, &rows));
    } else {
        let json_value = serde_json::to_value(&namespaces)?;
        output.output(&json_value)?;
    }

    Ok(())
}

/// Get specific namespace info
pub async fn namespaces_get(id: u32, opts: &GlobalOpts) -> Result<()> {
    info!("Getting namespace info: {}", id);

    let client = opts.build_client().await?;

    let params = build_params(opts)?;
    let namespace = client
        .metadata()
        .get_namespace_with_params(id, params.as_ref())
        .await
        .map_err(map_client_error)?;

    let output = OutputHandler::new(opts.output);
    let json_value = serde_json::to_value(&namespace)?;
    output.output(&json_value)?;

    Ok(())
}