//! `fafb-q info` command — display queue and namespace information.
//!
//! Uses the HTTP info endpoints:
//! - `GET /v1/{namespace}/{topic}/info` — topic details
//! - `GET /v1/{namespace}/topics` — list topics in a namespace

use colored::Colorize;

use super::{
    CliConfig, CliError, InfoArgs, OutputFormat, build_http_client, extract_error_message,
    format_bytes, http_base_url, response_json,
};

pub async fn run(config: CliConfig, args: InfoArgs) -> Result<(), CliError> {
    let target = args.target.ok_or_else(|| {
        CliError::Error("usage: fafb-q info <namespace> or fafb-q info <namespace>/<topic>".into())
    })?;

    let format = OutputFormat::auto_detect(config.json, false);
    let client = build_http_client(&config)?;
    let base = http_base_url(&config);

    let api_key = config.api_key.as_deref().ok_or_else(|| {
        CliError::Error("no API key specified — use --api-key, FAFB_API_KEY, or config file".into())
    })?;

    if target.contains('/') {
        let (ns, topic) = target.split_once('/').expect("checked contains('/')");
        topic_info(&client, &base, api_key, ns, topic, format).await
    } else {
        namespace_topics(&client, &base, api_key, &target, format).await
    }
}

async fn topic_info(
    client: &reqwest::Client,
    base: &str,
    api_key: &str,
    ns: &str,
    topic: &str,
    format: OutputFormat,
) -> Result<(), CliError> {
    let url = format!("{base}/v1/{ns}/{topic}/info");
    let resp = client
        .get(&url)
        .bearer_auth(api_key)
        .send()
        .await
        .map_err(|e| CliError::Error(format!("HTTP request failed: {e}")))?;

    let status = resp.status();
    let body = response_json(resp).await?;

    if !status.is_success() {
        return Err(CliError::Error(format!(
            "server error ({status}): {}",
            extract_error_message(&body)
        )));
    }

    match format {
        OutputFormat::Json => {
            println!("{body}");
        }
        _ => {
            println!("{} {ns}", "Namespace:".dimmed());
            println!("{} {topic}", "Topic:    ".dimmed());
            if let Some(head) = body.get("head_offset").and_then(|v| v.as_u64()) {
                println!("  {} {head}", "Head offset:      ".dimmed());
            }
            if let Some(base_off) = body.get("base_offset").and_then(|v| v.as_u64()) {
                println!("  {} {base_off}", "Base offset:      ".dimmed());
            }
            if let Some(depth) = body.get("depth").and_then(|v| v.as_u64()) {
                println!("  {} {depth}", "Messages:         ".dimmed());
            }
            if let Some(bytes) = body.get("bytes_used").and_then(|v| v.as_u64()) {
                println!(
                    "  {} {}",
                    "Disk bytes:       ".dimmed(),
                    format_bytes(bytes)
                );
            }
            if let Some(subs) = body.get("subscriber_count").and_then(|v| v.as_u64()) {
                let groups = body
                    .get("consumer_group_count")
                    .and_then(|v| v.as_u64())
                    .unwrap_or(0);
                println!(
                    "  {} {subs} ({groups} groups)",
                    "Subscribers:      ".dimmed()
                );
            }
            if let Some(oldest) = body.get("oldest_timestamp_millis").and_then(|v| v.as_u64()) {
                println!(
                    "  {} {}",
                    "Oldest message:   ".dimmed(),
                    crate::types::millis_to_rfc3339(oldest)
                );
            }
            if let Some(newest) = body.get("newest_timestamp_millis").and_then(|v| v.as_u64()) {
                println!(
                    "  {} {}",
                    "Newest message:   ".dimmed(),
                    crate::types::millis_to_rfc3339(newest)
                );
            }
        }
    }

    Ok(())
}

async fn namespace_topics(
    client: &reqwest::Client,
    base: &str,
    api_key: &str,
    ns: &str,
    format: OutputFormat,
) -> Result<(), CliError> {
    let url = format!("{base}/v1/{ns}/topics");
    let resp = client
        .get(&url)
        .bearer_auth(api_key)
        .send()
        .await
        .map_err(|e| CliError::Error(format!("HTTP request failed: {e}")))?;

    let status = resp.status();
    let body = response_json(resp).await?;

    if !status.is_success() {
        return Err(CliError::Error(format!(
            "server error ({status}): {}",
            extract_error_message(&body)
        )));
    }

    match format {
        OutputFormat::Json => {
            println!("{body}");
        }
        _ => {
            println!("{} {ns}", "Namespace:".dimmed());
            if let Some(topics) = body.get("topics").and_then(|v| v.as_array()) {
                println!("{} ({})", "Topics:".dimmed(), topics.len());
                for t in topics {
                    if let Some(name) = t.as_str() {
                        println!("  {name}");
                    }
                }
            } else {
                println!("  {}", "(no topics)".dimmed());
            }
        }
    }

    Ok(())
}
