//! CLI argument definitions for cg-coin

use crate::error::{CgCoinError, Result};
use cg_common::resolve_symbol;
use clap::{Parser, ValueEnum};
use std::path::PathBuf;

#[derive(Parser, Debug)]
#[command(name = "cg-coin")]
#[command(author, version, about = "Fetch cryptocurrency data from CoinGecko", long_about = None)]
pub struct Args {
    /// Coin ID (e.g., "bitcoin", "ethereum") or symbol (e.g., "BTC", "ETH")
    #[arg(value_name = "COIN")]
    pub coin: Option<String>,

    /// Symbol to resolve (e.g., "BTC", "ETH") - alternative to positional arg
    #[arg(short, long)]
    pub symbol: Option<String>,

    /// Include exchange tickers in output
    #[arg(long, default_value = "false")]
    pub tickers: bool,

    /// Include community (social) data
    #[arg(long, default_value = "true", action = clap::ArgAction::Set)]
    pub community: bool,

    /// Include developer (GitHub) data
    #[arg(long, default_value = "true", action = clap::ArgAction::Set)]
    pub developer: bool,

    /// Output format
    #[arg(short, long, value_enum, default_value = "json")]
    pub format: OutputFormat,

    /// Output file path (outputs to stdout if not specified)
    #[arg(short = 'O', long = "output-file")]
    pub output: Option<PathBuf>,

    /// List all supported symbols
    #[arg(long)]
    pub list: bool,

    /// Enable verbose logging
    #[arg(short, long)]
    pub verbose: bool,
}

#[derive(Debug, Clone, Copy, ValueEnum, PartialEq)]
pub enum OutputFormat {
    /// JSON output format
    #[value(name = "json")]
    Json,
    /// Compact JSON (no pretty print)
    #[value(name = "compact")]
    Compact,
}

impl Args {
    /// Resolve the coin identifier from args
    pub fn resolve_coin_id(&self) -> Result<String> {
        // Priority: --symbol flag > positional argument
        let input = self.symbol.as_ref().or(self.coin.as_ref()).ok_or_else(|| {
            CgCoinError::InvalidInput(
                "No coin specified. Use a positional argument or --symbol flag.".to_string(),
            )
        })?;

        Ok(resolve_symbol(input))
    }

    /// Validate CLI arguments
    pub fn validate(&self) -> Result<()> {
        // If --list is specified, no validation needed
        if self.list {
            return Ok(());
        }

        // Need either coin or symbol
        if self.coin.is_none() && self.symbol.is_none() {
            return Err(CgCoinError::InvalidInput(
                "No coin specified. Use a positional argument, --symbol, or --list.".to_string(),
            ));
        }

        Ok(())
    }
}
