nolo 0.1.0

A CLI tool for discovering and analyzing `TODO` comments across codebases.
Documentation
use clap::{Parser, Subcommand};
use std::path::PathBuf;

#[derive(Parser)]
#[command(name = "nolo")]
#[command(about = "A TODO comment management suite")]
#[command(version)]
pub struct CliArgs {
    #[command(subcommand)]
    pub command: Option<Commands>,
    /// Path to configuration file
    #[arg(long, global = true)]
    pub config: Option<PathBuf>,
}

#[derive(Subcommand)]
pub enum Commands {
    /// Scan for TODO comments (default)
    #[command(alias = "s")]
    Scan {
        /// Path to scan for TODO comments
        #[arg(value_name = "PATH")]
        path: Option<PathBuf>,
    },
    /// Generate analytics report for TODO comments
    #[command(alias = "r")]
    Report {
        /// Path to analyze for TODO comments
        #[arg(value_name = "PATH")]
        path: Option<PathBuf>,
        /// Output format for the report
        #[arg(long, value_enum, default_value = "table")]
        format: ReportFormat,
        /// Number of top files to display in report (default: 5)
        #[arg(long, default_value = "5")]
        display_limit: usize,
        /// Show all files with TODOs instead of limiting display
        #[arg(long, conflicts_with = "display_limit")]
        full_report: bool,
    },
}

#[derive(clap::ValueEnum, Clone)]
pub enum ReportFormat {
    Table,
    Json,
}

impl CliArgs {
    pub fn get_command_and_path(&self, config: &crate::config::Config) -> (CommandType, PathBuf) {
        let (command_type, path_option) = match &self.command {
            Some(Commands::Scan { path }) => (CommandType::Scan, path.as_ref()),
            Some(Commands::Report { path, .. }) => (CommandType::Report, path.as_ref()),
            None => (CommandType::Report, None),
        };

        let path = match path_option {
            Some(path) => path.clone(),
            None => {
                // Try config default first, then git root, then current dir
                let config_path = config.get_default_path();
                if config_path != "." {
                    PathBuf::from(config_path)
                } else if let Some(git_root) = crate::discover::git_root() {
                    PathBuf::from(git_root)
                } else {
                    PathBuf::from(".")
                }
            }
        };

        (command_type, path)
    }

    pub fn get_report_format(&self, config: &crate::config::Config) -> ReportFormat {
        match &self.command {
            Some(Commands::Report { format, .. }) => format.clone(),
            _ => {
                // Use config default
                match config.get_report_format().as_str() {
                    "json" => ReportFormat::Json,
                    _ => ReportFormat::Table,
                }
            }
        }
    }

    pub fn get_display_limit(&self, config: &crate::config::Config) -> Option<usize> {
        match &self.command {
            Some(Commands::Report {
                display_limit,
                full_report,
                ..
            }) => {
                if *full_report {
                    None
                } else {
                    Some(*display_limit)
                }
            }
            _ => {
                // Use config default for display limit
                Some(config.get_report_limit())
            }
        }
    }
}

pub enum CommandType {
    Scan,
    Report,
}