use crate::{delete, import};
use clap::{Parser, Subcommand};
use hagrid_database::Query;
use std::path::PathBuf;

#[derive(Parser)]
#[command(version, about, long_about = None, help_expected = true)]
pub(crate) struct Cli {
    #[arg(long, required = false, env = "HAGRID_DB_FILE_PATH")]
    /// Set a path to the Sqlite database file
    db_file_path: PathBuf,

    #[command(subcommand)]
    command: Command,
}

#[derive(Subcommand)]
enum Command {
    /// Delete (address, key)-binding(s), and/or a key(s).
    Delete {
        #[arg(long)]
        /// Also, delete all bindings
        all_bindings: bool,

        #[arg(long)]
        /// Also, delete all bindings and the key
        all: bool,

        /// E-Mail address, Fingerprint, or KeyID of the TPK to delete.
        /// If a Fingerprint or KeyID is given, --all is implied.
        query: Query,
    },
    /// Import keys into Hagrid
    Import {
        #[arg(required = true)]
        /// List of keyring files to import
        keyring_files: Vec<PathBuf>,
    },
}

pub(crate) fn dispatch_cmd(cli: &Cli) -> anyhow::Result<()> {
    let db_file_path = cli.db_file_path.canonicalize()?;

    match &cli.command {
        Command::Delete {
            query,
            all_bindings,
            all,
        } => delete::run(db_file_path, query, *all_bindings, *all),
        Command::Import { keyring_files } => import::run(db_file_path, keyring_files.to_owned()),
    }
}

pub(crate) fn print_errors(e: anyhow::Error) {
    eprint!("{}", e);
    let mut cause = e.source();
    while let Some(c) = cause {
        eprint!(":\n  {}", c);
        cause = c.source();
    }
    eprintln!();
}

#[cfg(test)]
mod tests {
    use super::*;
    use clap::CommandFactory;

    #[test]
    fn test_cli() {
        Cli::command().debug_assert()
    }
}
