use crate::blacklist::get_blacklist;
use crate::colors::get_colors;
use crate::config::get_config;
use crate::load_data::load_data_json_nested;
use crate::utils::{format_size, get_dir_size, get_installed_packages, read_first_line};
use std::process::exit;

/// Displays repository and system statistics to stdout.
///
/// Prints the following sections:
///
/// * **Repository Information** — last update date (read from the changelog
///   file via [`read_first_line`]), local repository path, and active branch.
/// * **Total Packages / Categories** — aggregate counts across the full repo.
/// * **Packages by Category** — per-category package counts, sorted
///   alphabetically and laid out in three columns.
/// * **System Summary** — number of installed `SBo` packages, blacklisted
///   packages, and the current cache size (`tmp_sbpkg` directory).
///
/// Exits the process with code `1` if the changelog file cannot be read.
pub fn stats() {
    let cfg = get_config();
    let color = get_colors(cfg.colors);
    let repo = load_data_json_nested();

    let total_categories: usize = repo.keys().len();
    let total_packages: usize = repo.values().map(|pkgs| pkgs.len()).sum();
    let total_installed = get_installed_packages().len();
    let blacklisted = get_blacklist().len();

    let filename = format!("{}/{}", cfg.repo_path, cfg.changelog);
    let last_update = read_first_line(&filename).unwrap_or_else(|e| {
        eprintln!(
            "{}Error:{} {filename} not found: {}",
            color.red, color.reset, e
        );
        exit(1)
    });

    println!("{}Repository Information:{}", color.bold, color.reset);
    println!(
        "  Last Update: {}{}{}",
        color.yellow, last_update, color.reset
    );
    println!(
        "  Local Repository: {}{}{}",
        color.yellow, cfg.local_repo, color.reset
    );
    println!("  Branch: {}{}{}", color.cyan, cfg.branch, color.reset);

    println!(
        "  Total Packages: {}{}{}",
        color.green, total_packages, color.reset
    );
    println!(
        "  Total Categories: {}{}{}",
        color.green, total_categories, color.reset
    );

    println!("\n{}Packages by Category:{}", color.bold, color.reset);
    let mut categories: Vec<(&String, usize)> = Vec::new();
    for (cat, pkgs) in &repo {
        categories.push((cat, pkgs.len()));
    }

    categories.sort_by_key(|(cat, _)| cat.as_str());

    for chunk in categories.chunks(3) {
        for (cat, count) in chunk {
            print!("  {:<15} {}{:>4}{}  ", cat, color.green, count, color.reset);
        }
        println!();
    }

    println!("\n{}System Summary:{}", color.bold, color.reset);
    println!(
        "  Installed SBo: {}{}{}",
        color.green, total_installed, color.reset
    );
    println!("  Blacklisted: {}{}{}", color.red, blacklisted, color.reset);
    let size = format_size(get_dir_size(cfg.tmp_sbpkg).unwrap_or(0));
    println!("  Cache size: {}{}{}", color.green, size, color.reset);
}
