devpulse 1.0.0

Developer diagnostics: HTTP timing, build artifact cleanup, environment health checks, port scanning, PATH analysis, and config format conversion
//! CLI argument definitions using clap derive macros.
//!
//! Defines the root Cli struct, all 5 subcommands, global flags (--json, --color),
//! and a hidden completions subcommand for shell completion generation.

use std::path::PathBuf;

use clap::{Parser, Subcommand, ValueEnum};
use clap_complete::Shell;

/// Color output mode for terminal rendering.
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum ColorChoice {
    /// Detect automatically based on terminal and NO_COLOR env var
    Auto,
    /// Always emit color codes
    Always,
    /// Never emit color codes
    Never,
}

/// devpulse — Take the pulse of your dev environment.
///
/// A Swiss army knife for developer diagnostics: HTTP timing,
/// build artifact cleanup, environment health checks, port
/// scanning, and PATH analysis. All in one fast Rust binary.
#[derive(Parser, Debug)]
#[command(
    name = "devpulse",
    version,
    about = "Take the pulse of your dev environment"
)]
#[command(propagate_version = true, arg_required_else_help = false)]
#[command(long_about = "devpulse — Developer diagnostics CLI\n\n\
    A single binary with 6 subcommands:\n  \
    http     HTTP request timing visualizer\n  \
    sweep    Build artifact scanner & cleaner\n  \
    doctor   Dev environment health checker\n  \
    ports    Listening port inspector\n  \
    env      Environment variable analyzer\n  \
    convert  Config format converter\n\n\
    All commands support --json for CI/scripting.\n\
    Respects NO_COLOR environment variable.")]
pub struct Cli {
    /// Subcommand to execute (optional — TUI launches if omitted)
    #[command(subcommand)]
    pub command: Option<Commands>,

    /// Output as JSON for scripting and CI pipelines
    #[arg(
        long,
        global = true,
        help = "Output as JSON for scripting and CI pipelines"
    )]
    pub json: bool,

    /// Color output mode: auto, always, never
    #[arg(
        long,
        global = true,
        default_value = "auto",
        help = "Color output: auto, always, never"
    )]
    pub color: ColorChoice,
}

/// Available subcommands for devpulse.
#[derive(Subcommand, Debug)]
pub enum Commands {
    /// HTTP request timing visualizer with colored phase breakdown
    #[command(
        long_about = "HTTP request timing visualizer with colored phase breakdown.\n\n\
        Shows DNS lookup, TCP connection, TLS handshake, server processing,\n\
        and content transfer times with colored bars and cumulative labels.\n\n\
        Examples:\n  \
        devpulse http https://httpbin.org/get\n  \
        devpulse http -X POST -d '{\"key\":\"val\"}' https://api.example.com\n  \
        devpulse http -H 'Authorization: Bearer tok' https://api.example.com"
    )]
    Http {
        /// URL to request (http:// or https://)
        #[arg(help = "URL to request (http:// or https://)")]
        url: String,

        /// HTTP method
        #[arg(
            short = 'X',
            long,
            default_value = "GET",
            help = "HTTP method (GET, POST, PUT, DELETE, etc.)"
        )]
        method: String,

        /// Headers in 'Key: Value' format (repeatable)
        #[arg(
            short = 'H',
            long = "header",
            help = "Header in 'Key: Value' format (repeatable)"
        )]
        headers: Vec<String>,

        /// Request body data
        #[arg(short = 'd', long = "data", help = "Request body data")]
        data: Option<String>,
    },

    /// Scan and clean build artifacts (node_modules, target, __pycache__, etc.)
    #[command(
        long_about = "Scan and clean build artifacts across all languages.\n\n\
        Finds node_modules/, target/, __pycache__/, .venv/, .next/, .gradle/,\n\
        and more. Shows sizes with color coding, supports selective deletion.\n\n\
        Examples:\n  \
        devpulse sweep\n  \
        devpulse sweep ~/projects\n  \
        devpulse sweep -y --min-size 100M ~/projects"
    )]
    Sweep {
        /// Root directory to scan (defaults to current directory)
        #[arg(help = "Root directory to scan (defaults to current directory)")]
        path: Option<PathBuf>,

        /// Delete all found artifacts without confirmation
        #[arg(short = 'y', long, help = "Delete all without confirmation")]
        yes: bool,

        /// Minimum size filter (e.g., 1M, 500K, 2G)
        #[arg(long, default_value = "1M", help = "Minimum size filter: 1M, 500K, 2G")]
        min_size: String,
    },

    /// Check developer tool health (git, node, rust, python, docker)
    #[command(long_about = "Check developer environment health.\n\n\
        Runs checks for Git, Node.js, Rust, Python, Docker, disk space,\n\
        and SSH keys. Shows pass/warn/fail status for each.\n\n\
        Examples:\n  \
        devpulse doctor\n  \
        devpulse doctor --json")]
    Doctor,

    /// Show listening ports and their processes
    #[command(long_about = "Show listening ports and their processes.\n\n\
        Lists all TCP ports currently in LISTEN state with the process\n\
        name and PID. Optionally filter to a specific port number.\n\n\
        Examples:\n  \
        devpulse ports\n  \
        devpulse ports 3000\n  \
        devpulse ports --json")]
    Ports {
        /// Filter to a specific port number
        #[arg(help = "Filter to specific port number")]
        port: Option<u16>,

        /// Scan a custom port range (e.g., "1-1024" or "8000-9000")
        #[arg(
            long = "scan-range",
            help = "Scan custom port range: START-END (e.g., 1-1024)"
        )]
        scan_range: Option<String>,
    },

    /// Inspect developer environment variables and PATH
    #[command(long_about = "Inspect developer environment variables and PATH.\n\n\
        Analyzes PATH entries (missing dirs, duplicates, tool locations),\n\
        shows dev tool variables, proxy settings, and CI detection.\n\n\
        Examples:\n  \
        devpulse env\n  \
        devpulse env path\n  \
        devpulse env proxy\n  \
        devpulse env --json")]
    Env {
        /// Filter section: 'path', 'proxy', 'ci', or a regex pattern
        #[arg(help = "Filter: 'path', 'proxy', 'ci', or regex pattern")]
        filter: Option<String>,
    },

    /// Convert config files between JSON, YAML, TOML, and .env formats
    #[command(
        long_about = "Convert config files between JSON, YAML, TOML, and .env formats.\n\n\
        Reads a config file, detects the input format (by extension or --from flag),\n\
        and converts it to the target format.  Dot-flattening is used for .env output.\n\n\
        Examples:\n  \
        devpulse convert config.json --to yaml\n  \
        devpulse convert settings.yaml --to toml\n  \
        devpulse convert .env --to json\n  \
        devpulse convert data.toml --to env -o .env.local"
    )]
    Convert {
        /// Input config file path
        #[arg(help = "Input config file (json, yaml, toml, or .env)")]
        input: String,

        /// Target output format
        #[arg(long, help = "Target format: json, yaml, toml, env")]
        to: String,

        /// Override input format detection
        #[arg(long, help = "Source format (auto-detected from extension if omitted)")]
        from: Option<String>,

        /// Write output to a file instead of stdout
        #[arg(short = 'o', long = "output", help = "Write output to file instead of stdout")]
        output: Option<String>,
    },

    /// Generate shell completions (hidden from help)
    #[command(hide = true)]
    Completions {
        /// Shell to generate completions for
        #[arg(help = "Shell: bash, zsh, fish, powershell, elvish")]
        shell: Shell,
    },
}

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

    /// Verify CLI structure is valid (catches clap misconfigurations at test time).
    #[test]
    fn verify_cli() {
        super::Cli::command().debug_assert();
    }
}