updt 0.1.35

Cross-platform update helper for npm, cargo, rustup, fnm, scoop, Homebrew, paru, flatpak, pacman, and pkg.
use chrono::Local;
use crossterm::style::Color as TermColor;
use std::io;
use std::process;

mod checks;
mod cli;
mod command;
mod completion;
mod flow;
mod output;
mod parse;
mod profile;
mod selection;
mod state;
mod ui;
mod upgrade;

use crate::cli::{CliCommand, parse_cli};
use crate::completion::install_fish_completion;
use crate::flow::check::{
    any_check_failed, build_upgradable_targets, resolve_check_targets, run_checks, run_checks_plain,
};
use crate::flow::interactive::{
    InteractiveResult, offer_install_cargo_update, run_interactive_flow,
};
use crate::output::{color_bold, ok_text, print_exit_signal_message, print_section, warn_text};
use crate::profile::{interactive_terminal, parse_profile};
use crate::selection::{resolve_cli_selection, select_targets, select_targets_prompt};
use crate::state::{AppState, profile_name};
use crate::upgrade::upgrade_selected;

fn main() {
    let cli = parse_cli();

    if matches!(cli, CliCommand::Fish) {
        match install_fish_completion() {
            Ok(path) => {
                println!("fish completion 已写入: {}", path.display());
                process::exit(0);
            }
            Err(err) => {
                eprintln!("[fish] 写入失败: {err}");
                process::exit(1);
            }
        }
    }

    let mut state = AppState::default();
    parse_profile(&mut state);
    let start_time = Local::now().format("%Y-%m-%d %H:%M:%S").to_string();

    let requested_updates = match &cli {
        CliCommand::Update(v) => v.clone(),
        _ => Vec::new(),
    };

    let mut force_text_flow = false;
    if interactive_terminal() {
        match run_interactive_flow(&mut state, &requested_updates, &start_time) {
            Ok(InteractiveResult::Exit(code)) => process::exit(code),
            Ok(InteractiveResult::RunUpgrade(selected_targets)) => {
                if upgrade_selected(&state, &selected_targets) {
                    process::exit(0);
                }
                process::exit(1);
            }
            Err(err) => {
                if err.kind() == io::ErrorKind::Interrupted {
                    print_exit_signal_message();
                    process::exit(0);
                }
                eprintln!("[ui] TUI 运行失败, 自动回退文本流程: {err}");
                force_text_flow = true;
            }
        }
    }

    if !interactive_terminal() || force_text_flow {
        print_section("检查可升级项");
        println!(
            "{}: {}",
            color_bold("开始时间", TermColor::Blue),
            start_time
        );
        println!(
            "{}: {}",
            color_bold("系统策略", TermColor::Blue),
            profile_name(state.system_profile)
        );
    }

    if force_text_flow {
        let targets = resolve_check_targets(&state, &requested_updates);
        run_checks_plain(&mut state, &targets);
    } else {
        run_checks(&mut state, &requested_updates, &start_time);
    }
    offer_install_cargo_update(&mut state);

    let upgradable_targets = build_upgradable_targets(&state);

    if upgradable_targets.is_empty() {
        print_section("汇总");
        println!("{}", ok_text("没有可升级项."));
        if any_check_failed(&state) {
            println!("{}", warn_text("但有检查失败, 请根据上方日志排查."));
            process::exit(1);
        }
        process::exit(0);
    }

    if !interactive_terminal() {
        print_section("选择要升级的项目");
    }
    let selected_targets = if requested_updates.is_empty() {
        if force_text_flow {
            select_targets_prompt(&state, &upgradable_targets)
        } else {
            select_targets(&state, &upgradable_targets)
        }
    } else {
        resolve_cli_selection(&requested_updates, &upgradable_targets)
    };

    if selected_targets.is_empty() {
        println!("{}", warn_text("未选择任何升级项, 已退出."));
        process::exit(0);
    }

    if upgrade_selected(&state, &selected_targets) {
        process::exit(0);
    }
    process::exit(1);
}