use anyhow::Result;

use crate::registry::{packages, tools, Scope};
use crate::ui::{self, style};

pub fn run() -> Result<()> {
    let tool_list = tools::list()?;
    let pkg_list = packages::list()?;

    if tool_list.is_empty() && pkg_list.is_empty() {
        println!("nothing in registry");
        return Ok(());
    }

    if !tool_list.is_empty() {
        println!("{}", style::bold("Tools"));
        let mut rows: Vec<Vec<String>> = Vec::with_capacity(tool_list.len());
        for r in &tool_list {
            rows.push(vec![
                r.tool.name.clone(),
                r.tool
                    .runtime
                    .map(|t| t.as_str().to_string())
                    .unwrap_or_else(|| "-".into()),
                r.source.label().to_string(),
                r.tool.description.clone().unwrap_or_default(),
            ]);
        }
        ui::print_table_styled(
            &["Tool", "Runtime", "Source", "Description"],
            &rows,
            Some(3),
            Some(&|col, cell| match col {
                0 => style::cyan(cell),
                1 | 2 => style::dim(cell),
                3 => cell.to_string(),
                _ => cell.to_string(),
            }),
        );
        println!();
    }

    if !pkg_list.is_empty() {
        println!("{}", style::bold("Packages"));
        let mut rows: Vec<Vec<String>> = Vec::with_capacity(pkg_list.len());
        for r in &pkg_list {
            let tools_list: Vec<&str> = r.package.tools.iter().map(|t| t.as_str()).collect();
            let tools_str = if tools_list.is_empty() {
                "any".into()
            } else {
                tools_list.join(",")
            };
            rows.push(vec![
                r.package.name.clone(),
                tools_str,
                scope_label(r.package.scope).to_string(),
                r.source.label().to_string(),
                r.package.description.clone().unwrap_or_default(),
            ]);
        }
        ui::print_table_styled(
            &["Package", "Tools", "Scope", "Source", "Description"],
            &rows,
            Some(4),
            Some(&|col, cell| match col {
                0 => style::cyan(cell),
                1 => style::dim(cell),
                2 => color_scope(cell),
                3 => style::dim(cell),
                _ => cell.to_string(),
            }),
        );
    }

    Ok(())
}

fn scope_label(s: Scope) -> &'static str {
    match s {
        Scope::Global => "global",
        Scope::Project => "project",
        Scope::Both => "both",
    }
}

fn color_scope(cell: &str) -> String {
    match cell {
        "global" => style::yellow(cell),
        "project" => style::magenta(cell),
        "both" => style::cyan(cell),
        _ => cell.to_string(),
    }
}
