use clap::{Parser, Subcommand, Args};


#[derive(Parser)]
#[command(name = "apt-ostree")]
#[command(about = "Debian/Ubuntu equivalent of rpm-ostree")]
#[command(version = "0.1.0")]
#[command(propagate_version = true)]
pub struct Cli {
    #[command(subcommand)]
    pub command: Commands,
}

#[derive(Subcommand)]
pub enum Commands {
    /// Get the version of the booted system
    Status(StatusArgs),
    
    /// Perform a system upgrade
    Upgrade(UpgradeArgs),
    
    /// Revert to the previously booted tree
    Rollback(RollbackArgs),
    
    /// Deploy a specific commit
    Deploy(DeployArgs),
    
    /// Switch to a different tree
    Rebase(RebaseArgs),
    
    /// Overlay additional packages
    Install(InstallArgs),
    
    /// Remove overlayed additional packages
    Uninstall(UninstallArgs),
    
    /// Search for packages
    Search(SearchArgs),
    
    /// Enable or disable local initramfs regeneration
    Initramfs(InitramfsArgs),
    
    /// Add files to the initramfs
    InitramfsEtc(InitramfsEtcArgs),
    
    /// Query or modify kernel arguments
    Kargs(KargsArgs),
    
    /// Reload configuration
    Reload(ReloadArgs),
    
    /// Cancel an active transaction
    Cancel(CancelArgs),
    
    /// Manage active transactions
    Transaction(TransactionArgs),
    
    /// Commands to compose a tree
    Compose(ComposeArgs),
    
    /// Commands to query the package database
    Db(DbArgs),
    
    /// Manage base package overrides
    Override(OverrideArgs),
    
    /// Remove all mutations
    Reset(ResetArgs),
    
    /// Generate package repository metadata
    RefreshMd(RefreshMdArgs),
    
    /// Apply pending deployment changes to booted deployment
    ApplyLive(ApplyLiveArgs),
    
    /// Apply a transient overlayfs to /usr
    Usroverlay(UsroverlayArgs),
    
    /// Clear cached/pending data
    Cleanup(CleanupArgs),
    
    /// Unset the finalization locking state and reboot
    FinalizeDeployment(FinalizeDeploymentArgs),
    
    /// Display system metrics and performance information
    Metrics(MetricsArgs),
    
    /// Start the daemon
    StartDaemon(StartDaemonArgs),
    
    /// Experimental features
    Ex(ExArgs),
    
    /// Telemetry and usage statistics
    Countme(CountmeArgs),
    
    /// Container management
    Container(ContainerArgs),
    
    /// Development and debugging tools (hidden)
    #[command(hide = true)]
    Testutils(TestutilsArgs),
    
    /// Shared library backend (hidden)
    #[command(hide = true)]
    ShlibBackend(ShlibBackendArgs),
    
    /// Internal system commands (hidden)
    #[command(hide = true)]
    Internals(InternalsArgs),
}

#[derive(Args)]
pub struct StatusArgs {
    /// Print additional fields (e.g. StateRoot); implies -a
    #[arg(short, long)]
    pub verbose: bool,
    
    /// Expand advisories listing
    #[arg(short, long)]
    pub advisories: bool,
    
    /// Output JSON
    #[arg(long)]
    pub json: bool,
    
    /// Filter JSONPath expression
    #[arg(short = 'J', long)]
    pub jsonpath: Option<String>,
    
    /// Only print the booted deployment
    #[arg(short, long)]
    pub booted: bool,
    
    /// If pending deployment available, exit 77
    #[arg(long)]
    pub pending_exit_77: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct UpgradeArgs {
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Initiate a reboot after operation is complete
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Permit deployment of chronologically older trees
    #[arg(long)]
    pub allow_downgrade: bool,
    
    /// Just preview package differences (implies --unchanged-exit-77)
    #[arg(long)]
    pub preview: bool,
    
    /// Just check if an upgrade is available (implies --unchanged-exit-77)
    #[arg(long)]
    pub check: bool,
    
    /// Do not download latest ostree and APT data
    #[arg(short, long)]
    pub cache_only: bool,
    
    /// Just download latest ostree and APT data, don't deploy
    #[arg(long)]
    pub download_only: bool,
    
    /// If no new deployment made, exit 77
    #[arg(long)]
    pub unchanged_exit_77: bool,
    
    /// Prevent automatic deployment finalization on shutdown
    #[arg(long)]
    pub lock_finalization: bool,
    
    /// Force an upgrade even if an updates driver is registered
    #[arg(long)]
    pub bypass_driver: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
    
    /// Overlay additional packages
    #[arg(long, value_delimiter = ',')]
    pub install: Vec<String>,
    
    /// Remove overlayed additional packages
    #[arg(long, value_delimiter = ',')]
    pub uninstall: Vec<String>,
}

#[derive(Args)]
pub struct RollbackArgs {
    /// Initiate a reboot after operation
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct DeployArgs {
    /// Commit to deploy
    pub commit: String,
    
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Initiate a reboot after operation is complete
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Just preview package differences
    #[arg(long)]
    pub preview: bool,
    
    /// Do not download latest ostree and APT data
    #[arg(short, long)]
    pub cache_only: bool,
    
    /// Just download latest ostree and APT data, don't deploy
    #[arg(long)]
    pub download_only: bool,
    
    /// Do not check if commit belongs on the same branch
    #[arg(long)]
    pub skip_branch_check: bool,
    
    /// Prevent automatic deployment finalization on shutdown
    #[arg(long)]
    pub lock_finalization: bool,
    
    /// Forbid deployment of chronologically older trees
    #[arg(long)]
    pub disallow_downgrade: bool,
    
    /// Register the calling agent as the driver for updates
    #[arg(long)]
    pub register_driver: Option<String>,
    
    /// Force a deploy even if an updates driver is registered
    #[arg(long)]
    pub bypass_driver: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
    
    /// Overlay additional package
    #[arg(long)]
    pub install: Option<String>,
    
    /// Remove overlayed additional package
    #[arg(long)]
    pub uninstall: Option<String>,
}

#[derive(Args)]
pub struct RebaseArgs {
    /// Target tree to rebase to
    pub target: String,
    
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Rebase to branch BRANCH; use --remote to change remote as well
    #[arg(short, long)]
    pub branch: Option<String>,
    
    /// Rebase to current branch name using REMOTE; may also be combined with --branch
    #[arg(long)]
    pub remote: Option<String>,
    
    /// Initiate a reboot after operation is complete
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Keep previous refspec after rebase
    #[arg(long)]
    pub skip_purge: bool,
    
    /// Do not download latest ostree and APT data
    #[arg(short, long)]
    pub cache_only: bool,
    
    /// Just download latest ostree and APT data, don't deploy
    #[arg(long)]
    pub download_only: bool,
    
    /// Human-readable description of custom origin
    #[arg(long)]
    pub custom_origin_description: Option<String>,
    
    /// Machine-readable description of custom origin
    #[arg(long)]
    pub custom_origin_url: Option<String>,
    
    /// Enable experimental features
    #[arg(long)]
    pub experimental: bool,
    
    /// Forbid deployment of chronologically older trees
    #[arg(long)]
    pub disallow_downgrade: bool,
    
    /// Prevent automatic deployment finalization on shutdown
    #[arg(long)]
    pub lock_finalization: bool,
    
    /// Force a rebase even if an updates driver is registered
    #[arg(long)]
    pub bypass_driver: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
    
    /// Overlay additional package
    #[arg(long)]
    pub install: Option<String>,
    
    /// Remove overlayed additional package
    #[arg(long)]
    pub uninstall: Option<String>,
}

#[derive(Args)]
pub struct InstallArgs {
    /// Packages to install
    pub packages: Vec<String>,
    
    /// Remove overlayed additional package
    #[arg(long)]
    pub uninstall: Option<String>,
    
    /// Do not download latest ostree and APT data
    #[arg(short, long)]
    pub cache_only: bool,
    
    /// Just download latest ostree and APT data, don't deploy
    #[arg(long)]
    pub download_only: bool,
    
    /// Apply changes to both pending deployment and running filesystem tree
    #[arg(long)]
    pub apply_live: bool,
    
    /// Allow package to replace files from other packages
    #[arg(long)]
    pub force_replacefiles: bool,
    
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Initiate a reboot after operation is complete
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Exit after printing the transaction
    #[arg(short, long)]
    pub dry_run: bool,
    
    /// Auto-confirm interactive prompts for non-security questions
    #[arg(short, long)]
    pub assumeyes: bool,
    
    /// Allow inactive package requests
    #[arg(long)]
    pub allow_inactive: bool,
    
    /// Do nothing if package already (un)installed
    #[arg(long)]
    pub idempotent: bool,
    
    /// If no overlays were changed, exit 77
    #[arg(long)]
    pub unchanged_exit_77: bool,
    
    /// Prevent automatic deployment finalization on shutdown
    #[arg(long)]
    pub lock_finalization: bool,
    
    /// Enable the repository based on the repo id. Is only supported in a container build.
    #[arg(long)]
    pub enablerepo: Option<String>,
    
    /// Only disabling all (*) repositories is supported currently. Is only supported in a container build.
    #[arg(long)]
    pub disablerepo: Option<String>,
    
    /// Set the releasever. Is only supported in a container build.
    #[arg(long)]
    pub releasever: Option<String>,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct UninstallArgs {
    /// Packages to remove
    pub packages: Vec<String>,
    
    /// Overlay additional package
    #[arg(long)]
    pub install: Option<String>,
    
    /// Remove all overlayed additional packages
    #[arg(long)]
    pub all: bool,
    
    /// Do not download latest ostree and APT data
    #[arg(short, long)]
    pub cache_only: bool,
    
    /// Just download latest ostree and APT data, don't deploy
    #[arg(long)]
    pub download_only: bool,
    
    /// Apply changes to both pending deployment and running filesystem tree
    #[arg(long)]
    pub apply_live: bool,
    
    /// Allow package to replace files from other packages
    #[arg(long)]
    pub force_replacefiles: bool,
    
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Initiate a reboot after operation is complete
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Exit after printing the transaction
    #[arg(short, long)]
    pub dry_run: bool,
    
    /// Auto-confirm interactive prompts for non-security questions
    #[arg(short, long)]
    pub assumeyes: bool,
    
    /// Allow inactive package requests
    #[arg(long)]
    pub allow_inactive: bool,
    
    /// Do nothing if package already (un)installed
    #[arg(long)]
    pub idempotent: bool,
    
    /// If no overlays were changed, exit 77
    #[arg(long)]
    pub unchanged_exit_77: bool,
    
    /// Prevent automatic deployment finalization on shutdown
    #[arg(long)]
    pub lock_finalization: bool,
    
    /// Enable the repository based on the repo id. Is only supported in a container build.
    #[arg(long)]
    pub enablerepo: Option<String>,
    
    /// Only disabling all (*) repositories is supported currently. Is only supported in a container build.
    #[arg(long)]
    pub disablerepo: Option<String>,
    
    /// Set the releasever. Is only supported in a container build.
    #[arg(long)]
    pub releasever: Option<String>,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct SearchArgs {
    /// Search query
    pub query: String,
    
    /// Remove overlayed additional package
    #[arg(long)]
    pub uninstall: Option<String>,
    
    /// Do not download latest ostree and APT data
    #[arg(short, long)]
    pub cache_only: bool,
    
    /// Just download latest ostree and APT data, don't deploy
    #[arg(long)]
    pub download_only: bool,
    
    /// Apply changes to both pending deployment and running filesystem tree
    #[arg(long)]
    pub apply_live: bool,
    
    /// Allow package to replace files from other packages
    #[arg(long)]
    pub force_replacefiles: bool,
    
    /// Overlay additional package
    #[arg(long)]
    pub install: Option<String>,
    
    /// Remove all overlayed additional packages
    #[arg(long)]
    pub all: bool,
    
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Initiate a reboot after operation is complete
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Exit after printing the transaction
    #[arg(short, long)]
    pub dry_run: bool,
    
    /// Auto-confirm interactive prompts for non-security questions
    #[arg(short, long)]
    pub assumeyes: bool,
    
    /// Allow inactive package requests
    #[arg(long)]
    pub allow_inactive: bool,
    
    /// Do nothing if package already (un)installed
    #[arg(long)]
    pub idempotent: bool,
    
    /// If no overlays were changed, exit 77
    #[arg(long)]
    pub unchanged_exit_77: bool,
    
    /// Prevent automatic deployment finalization on shutdown
    #[arg(long)]
    pub lock_finalization: bool,
    
    /// Enable the repository based on the repo id. Is only supported in a container build.
    #[arg(long)]
    pub enablerepo: Option<String>,
    
    /// Only disabling all (*) repositories is supported currently. Is only supported in a container build.
    #[arg(long)]
    pub disablerepo: Option<String>,
    
    /// Set the releasever. Is only supported in a container build.
    #[arg(long)]
    pub releasever: Option<String>,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct InitramfsArgs {
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Enable regenerating initramfs locally using dracut
    #[arg(long)]
    pub enable: bool,
    
    /// Append ARG to the dracut arguments
    #[arg(long)]
    pub arg: Option<String>,
    
    /// Disable regenerating initramfs locally
    #[arg(long)]
    pub disable: bool,
    
    /// Initiate a reboot after operation is complete
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Prevent automatic deployment finalization on shutdown
    #[arg(long)]
    pub lock_finalization: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct InitramfsEtcArgs {
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Deploy a new tree with the latest tracked /etc files
    #[arg(long)]
    pub force_sync: bool,
    
    /// Track root /etc file
    #[arg(long)]
    pub track: Option<String>,
    
    /// Untrack root /etc file
    #[arg(long)]
    pub untrack: Option<String>,
    
    /// Untrack all root /etc files
    #[arg(long)]
    pub untrack_all: bool,
    
    /// Initiate a reboot after operation is complete
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Prevent automatic deployment finalization on shutdown
    #[arg(long)]
    pub lock_finalization: bool,
    
    /// If no new deployment made, exit 77
    #[arg(long)]
    pub unchanged_exit_77: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct KargsArgs {
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Modify the kernel args from a specific deployment based on index. Index is in the form of a number (e.g. 0 means the first deployment in the list)
    #[arg(long)]
    pub deploy_index: Option<String>,
    
    /// Initiate a reboot after operation is complete
    #[arg(long)]
    pub reboot: bool,
    
    /// Append kernel argument; useful with e.g. console= that can be used multiple times. empty value for an argument is allowed
    #[arg(long, value_delimiter = ',')]
    pub append: Vec<String>,
    
    /// Replace existing kernel argument, the user is also able to replace an argument with KEY=VALUE if only one value exist for that argument
    #[arg(long, value_delimiter = ',')]
    pub replace: Vec<String>,
    
    /// Delete a specific kernel argument key/val pair or an entire argument with a single key/value pair
    #[arg(long, value_delimiter = ',')]
    pub delete: Vec<String>,
    
    /// Like --append, but does nothing if the key is already present
    #[arg(long, value_delimiter = ',')]
    pub append_if_missing: Vec<String>,
    
    /// Like --delete, but does nothing if the key is already missing
    #[arg(long, value_delimiter = ',')]
    pub delete_if_present: Vec<String>,
    
    /// If no kernel args changed, exit 77
    #[arg(long)]
    pub unchanged_exit_77: bool,
    
    /// Instead of modifying old kernel arguments, we modify args from current /proc/cmdline (the booted deployment)
    #[arg(long)]
    pub import_proc_cmdline: bool,
    
    /// Use an editor to modify the kernel arguments
    #[arg(long)]
    pub editor: bool,
    
    /// Prevent automatic deployment finalization on shutdown
    #[arg(long)]
    pub lock_finalization: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct ReloadArgs {
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct CancelArgs {
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct TransactionArgs {
    #[command(subcommand)]
    pub subcommand: TransactionSubcommands,
}

#[derive(Subcommand)]
pub enum TransactionSubcommands {
    /// List active transactions
    List,
    /// Show transaction details
    Show { transaction_id: String },
    /// Wait for transaction completion
    Wait { transaction_id: String },
}

#[derive(Args)]
pub struct ComposeArgs {
    #[command(subcommand)]
    pub subcommand: ComposeSubcommands,
}

#[derive(Subcommand)]
pub enum ComposeSubcommands {
    /// Process a "treefile"; install packages and commit the result to an OSTree repository
    Tree { 
        /// Path to treefile
        treefile: String,
        /// Path to OSTree repository
        #[arg(short, long)]
        repo: Option<String>,
        /// Path to OSTree repository for ostree-layers and ostree-override-layers
        #[arg(long)]
        layer_repo: Option<String>,
        /// Always create a new OSTree commit, even if nothing appears to have changed
        #[arg(long)]
        force_nocache: bool,
        /// Assume cache is present, do not attempt to update it
        #[arg(long)]
        cache_only: bool,
        /// Cached state
        #[arg(long)]
        cachedir: Option<String>,
        /// Rootfs to use for configuring libdnf
        #[arg(long)]
        source_root: Option<String>,
        /// Like --dry-run, but download and import RPMs as well; requires --cachedir
        #[arg(long)]
        download_only: bool,
        /// Like --dry-run, but download RPMs as well; requires --cachedir
        #[arg(long)]
        download_only_rpms: bool,
        /// HTTP proxy
        #[arg(long)]
        proxy: Option<String>,
        /// Just print the transaction and exit
        #[arg(long)]
        dry_run: bool,
        /// Just expand any includes and print treefile
        #[arg(long)]
        print_only: bool,
        /// Disable SELinux labeling, even if manifest enables it
        #[arg(long)]
        disable_selinux: bool,
        /// Update the modification time on FILE if a new commit was created
        #[arg(long)]
        touch_if_changed: Option<String>,
        /// Use this commit for change detection
        #[arg(long)]
        previous_commit: Option<String>,
        /// Use this input hash for change detection
        #[arg(long)]
        previous_inputhash: Option<String>,
        /// Use this version number for automatic version numbering
        #[arg(long)]
        previous_version: Option<String>,
        /// Working directory
        #[arg(long)]
        workdir: Option<String>,
        /// Also run default postprocessing
        #[arg(long)]
        postprocess: bool,
        /// Write lockfile to FILE
        #[arg(long)]
        ex_write_lockfile_to: Option<String>,
        /// Read lockfile from FILE
        #[arg(long)]
        ex_lockfile: Option<String>,
        /// With --ex-lockfile, only allow installing locked packages
        #[arg(long)]
        ex_lockfile_strict: bool,
        /// Append given key and value (in string format) to metadata
        #[arg(long)]
        add_metadata_string: Vec<String>,
        /// Parse the given JSON file as object, convert to GVariant, append to OSTree commit
        #[arg(long)]
        add_metadata_from_json: Option<String>,
        /// File to write the composed commitid to instead of updating the ref
        #[arg(long)]
        write_commitid_to: Option<String>,
        /// Write JSON to FILE containing information about the compose run
        #[arg(long)]
        write_composejson_to: Option<String>,
        /// Always commit without a parent
        #[arg(long)]
        no_parent: bool,
        /// Commit with specific parent
        #[arg(long)]
        parent: Option<String>,
        /// Enable verbose output
        #[arg(long)]
        verbose: bool,
        /// Generate container image
        #[arg(long)]
        container: bool,
    },
    /// Install packages into a target path
    Install { 
        /// Path to treefile
        treefile: String,
        /// Destination directory
        destdir: String,
        /// Path to OSTree repository
        #[arg(short, long)]
        repo: Option<String>,
        /// Path to OSTree repository for ostree-layers and ostree-override-layers
        #[arg(long)]
        layer_repo: Option<String>,
        /// Always create a new OSTree commit, even if nothing appears to have changed
        #[arg(long)]
        force_nocache: bool,
        /// Assume cache is present, do not attempt to update it
        #[arg(long)]
        cache_only: bool,
        /// Cached state
        #[arg(long)]
        cachedir: Option<String>,
        /// Rootfs to use for configuring libdnf
        #[arg(long)]
        source_root: Option<String>,
        /// Like --dry-run, but download and import RPMs as well; requires --cachedir
        #[arg(long)]
        download_only: bool,
        /// Like --dry-run, but download RPMs as well; requires --cachedir
        #[arg(long)]
        download_only_rpms: bool,
        /// HTTP proxy
        #[arg(long)]
        proxy: Option<String>,
        /// Just print the transaction and exit
        #[arg(long)]
        dry_run: bool,
        /// Just expand any includes and print treefile
        #[arg(long)]
        print_only: bool,
        /// Disable SELinux labeling, even if manifest enables it
        #[arg(long)]
        disable_selinux: bool,
        /// Update the modification time on FILE if a new commit was created
        #[arg(long)]
        touch_if_changed: Option<String>,
        /// Use this commit for change detection
        #[arg(long)]
        previous_commit: Option<String>,
        /// Use this input hash for change detection
        #[arg(long)]
        previous_inputhash: Option<String>,
        /// Use this version number for automatic version numbering
        #[arg(long)]
        previous_version: Option<String>,
        /// Working directory
        #[arg(long)]
        workdir: Option<String>,
        /// Also run default postprocessing
        #[arg(long)]
        postprocess: bool,
        /// Write lockfile to FILE
        #[arg(long)]
        ex_write_lockfile_to: Option<String>,
        /// Read lockfile from FILE
        #[arg(long)]
        ex_lockfile: Option<String>,
        /// With --ex-lockfile, only allow installing locked packages
        #[arg(long)]
        ex_lockfile_strict: bool,
    },
    /// Perform final postprocessing on an installation root
    Postprocess { 
        /// Path to rootfs
        rootfs: String,
        /// Path to treefile (optional)
        treefile: Option<String>,
    },
    /// Commit a target path to an OSTree repository
    Commit { 
        /// Path to treefile
        treefile: String,
        /// Path to rootfs
        rootfs: String,
        /// Path to OSTree repository
        #[arg(short, long)]
        repo: Option<String>,
        /// Path to OSTree repository for ostree-layers and ostree-override-layers
        #[arg(long)]
        layer_repo: Option<String>,
        /// Use new "unified core" codepath
        #[arg(long)]
        unified_core: bool,
        /// Append given key and value (in string format) to metadata
        #[arg(long)]
        add_metadata_string: Vec<String>,
        /// Parse the given JSON file as object, convert to GVariant, append to OSTree commit
        #[arg(long)]
        add_metadata_from_json: Option<String>,
        /// File to write the composed commitid to instead of updating the ref
        #[arg(long)]
        write_commitid_to: Option<String>,
        /// Write JSON to FILE containing information about the compose run
        #[arg(long)]
        write_composejson_to: Option<String>,
        /// Always commit without a parent
        #[arg(long)]
        no_parent: bool,
        /// Commit with specific parent
        #[arg(long)]
        parent: Option<String>,
    },
    /// Download packages guaranteed to depsolve with a base OSTree
    Extensions { 
        /// Path to treefile
        treefile: String,
        /// Path to extensions YAML file
        extyaml: String,
        /// Path to OSTree repository
        #[arg(short, long)]
        repo: Option<String>,
        /// Path to OSTree repository for ostree-layers and ostree-override-layers
        #[arg(long)]
        layer_repo: Option<String>,
        /// Use new "unified core" codepath
        #[arg(long)]
        unified_core: bool,
        /// Path to extensions output directory
        #[arg(long)]
        output_dir: Option<String>,
        /// Base OSTree revision
        #[arg(long)]
        base_rev: Option<String>,
        /// Cached state
        #[arg(long)]
        cachedir: Option<String>,
        /// Path to already present rootfs
        #[arg(long)]
        rootfs: Option<String>,
        /// Update the modification time on FILE if new extensions were downloaded
        #[arg(long)]
        touch_if_changed: Option<String>,
    },
    /// Generate a reproducible "chunked" container image (using RPM data) from a treefile
    Image { 
        /// Path to the manifest file
        manifest: String,
        /// Target path to write
        output: String,
        /// Directory to use for caching downloaded packages and other data
        #[arg(long)]
        cachedir: Option<String>,
        /// Rootfs to use for resolving package system configuration
        #[arg(long)]
        source_root: Option<String>,
        /// Container authentication file
        #[arg(long)]
        authfile: Option<String>,
        /// OSTree repository to use for ostree-layers and ostree-override-layers
        #[arg(long)]
        layer_repo: Option<String>,
        /// Do not query previous image in target location; use this for the first build
        #[arg(short, long)]
        initialize: bool,
        /// Control conditions under which the image is written
        #[arg(long, default_value = "query")]
        initialize_mode: Option<String>,
        /// Output format
        #[arg(long, default_value = "ociarchive")]
        format: Option<String>,
        /// Force a build
        #[arg(long)]
        force_nocache: bool,
        /// Operate only on cached data, do not access network repositories
        #[arg(long)]
        offline: bool,
        /// Path to write a JSON-formatted lockfile
        #[arg(long)]
        write_lockfile_to: Option<String>,
        /// JSON-formatted lockfile; can be specified multiple times
        #[arg(long)]
        lockfile: Vec<String>,
        /// With --lockfile, only allow installing locked packages
        #[arg(long)]
        lockfile_strict: bool,
        /// Additional labels for the container image, in KEY=VALUE format
        #[arg(short, long)]
        label: Vec<String>,
        /// Path to container image configuration in JSON format
        #[arg(long)]
        image_config: Option<String>,
        /// Update the timestamp or create this file on changes
        #[arg(long)]
        touch_if_changed: Option<String>,
        /// Number of times to retry copying an image to remote destination
        #[arg(long)]
        copy_retry_times: Option<u32>,
        /// Maximum number of layers to use
        #[arg(long)]
        max_layers: Option<u32>,
    },
    /// Generate a root filesystem tree from a treefile
    Rootfs { 
        /// Path to the input manifest
        manifest: String,
        /// Path to the target root filesystem tree
        dest: String,
        /// Directory to use for caching downloaded packages and other data
        #[arg(long)]
        cachedir: Option<String>,
        /// Source root for package system configuration
        #[arg(long)]
        source_root: Option<String>,
        /// Rootfs to use for resolving package system configuration
        #[arg(long)]
        source_root_rw: Option<String>,
    },
    /// Generate a "chunked" OCI archive from an input rootfs
    BuildChunkedOci {
        /// Path to the source root filesystem tree
        #[arg(long)]
        rootfs: Option<String>,
        /// Use the provided image (in containers-storage)
        #[arg(long)]
        from: Option<String>,
        /// If set, configure the output OCI image to be a bootc container
        #[arg(long)]
        bootc: bool,
        /// The format version
        #[arg(long, default_value = "1")]
        format_version: Option<String>,
        /// Maximum number of layers to use
        #[arg(long)]
        max_layers: Option<u32>,
        /// Tag to use for output image, or latest if unset
        #[arg(long, default_value = "latest")]
        reference: Option<String>,
        /// Output image reference, in TRANSPORT:TARGET syntax
        #[arg(long)]
        output: String,
    },
    /// Generate a reproducible "chunked" container image (using RPM data) from an OSTree commit
    ContainerEncapsulate {
        /// OSTree branch name or checksum
        ostree_ref: String,
        /// Image reference, e.g. registry:quay.io/exampleos/exampleos:latest
        imgref: String,
        /// Path to OSTree repository
        #[arg(long)]
        repo: Option<String>,
        /// Additional labels for the container
        #[arg(short, long)]
        label: Vec<String>,
        /// Path to container image configuration in JSON format
        #[arg(long)]
        image_config: Option<String>,
        /// Override the architecture
        #[arg(long)]
        arch: Option<String>,
        /// Propagate an OSTree commit metadata key to container label
        #[arg(long)]
        copymeta: Vec<String>,
        /// Propagate an optionally-present OSTree commit metadata key to container label
        #[arg(long)]
        copymeta_opt: Vec<String>,
        /// Corresponds to the Dockerfile CMD instruction
        #[arg(long)]
        cmd: Option<String>,
        /// Maximum number of container image layers
        #[arg(long)]
        max_layers: Option<u32>,
        /// The encapsulated container format version; must be 1 or 2
        #[arg(long, default_value = "1")]
        format_version: Option<String>,
        /// Output content metadata as JSON
        #[arg(long)]
        write_contentmeta_json: Option<String>,
        /// Compare OCI layers of current build with another(imgref)
        #[arg(long)]
        compare_with_build: Option<String>,
        /// Prevent a change in packing structure by taking a previous build metadata
        #[arg(long)]
        previous_build_manifest: Option<String>,
    },
}

#[derive(Args)]
pub struct DbArgs {
    #[command(subcommand)]
    pub subcommand: DbSubcommands,
}

#[derive(Subcommand)]
pub enum DbSubcommands {
    /// List packages
    List,
    /// Show package info
    Info { 
        /// Package name to get info for
        package: String 
    },
    /// Search packages
    Search { 
        /// Search query
        query: String 
    },
    /// Show package dependencies
    Depends { 
        /// Package name to get dependencies for
        package: String 
    },
    /// Install packages into a target path
    Install { 
        /// Packages to install
        packages: Vec<String>,
        /// Target path for installation
        #[arg(long, default_value = "/")]
        target: String,
        /// Repository to use
        #[arg(long)]
        repo: Option<String>,
    },
    /// Remove packages from a target path
    Remove { 
        /// Packages to remove
        packages: Vec<String>,
        /// Target path for removal
        #[arg(long, default_value = "/")]
        target: String,
        /// Repository to use
        #[arg(long)]
        repo: Option<String>,
    },
}

#[derive(Args)]
pub struct OverrideArgs {
    #[command(subcommand)]
    pub subcommand: OverrideSubcommands,
}

#[derive(Subcommand)]
pub enum OverrideSubcommands {
    /// Remove packages from the base layer
    Remove { 
        /// Packages to remove
        packages: Vec<String>,
        /// Replace a package
        #[arg(long)]
        replace: Option<String>,
        /// Operate on provided STATEROOT
        #[arg(long)]
        stateroot: Option<String>,
        /// Initiate a reboot after operation is complete
        #[arg(short, long)]
        reboot: bool,
        /// Exit after printing the transaction
        #[arg(short, long)]
        dry_run: bool,
        /// Prevent automatic deployment finalization on shutdown
        #[arg(long)]
        lock_finalization: bool,
        /// Only operate on cached data
        #[arg(short, long)]
        cache_only: bool,
        /// Use system root SYSROOT (default: /)
        #[arg(long)]
        sysroot: Option<String>,
        /// Force a peer-to-peer connection instead of using the system message bus
        #[arg(long)]
        peer: bool,
        /// Overlay additional package
        #[arg(long)]
        install: Option<String>,
        /// Remove overlayed additional package
        #[arg(long)]
        uninstall: Option<String>,
    },
    /// Replace packages in the base layer
    Replace { 
        /// Packages to replace
        packages: Vec<String>,
        /// Remove a package
        #[arg(long)]
        remove: Option<String>,
        /// Operate on provided STATEROOT
        #[arg(long)]
        stateroot: Option<String>,
        /// Initiate a reboot after operation is complete
        #[arg(short, long)]
        reboot: bool,
        /// Exit after printing the transaction
        #[arg(short, long)]
        dry_run: bool,
        /// Prevent automatic deployment finalization on shutdown
        #[arg(long)]
        lock_finalization: bool,
        /// Only operate on cached data
        #[arg(short, long)]
        cache_only: bool,
        /// Use system root SYSROOT (default: /)
        #[arg(long)]
        sysroot: Option<String>,
        /// Force a peer-to-peer connection instead of using the system message bus
        #[arg(long)]
        peer: bool,
        /// Overlay additional package
        #[arg(long)]
        install: Option<String>,
        /// Remove overlayed additional package
        #[arg(long)]
        uninstall: Option<String>,
    },
    /// Reset currently active package overrides
    Reset { 
        /// Reset all active overrides
        #[arg(short, long)]
        all: bool,
        /// Operate on provided STATEROOT
        #[arg(long)]
        stateroot: Option<String>,
        /// Initiate a reboot after operation is complete
        #[arg(short, long)]
        reboot: bool,
        /// Exit after printing the transaction
        #[arg(short, long)]
        dry_run: bool,
        /// Prevent automatic deployment finalization on shutdown
        #[arg(long)]
        lock_finalization: bool,
        /// Only operate on cached data
        #[arg(short, long)]
        cache_only: bool,
        /// Use system root SYSROOT (default: /)
        #[arg(long)]
        sysroot: Option<String>,
        /// Force a peer-to-peer connection instead of using the system message bus
        #[arg(long)]
        peer: bool,
        /// Overlay additional package
        #[arg(long)]
        install: Option<String>,
        /// Remove overlayed additional package
        #[arg(long)]
        uninstall: Option<String>,
    },
}

#[derive(Args)]
pub struct ResetArgs {
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Initiate a reboot after transaction is complete
    #[arg(short, long)]
    pub reboot: bool,
    
    /// Remove all overlayed packages
    #[arg(short, long)]
    pub overlays: bool,
    
    /// Remove all overrides
    #[arg(short, long)]
    pub overrides: bool,
    
    /// Stop regenerating initramfs or tracking files
    #[arg(short, long)]
    pub initramfs: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
    
    /// Overlay additional package
    #[arg(long)]
    pub install: Option<String>,
    
    /// Remove overlayed additional package
    #[arg(long)]
    pub uninstall: Option<String>,
}

#[derive(Args)]
pub struct RefreshMdArgs {
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Expire current cache
    #[arg(short, long)]
    pub force: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct ApplyLiveArgs {
    /// Target provided commit instead of pending deployment
    #[arg(long)]
    pub target: Option<String>,
    
    /// Reset back to booted commit
    #[arg(long)]
    pub reset: bool,
    
    /// Allow replacement of packages/files (default is pure additive)
    #[arg(long)]
    pub allow_replacement: bool,
}

#[derive(Args)]
pub struct UsroverlayArgs {
    /// Make the current deployment mutable (as a hotfix or development)
    #[arg(long)]
    pub hotfix: bool,
    
    /// Retain changes across reboots
    #[arg(long)]
    pub transient: bool,
    
    /// Show detailed output
    #[arg(long)]
    pub verbose: bool,
    
    /// Remove existing overlay
    #[arg(long)]
    pub remove: bool,
    
    /// Create overlay directories
    #[arg(long)]
    pub create: bool,
}

#[derive(Args)]
pub struct CleanupArgs {
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Clear temporary files; will leave deployments unchanged
    #[arg(short, long)]
    pub base: bool,
    
    /// Remove pending deployment
    #[arg(short, long)]
    pub pending: bool,
    
    /// Remove rollback deployment
    #[arg(short, long)]
    pub rollback: bool,
    
    /// Delete cached apt repo metadata
    #[arg(short, long)]
    pub repomd: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct FinalizeDeploymentArgs {
    /// Checksum to finalize
    pub checksum: String,
    
    /// Operate on provided STATEROOT
    #[arg(long)]
    pub stateroot: Option<String>,
    
    /// Don't error out if no expected checksum is provided
    #[arg(long)]
    pub allow_missing_checksum: bool,
    
    /// Don't error out if staged deployment wasn't locked
    #[arg(long)]
    pub allow_unlocked: bool,
    
    /// Use system root SYSROOT (default: /)
    #[arg(long)]
    pub sysroot: Option<String>,
    
    /// Force a peer-to-peer connection instead of using the system message bus
    #[arg(long)]
    pub peer: bool,
}

#[derive(Args)]
pub struct MetricsArgs {
    /// Show system metrics
    #[arg(long)]
    pub system: bool,
    
    /// Show performance metrics
    #[arg(long)]
    pub performance: bool,
    
    /// Show all metrics
    #[arg(long)]
    pub all: bool,
}

#[derive(Args)]
pub struct StartDaemonArgs {
    /// Debug mode
    #[arg(short, long)]
    pub debug: bool,
    
    /// System root path
    #[arg(long, default_value = "/")]
    pub sysroot: String,
}

#[derive(Args)]
pub struct ExArgs {
    #[command(subcommand)]
    pub subcommand: ExSubcommands,
}

#[derive(Subcommand)]
pub enum ExSubcommands {
    /// Unpack OSTree commit
    Unpack {
        commit: String,
        destination: String,
        #[arg(long)]
        force: bool,
    },
    /// Show history
    History {
        #[arg(long)]
        verbose: bool,
    },
    /// Manage initramfs /etc
    InitramfsEtc {
        #[arg(long)]
        add: Vec<String>,
        #[arg(long)]
        remove: Vec<String>,
    },
    /// Manage modules
    Module {
        #[arg(long)]
        enable: String,
        #[arg(long)]
        disable: String,
    },
    /// Rebuild system
    Rebuild {
        #[arg(long)]
        force: bool,
    },
    /// Deploy from self
    DeployFromSelf {
        #[arg(long)]
        force: bool,
    },
}

#[derive(Args)]
pub struct CountmeArgs {
    /// Force countme
    #[arg(short, long)]
    pub force: bool,
    
    /// Dry run
    #[arg(long)]
    pub dry_run: bool,
    
    /// Verbose output
    #[arg(short, long)]
    pub verbose: bool,
}

#[derive(Args)]
pub struct ContainerArgs {
    #[command(subcommand)]
    pub subcommand: ContainerSubcommands,
}

#[derive(Subcommand)]
pub enum ContainerSubcommands {
    /// Install container
    Install { image: String },
    /// Uninstall container
    Uninstall { name: String },
    /// List containers
    List,
    /// Show container info
    Info { name: String },
}

#[derive(Args)]
pub struct TestutilsArgs {
    #[command(subcommand)]
    pub subcommand: TestutilsSubcommands,
}

#[derive(Subcommand)]
pub enum TestutilsSubcommands {
    /// Inject package list metadata into OSTree commits
    InjectPkglist(InjectPkglistArgs),
    
    /// Run scripts in bubblewrap containers
    ScriptShell(ScriptShellArgs),
    
    /// Generate synthetic OS updates by modifying ELF files
    GenerateSyntheticUpgrade(GenerateSyntheticUpgradeArgs),
    
    /// Run integration tests on booted machine
    IntegrationReadOnly,
    
    /// Run C unit tests
    CUnits,
    
    /// Test command for development verification
    Moo,
}

#[derive(Args)]
pub struct InjectPkglistArgs {
    /// Repository path
    pub repo: String,
    
    /// OSTree reference
    pub refspec: String,
}

#[derive(Args)]
pub struct ScriptShellArgs {
    /// Script or command to execute
    pub script: String,
    
    /// Arguments for the script
    pub args: Vec<String>,
    
    /// Root path for script execution
    #[arg(long, default_value = "/")]
    pub rootpath: String,
    
    /// Run in read-only mode
    #[arg(long)]
    pub read_only: bool,
    
    /// User to run as
    #[arg(long)]
    pub user: Option<String>,
    
    /// Group to run as
    #[arg(long)]
    pub group: Option<String>,
    
    /// Working directory
    #[arg(long)]
    pub cwd: Option<String>,
    
    /// Environment variables (format: KEY=VALUE)
    #[arg(long)]
    pub env: Vec<String>,
}

#[derive(Args)]
pub struct GenerateSyntheticUpgradeArgs {
    /// Repository path
    #[arg(long)]
    pub repo: String,
    
    /// Source reference
    #[arg(long = "srcref")]
    pub src_ref: Option<String>,
    
    /// OSTree reference
    #[arg(long = "ref")]
    pub ostref: String,
    
    /// Percentage of binaries to modify
    #[arg(long, default_value = "30")]
    pub percentage: u32,
    
    /// Commit version
    #[arg(long)]
    pub commit_version: Option<String>,
}

#[derive(Args)]
pub struct ShlibBackendArgs {
    #[command(subcommand)]
    pub subcommand: ShlibBackendSubcommands,
}

#[derive(Subcommand)]
pub enum ShlibBackendSubcommands {
    /// Get base architecture
    GetBasearch,
    
    /// Variable substitution for architecture
    VarsubstBasearch {
        /// Source string for substitution
        source: String,
    },
    
    /// Extract package list from OSTree commit
    PackagelistFromCommit {
        /// Commit hash
        commit: String,
    },
}

#[derive(Args)]
pub struct InternalsArgs {
    #[command(subcommand)]
    pub subcommand: InternalsSubcommands,
}

#[derive(Subcommand)]
pub enum InternalsSubcommands {
    /// Internal system diagnostics
    Diagnostics,
    
    /// System state validation
    ValidateState,
    
    /// Debug information dump
    DebugDump,
    
    /// Real-time system health monitoring
    SystemHealth,
    
    /// System performance analysis
    Performance,
    
    /// Security status and vulnerability checks
    Security,
}
