use std::env;
use std::path::{Path, PathBuf};
use std::process::{self, Command};

const VERSION: &str = env!("CARGO_PKG_VERSION");
const PROJECT_URL: &str = "https://github.com/eunomia-bpf/agentsight";

fn main() {
    let args: Vec<String> = env::args().skip(1).collect();
    if args.iter().any(|arg| arg == "-h" || arg == "--help") || args.is_empty() {
        print_help();
        return;
    }

    if args.iter().any(|arg| arg == "-V" || arg == "--version") {
        print_version();
        return;
    }

    let Some(agentsight) = find_on_path("agentsight") else {
        eprintln!("asight: could not find the `agentsight` collector on PATH.");
        eprintln!("Install the official collector with:");
        eprintln!();
        eprintln!("  cargo install agentsight");
        eprintln!();
        eprintln!("Project: {PROJECT_URL}");
        process::exit(127);
    };

    exec_agentsight(&agentsight, &args);
}

fn print_help() {
    println!(
        "asight {VERSION}

Official short command alias for Eunomia AgentSight.

Usage:
  asight --help
  asight --version
  asight <agentsight-args>...

Examples:
  asight record -- claude
  asight top
  asight report export -o snapshot.json

This binary forwards commands to the official `agentsight` collector when it is
available on PATH. Install the collector with:

  cargo install agentsight

Project:
  {PROJECT_URL}"
    );
}

fn print_version() {
    println!("asight {VERSION}");
    println!("Official alias for Eunomia AgentSight: {PROJECT_URL}");

    if let Some(agentsight) = find_on_path("agentsight") {
        match Command::new(agentsight).arg("--version").output() {
            Ok(output) if output.status.success() && !output.stdout.is_empty() => {
                println!(
                    "collector: {}",
                    String::from_utf8_lossy(&output.stdout).trim()
                );
            }
            Ok(_) | Err(_) => {}
        }
    }
}

fn find_on_path(command: &str) -> Option<PathBuf> {
    if command.contains(std::path::MAIN_SEPARATOR) {
        let path = PathBuf::from(command);
        return is_executable_file(&path).then_some(path);
    }

    let path_var = env::var_os("PATH")?;
    env::split_paths(&path_var)
        .map(|dir| dir.join(command))
        .find(|candidate| is_executable_file(candidate))
}

fn is_executable_file(path: &Path) -> bool {
    path.is_file()
}

fn exec_agentsight(agentsight: &Path, args: &[String]) -> ! {
    #[cfg(unix)]
    {
        use std::os::unix::process::CommandExt;
        let err = Command::new(agentsight).args(args).exec();
        eprintln!("asight: failed to exec `{}`: {err}", agentsight.display());
        process::exit(126);
    }

    #[cfg(not(unix))]
    {
        let status = Command::new(agentsight).args(args).status();
        match status {
            Ok(status) => process::exit(status.code().unwrap_or(1)),
            Err(err) => {
                eprintln!("asight: failed to run `{}`: {err}", agentsight.display());
                process::exit(126);
            }
        }
    }
}
