use std::path::PathBuf;

use clap::{Parser, ValueHint};

use crate::github::repository::Repository;

/// A command line tool to download release assets from GitHub
///
/// EXAMPLES:
/// Select and download an asset (interactive mode):
/// $ dra download devmatteini/dra-tests
///
/// Download a selected asset (non-interactive mode):
/// $ dra untag devmatteini/dra-tests
/// helloworld_{tag}.tar.gz
/// $ dra download -s "helloworld_{tag}.tar.gz" devmatteini/dra-tests
///
/// Automatically select and download an asset based on your operating system
/// and architecture (non-interactive mode):
/// $ dra download -a devmatteini/dra-tests
///
/// Download and install an asset:
/// $ dra download --install devmatteini/dra-tests
///
/// Download and install multiple executables from tar/zip archive asset:
/// $ dra download -s helloworld-many-executables-unix.tar.gz -I helloworld-v2 -I random-script devmatteini/dra-tests
///
/// More examples can be found at:
/// - https://github.com/devmatteini/dra#usage
/// - https://github.com/devmatteini/dra#examples
#[derive(Debug, Parser)]
#[command(name = "dra", version, verbatim_doc_comment)]
pub struct Cli {
    #[command(subcommand)]
    pub cmd: Command,
}

#[derive(Debug, Parser)]
pub enum Command {
    /// Select and download an asset
    Download {
        /// GitHub repository using format {owner}/{repo} or the repository URL https://github.com/{owner}/{repo}
        #[arg(value_parser = Repository::try_parse)]
        repo: Repository,

        /// Select and download the first asset that matches a given pattern.
        ///
        /// Supported patterns are:
        /// - Literal, the exact name of the asset (e.g. helloworld.tar.gz)
        /// - Untagged, a version-free pattern of your asset, generated by `untag` command (e.g. helloworld_{tag}.tar.gz)
        /// - Wildcard, a pattern that uses `*` and/or `?` special characters (e.g. helloworld*_amd64.deb)
        #[arg(
            short,
            long,
            group = "non-interactive",
            value_name = "PATTERN",
            verbatim_doc_comment
        )]
        select: Option<String>,

        /// Automatically select and download an asset based on your operating system and architecture
        #[arg(short, long, group = "non-interactive")]
        automatic: bool,

        /// Set the tag name for fetching a specific release.
        /// Default value is the latest release
        #[arg(short, long, verbatim_doc_comment)]
        tag: Option<String>,

        /// Save asset to custom path (file or directory).
        /// Default path is current working directory and the name of the asset.
        /// When used with install feature, it will save the executable to the specified path when applicable.
        /// If you install multiple executables, it must be a directory path.
        #[arg(short, long, value_hint = ValueHint::AnyPath, verbatim_doc_comment)]
        output: Option<PathBuf>,

        /// Install downloaded asset
        ///
        /// Supported assets are:
        /// - Debian packages (requires elevated privileges)
        /// - RPM packages (requires elevated privileges)
        /// - Tar archives with executable(s)
        /// - Zip files with executable(s)
        /// - 7-Zip files with executable(s) (requires `7z` cli to be installed and in your `PATH`)
        /// - Compressed executable files
        /// - Executable files
        /// - AppImage files
        ///
        /// If a tar/zip archive contains many executables and cannot automatically detect which one to install, use `--install-file <INSTALL_FILE>`.
        #[arg(short, long, group = "install-feature", verbatim_doc_comment)]
        install: bool,

        /// Install downloaded asset and select which executable to install from a tar/zip archive.
        /// You can install multiple executables by specifying `-I/--install-file` multiple times.
        ///
        /// If you use this option for other types of assets, it will be treated as the default install.
        #[arg(
            short = 'I',
            long,
            num_args = 1,
            group = "install-feature",
            verbatim_doc_comment
        )]
        install_file: Option<Vec<String>>,
    },

    /// Select an asset and generate an untagged version of it
    Untag {
        /// GitHub repository using format {owner}/{repo} or the repository URL https://github.com/{owner}/{repo}
        #[arg(value_parser = Repository::try_parse)]
        repo: Repository,
    },

    /// Generate shell completion
    Completion {
        /// Shell to generate completion for
        #[arg(value_enum)]
        shell: clap_complete::Shell,
    },
}
