use clap::{ArgAction, Args, Parser, Subcommand, arg};
use color_print::cstr;

const EXAMPLE_USAGE: &str = cstr!(
    "<underline>Example Usage:</underline>
  php-upgrade 8.3 8.4
  a2enconf php8.4-fpm # Update webserver config
  php-upgrade purge 8.3"
);

/// Upgrade and manage PHP version-specific packages with ease
#[derive(Parser, Debug)]
#[command(
    version,
    flatten_help = true,
    after_help = EXAMPLE_USAGE,
    args_conflicts_with_subcommands = true,
    disable_help_flag = true,
    disable_version_flag = true,
)]
pub struct EntryArgs {
    #[command(subcommand)]
    pub command: Option<ProgramCommands>,

    #[command(flatten)]
    pub global: GlobalArgs,

    /// Print help information and exit
    #[arg(short, long, action = ArgAction::Help, global = true)]
    help: Option<bool>,

    /// Print php-upgrade's version and exit
    #[arg(short, long, action = ArgAction::Version)]
    version: Option<bool>,

    #[command(flatten)]
    pub upgrade: UpgradeArgs,
}

#[derive(Args, Debug)]
#[command(next_help_heading = "Options")]
pub struct GlobalArgs {
    /// Skip confirmation prompts, accept defaults, and run non-interactively. If an undesirable situation occurs, the program will abort
    #[arg(short = 'y', long = "yes", global = true)]
    pub non_interactive: bool,

    /// Run in offline mode. Will not fetch the latest PHP version number
    #[arg(long, global = true)]
    pub offline: bool,
}

#[derive(Subcommand, Debug)]
pub enum ProgramCommands {
    Upgrade(UpgradeArgs),
    Purge(PurgeArgs),
    IniDiff(IniDiffArgs),
    ListPackages(ListPackagesArgs),
    LatestVer(LatestVersionArgs),
    InstalledVer(InstalledVersionArgs),
}

/// Upgrade all PHP packages for a specific version
#[derive(Args, Debug)]
#[command(next_help_heading = "Upgrade Options")] // For top-level command
pub struct UpgradeArgs {
    /// The version to upgrade from. Defaults to the current CLI PHP version
    #[arg(short, long, value_name = "FROM_VER")]
    pub from: Option<String>,

    /// The version to upgrade to. Defaults to the latest available PHP version
    #[arg(value_name = "TO_VER")]
    pub to: Option<String>,
}

/// Purge all PHP packages for a specific version
#[derive(Args, Debug)]
pub struct PurgeArgs {
    /// The version to purge all packages for
    pub version: Option<String>,
}

/// Show the difference between the php.ini files of two PHP versions
#[derive(Args, Debug)]
pub struct IniDiffArgs {
    /// The PHP version to compare from
    #[arg(value_name = "FROM_VER")]
    pub from: Option<String>,

    /// The PHP version to compare to. Defaults to the current CLI PHP version
    #[arg(value_name = "TO_VER")]
    pub to: Option<String>,
}

/// List all installed packages for a specific PHP version
#[derive(Args, Debug)]
pub struct ListPackagesArgs {
    /// The version to list packages for. Defaults to the installed version
    pub version: Option<String>,
}

/// Get the version number of the latest PHP release
#[derive(Args, Debug)]
pub struct LatestVersionArgs {}

/// Get the currently installed PHP version number
#[derive(Args, Debug)]
pub struct InstalledVersionArgs {}
