//! Command-line interface for the `timefs` binary.

use clap::{ArgAction, Parser, Subcommand, ValueEnum};
use std::path::PathBuf;

/// Top-level CLI arguments for `timefs`.
#[derive(Debug, Parser)]
#[command(
    author,
    version,
    about = "Mount Git history as a read-only filesystem",
    after_help = "Examples:\n  timefs mount ~/code/git /mnt/git -f\n  timefs mount ~/code/linux /mnt/linux --ref-snapshot --cache-size 512\n  timefs unmount /mnt/git",
    propagate_version = true
)]
pub struct Cli {
    /// Increase logging verbosity (`-v` for info, `-vv` for debug).
    #[arg(short, long, global = true, action = ArgAction::Count)]
    pub verbose: u8,

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

/// Supported `timefs` subcommands.
#[derive(Debug, Subcommand)]
pub enum Command {
    /// Mount a Git repository at a filesystem mountpoint.
    Mount(MountArgs),
    /// Unmount a previously mounted `timefs` filesystem.
    Unmount(UnmountArgs),
}

/// Arguments for the `mount` subcommand.
#[derive(Debug, Clone, Parser)]
#[command(
    after_help = "Examples:\n  timefs mount ~/code/git /mnt/git -f\n  timefs mount ~/code/linux /mnt/linux --allow-other --cache-size 512\n  timefs mount ~/code/repo /mnt/repo --ref-snapshot --submodules recurse"
)]
pub struct MountArgs {
    /// Path to the Git repository to mount.
    pub repo: PathBuf,

    /// Existing directory where the filesystem should be mounted.
    pub mountpoint: PathBuf,

    /// Keep the filesystem in the foreground.
    #[arg(short = 'f', long)]
    pub foreground: bool,

    /// Allow access from users other than the mounter.
    #[arg(long)]
    pub allow_other: bool,

    /// Strategy for exposing submodules.
    #[arg(long, value_enum, default_value_t = SubmodulesMode::Placeholder)]
    pub submodules: SubmodulesMode,

    /// Resolve local Git LFS objects when present.
    #[arg(long)]
    pub lfs: bool,

    /// Freeze ref resolution at mount time.
    #[arg(long)]
    pub ref_snapshot: bool,

    /// Cap the in-memory cache size in mebibytes.
    #[arg(long = "cache-size", default_value_t = 256)]
    pub cache_size_mb: usize,

    /// Override the UID reported for every filesystem node.
    #[arg(long)]
    pub uid: Option<u32>,

    /// Override the GID reported for every filesystem node.
    #[arg(long)]
    pub gid: Option<u32>,
}

/// Arguments for the `unmount` subcommand.
#[derive(Debug, Clone, Parser)]
#[command(after_help = "Example:\n  timefs unmount /mnt/git")]
pub struct UnmountArgs {
    /// Existing mountpoint to unmount.
    pub mountpoint: PathBuf,
}

/// Supported submodule handling modes.
#[derive(Copy, Clone, Debug, Eq, PartialEq, ValueEnum)]
pub enum SubmodulesMode {
    /// Expose a placeholder directory with the pinned gitlink SHA.
    Placeholder,
    /// Recurse into submodules when supported.
    Recurse,
}
