mod cli;
mod killer;
mod parser;
mod utils;

use clap::Parser;
use colored::*;

/// portslay - port-based process termination tool
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
    /// Target port number
    port: u16,

    /// Send SIGKILL (9) signal (default: SIGTERM)
    #[arg(short, long)]
    force: bool,

    /// Terminate all processes without confirmation
    #[arg(short, long)]
    all: bool,

    /// Only list processes, do nothing else
    #[arg(short, long)]
    list: bool,
}

fn main() {
    let args = Args::parse();
    let port = args.port;

    match parser::find_processes_on_port(port) {
        Ok(processes) => {
            if processes.is_empty() {
                utils::exit_with_error(&format!("No process found on port {}", port));
            }

            if args.list {
                println!("Processes on port {}:", port.to_string().cyan().bold());
                cli::display_processes(&processes);
                return;
            }

            if args.all {
                let pids: Vec<i32> = processes.iter().map(|p| p.pid).collect();
                for pid in pids {
                    if let Err(e) = killer::kill_process(pid, args.force) {
                        utils::exit_with_error(&e);
                    }
                }
                utils::print_success(&format!("All processes on port {} killed.", port));
                return;
            }

            if processes.len() == 1 {
                cli::display_processes(&processes);
                if cli::prompt_confirmation() {
                    if let Err(e) = killer::kill_process(processes[0].pid, args.force) {
                        utils::exit_with_error(&e);
                    }
                    utils::print_success(&format!("Process {} killed.", processes[0].pid));
                }
            } else {
                println!("Port {} is used by:", port.to_string().cyan().bold());
                cli::display_processes(&processes);

                match cli::prompt_selection(processes.len()) {
                    Some(cli::Selection::Index(idx)) => {
                        let p = &processes[idx];
                        if let Err(e) = killer::kill_process(p.pid, args.force) {
                            utils::exit_with_error(&e);
                        }
                        utils::print_success(&format!("Process {} killed.", p.pid));
                    }
                    Some(cli::Selection::All) => {
                        for p in processes {
                            if let Err(e) = killer::kill_process(p.pid, args.force) {
                                utils::exit_with_error(&e);
                            }
                        }
                        utils::print_success(&format!("All processes on port {} killed.", port));
                    }
                    None => {
                        println!("{}", "Bye!".yellow());
                    }
                }
            }
        }
        Err(e) => {
            utils::exit_with_error(&e);
        }
    }
}
