use crate::client::KeepClient;
use crate::config::Settings;
use anyhow::Result;
use clap::Command;
use log::debug;
use std::collections::HashMap;

/// Client update mode: runs meta plugins on the server for an existing item.
///
/// Sends the list of plugin names (from --meta-plugin config) and any direct
/// metadata (--meta key=value) to the server. The server reads the stored file,
/// runs the specified plugins, and stores the results.
pub fn mode(
    client: &KeepClient,
    cmd: &mut Command,
    settings: &Settings,
    ids: &mut [i64],
    tags: &mut [String],
) -> Result<(), anyhow::Error> {
    debug!("CLIENT_UPDATE: Updating item via remote server");

    if ids.len() != 1 {
        cmd.error(
            clap::error::ErrorKind::InvalidValue,
            "--update requires exactly one numeric ID",
        )
        .exit();
    }

    let item_id = ids[0];

    // Collect plugin names from settings (--meta-plugin config)
    let plugin_names: Vec<String> = settings
        .meta_plugins_names()
        .into_iter()
        .flat_map(|s| {
            s.split(',')
                .map(|p| p.trim().to_string())
                .collect::<Vec<_>>()
        })
        .filter(|p| !p.is_empty())
        .collect();

    // Collect direct metadata from --meta flags
    let metadata: HashMap<String, String> = settings
        .meta
        .iter()
        .filter_map(|(k, v)| v.as_ref().map(|val| (k.clone(), val.clone())))
        .collect();

    // Build query params
    let mut params: Vec<(String, String)> = Vec::new();

    if !plugin_names.is_empty() {
        params.push(("plugins".to_string(), plugin_names.join(",")));
    }

    if !metadata.is_empty() {
        let meta_json = serde_json::to_string(&metadata)?;
        params.push(("metadata".to_string(), meta_json));
    }

    if !tags.is_empty() {
        params.push(("tags".to_string(), tags.join(",")));
    }

    // Nothing to update
    if params.is_empty() {
        if !settings.quiet {
            eprintln!("KEEP: No changes specified for item {item_id}");
        }
        return Ok(());
    }

    let param_refs: Vec<(&str, &str)> = params
        .iter()
        .map(|(k, v)| (k.as_str(), v.as_str()))
        .collect();

    let url_path = format!("/api/item/{item_id}/update");

    // POST to update endpoint
    let _item_info = client.post_bytes(&url_path, &[], &param_refs)?;

    if !settings.quiet {
        let mut parts = Vec::new();
        if !plugin_names.is_empty() {
            parts.push(format!("plugins: {}", plugin_names.join(", ")));
        }
        if !metadata.is_empty() {
            parts.push(format!("{} metadata", metadata.len()));
        }
        if !tags.is_empty() {
            parts.push(format!("tags: {}", tags.join(" ")));
        }
        let action = parts.join(", ");

        eprintln!("KEEP: Updated item {item_id} ({action})");
    }

    Ok(())
}
