//! CLI argument parsing and command definitions.
//!
//! This module defines the complete command hierarchy for the GDELT CLI,
//! optimized for both human and AI agent usage.

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

/// GDELT CLI - Query and analyze global event data
///
/// A comprehensive CLI for the GDELT Project, optimized for agentic usage.
/// Supports local data caching with DuckDB, real-time API access, and
/// built-in analytics.
#[derive(Parser, Debug)]
#[command(name = "gdelt")]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
pub struct Cli {
    #[command(subcommand)]
    pub command: Command,

    #[command(flatten)]
    pub global: GlobalArgs,
}

/// Global arguments available on all commands
#[derive(Args, Debug, Clone)]
pub struct GlobalArgs {
    /// Output format
    #[arg(short, long, global = true, value_enum, default_value = "auto")]
    pub output: OutputFormat,

    /// Shorthand for --output json
    #[arg(long, global = true, conflicts_with = "output")]
    pub json: bool,

    /// Shorthand for --output jsonl (streaming)
    #[arg(long, global = true, conflicts_with = "output")]
    pub jsonl: bool,

    /// Shorthand for --output csv
    #[arg(long, global = true, conflicts_with = "output")]
    pub csv: bool,

    /// Shorthand for --output table
    #[arg(long, global = true, conflicts_with = "output")]
    pub table: bool,

    /// Shorthand for --output markdown
    #[arg(long, global = true, conflicts_with = "output")]
    pub markdown: bool,

    /// Pretty-print output (default for TTY)
    #[arg(long, global = true)]
    pub pretty: bool,

    /// Compact output (no whitespace)
    #[arg(long, global = true, conflicts_with = "pretty")]
    pub compact: bool,

    /// Suppress non-essential output
    #[arg(short, long, global = true)]
    pub quiet: bool,

    /// Increase verbosity (-v, -vv, -vvv)
    #[arg(short, long, global = true, action = clap::ArgAction::Count)]
    pub verbose: u8,

    /// Show what would be done without executing
    #[arg(long, global = true)]
    pub dry_run: bool,

    /// Auto-confirm all prompts
    #[arg(short, long, global = true)]
    pub yes: bool,

    /// Bypass cache for this request
    #[arg(long, global = true)]
    pub no_cache: bool,

    /// Only return cached results (fail if miss)
    #[arg(long, global = true, conflicts_with = "no_cache")]
    pub cache_only: bool,

    /// Request timeout in seconds
    #[arg(long, global = true, default_value = "30")]
    pub timeout: u64,

    /// Number of retry attempts
    #[arg(long, global = true, default_value = "3")]
    pub retries: u32,

    /// Wait and retry when rate limited (shows countdown)
    #[arg(long, global = true)]
    pub wait_on_rate_limit: bool,

    /// Maximum wait time when rate limited (seconds)
    #[arg(long, global = true, default_value = "120")]
    pub max_rate_limit_wait: u64,

    /// Path to configuration file
    #[arg(short, long, global = true, env = "GDELT_CONFIG")]
    pub config: Option<PathBuf>,

    /// Configuration profile to use
    #[arg(long, global = true)]
    pub profile: Option<String>,

    /// Enable debug output
    #[arg(long, global = true)]
    pub debug: bool,

    /// Enable trace-level logging
    #[arg(long, global = true, conflicts_with = "debug")]
    pub trace: bool,

    /// Show timing information
    #[arg(long, global = true)]
    pub timing: bool,

    /// Print help as JSON (for agents)
    #[arg(long, global = true)]
    pub help_json: bool,
}

impl GlobalArgs {
    /// Get the effective output format
    pub fn effective_output_format(&self) -> OutputFormat {
        if self.json {
            OutputFormat::Json
        } else if self.jsonl {
            OutputFormat::Jsonl
        } else if self.csv {
            OutputFormat::Csv
        } else if self.table {
            OutputFormat::Table
        } else if self.markdown {
            OutputFormat::Markdown
        } else {
            self.output
        }
    }

    /// Check if output should be pretty-printed
    pub fn should_pretty_print(&self) -> bool {
        if self.compact {
            return false;
        }
        if self.pretty {
            return true;
        }
        // Default to pretty for TTY
        atty::is(atty::Stream::Stdout)
    }
}

/// Output format options
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, ValueEnum)]
pub enum OutputFormat {
    /// Auto-detect based on TTY (table for TTY, json otherwise)
    #[default]
    Auto,
    /// JSON output
    Json,
    /// JSON Lines (streaming)
    Jsonl,
    /// CSV output
    Csv,
    /// Table output (human-readable)
    Table,
    /// Markdown output
    Markdown,
}

/// Top-level commands
#[derive(Subcommand, Debug)]
pub enum Command {
    /// Search and query DOC 2.0 API (news articles)
    #[command(subcommand)]
    Doc(DocCommand),

    /// Search and query GEO 2.0 API (geographic data)
    #[command(subcommand)]
    Geo(GeoCommand),

    /// Search and query TV 2.0 API (television news)
    #[command(subcommand)]
    Tv(TvCommand),

    /// Search and query TV AI API (AI-enhanced TV analysis)
    #[command(subcommand)]
    Tvai(TvAiCommand),

    /// Manage local data downloads
    #[command(subcommand)]
    Data(DataCommand),

    /// Query local events database
    #[command(subcommand)]
    Events(EventsCommand),

    /// Query local GKG (Global Knowledge Graph)
    #[command(subcommand)]
    Gkg(GkgCommand),

    /// Database management
    #[command(subcommand)]
    Db(DbCommand),

    /// Run MCP server (foreground)
    Serve(ServeArgs),

    /// Manage background daemon
    #[command(subcommand)]
    Daemon(DaemonCommand),

    /// Manage Claude Code skill installation
    #[command(subcommand)]
    Skill(SkillCommand),

    /// Analytics and reporting
    #[command(subcommand)]
    Analytics(AnalyticsCommand),

    /// Configuration management
    #[command(subcommand)]
    Config(ConfigCommand),

    /// Schema introspection (for agents)
    #[command(subcommand)]
    Schema(SchemaCommand),

    /// Enrich articles with GKG metadata and optionally fetch full text
    Enrich(EnrichArgs),

    /// Generate shell completions
    Completions(CompletionsArgs),
}

// ============================================================================
// DOC 2.0 API Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum DocCommand {
    /// Search for articles
    Search(DocSearchArgs),
    /// Get timeline data (volume/tone over time)
    Timeline(DocTimelineArgs),
    /// Generate word cloud data
    Wordcloud(DocWordcloudArgs),
    /// List available GKG themes
    Themes(DocThemesArgs),
}

#[derive(Args, Debug)]
pub struct DocSearchArgs {
    /// Search query (supports GDELT query syntax)
    pub query: String,

    /// Time span to search (e.g., "24h", "7d", "3m")
    #[arg(short, long, default_value = "24h")]
    pub timespan: String,

    /// Start datetime (YYYYMMDDHHMMSS), overrides timespan
    #[arg(long)]
    pub start: Option<String>,

    /// End datetime (YYYYMMDDHHMMSS)
    #[arg(long)]
    pub end: Option<String>,

    /// Maximum records to return
    #[arg(short = 'n', long, default_value = "75")]
    pub max_records: u32,

    /// Sort order
    #[arg(short, long, value_enum, default_value = "hybrid-rel")]
    pub sort: SortOrder,

    /// Filter by source language (ISO 639-1)
    #[arg(short, long)]
    pub lang: Option<String>,

    /// Filter by source country (FIPS code)
    #[arg(long)]
    pub country: Option<String>,

    /// Filter by domain
    #[arg(short, long)]
    pub domain: Option<String>,

    /// Filter by GKG theme
    #[arg(long)]
    pub theme: Option<String>,

    /// Minimum tone score (-10 to 10)
    #[arg(long)]
    pub tone_min: Option<f64>,

    /// Maximum tone score (-10 to 10)
    #[arg(long)]
    pub tone_max: Option<f64>,

    /// Enrich results with GKG metadata (themes, persons, orgs, tone)
    #[arg(long)]
    pub enrich: bool,

    /// Fetch full article text (slow, use sparingly)
    #[arg(long)]
    pub fetch_text: bool,

    /// Concurrent fetch limit for article text
    #[arg(long, default_value = "5")]
    pub fetch_concurrency: usize,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum SortOrder {
    /// Most recent first
    DateDesc,
    /// Oldest first
    DateAsc,
    /// Most negative tone first
    ToneDesc,
    /// Most positive tone first
    ToneAsc,
    /// Hybrid relevance
    HybridRel,
}

#[derive(Args, Debug)]
pub struct DocTimelineArgs {
    /// Search query
    pub query: String,

    /// Timeline type
    #[arg(short, long, value_enum, default_value = "vol")]
    pub mode: TimelineMode,

    /// Time span to analyze
    #[arg(short, long, default_value = "30d")]
    pub timespan: String,

    /// Smoothing window (1-30)
    #[arg(long)]
    pub smooth: Option<u8>,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum TimelineMode {
    /// Volume percentage
    Vol,
    /// Raw article counts
    VolRaw,
    /// Average tone
    Tone,
    /// Language breakdown
    Lang,
    /// Source country breakdown
    SourceCountry,
}

#[derive(Args, Debug)]
pub struct DocWordcloudArgs {
    /// Search query
    pub query: String,

    /// Time span
    #[arg(short, long, default_value = "24h")]
    pub timespan: String,
}

#[derive(Args, Debug)]
pub struct DocThemesArgs {
    /// Filter themes by pattern
    #[arg(short, long)]
    pub filter: Option<String>,
}

// ============================================================================
// GEO 2.0 API Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum GeoCommand {
    /// Search with geographic context
    Search(GeoSearchArgs),
    /// Get point data for locations
    Points(GeoPointsArgs),
    /// Generate heatmap data
    Heatmap(GeoHeatmapArgs),
    /// Country/region aggregation
    Aggregate(GeoAggregateArgs),
}

#[derive(Args, Debug)]
pub struct GeoSearchArgs {
    /// Search query
    pub query: String,

    /// Time span (max 7 days)
    #[arg(short, long, default_value = "24h")]
    pub timespan: String,

    /// Filter by location name
    #[arg(long)]
    pub location: Option<String>,

    /// Filter by country code
    #[arg(long)]
    pub country: Option<String>,

    /// Maximum points to return
    #[arg(short = 'n', long, default_value = "250")]
    pub max_points: u32,
}

#[derive(Args, Debug)]
pub struct GeoPointsArgs {
    /// Search query
    pub query: String,

    /// Time span
    #[arg(short, long, default_value = "24h")]
    pub timespan: String,

    /// Geographic resolution (0=all, 1=no countries, 2=cities only)
    #[arg(long, default_value = "0")]
    pub resolution: u8,
}

#[derive(Args, Debug)]
pub struct GeoHeatmapArgs {
    /// Search query
    pub query: String,

    /// Time span
    #[arg(short, long, default_value = "7d")]
    pub timespan: String,
}

#[derive(Args, Debug)]
pub struct GeoAggregateArgs {
    /// Search query
    pub query: String,

    /// Aggregation level
    #[arg(short, long, value_enum, default_value = "country")]
    pub level: AggregationLevel,

    /// Time span
    #[arg(short, long, default_value = "7d")]
    pub timespan: String,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum AggregationLevel {
    Country,
    Adm1,
}

// ============================================================================
// TV 2.0 API Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum TvCommand {
    /// Search TV captions
    Search(TvSearchArgs),
    /// Get video clips
    Clips(TvClipsArgs),
    /// TV coverage timeline
    Timeline(TvTimelineArgs),
    /// List stations
    Stations(TvStationsArgs),
}

#[derive(Args, Debug)]
pub struct TvSearchArgs {
    /// Search query
    pub query: String,

    /// Time span
    #[arg(short, long, default_value = "7d")]
    pub timespan: String,

    /// Filter by station
    #[arg(long)]
    pub station: Option<String>,

    /// Maximum results
    #[arg(short = 'n', long, default_value = "250")]
    pub max_records: u32,
}

#[derive(Args, Debug)]
pub struct TvClipsArgs {
    /// Search query
    pub query: String,

    /// Time span
    #[arg(short, long, default_value = "24h")]
    pub timespan: String,
}

#[derive(Args, Debug)]
pub struct TvTimelineArgs {
    /// Search query
    pub query: String,

    /// Time span
    #[arg(short, long, default_value = "30d")]
    pub timespan: String,

    /// Break down by station
    #[arg(long)]
    pub by_station: bool,
}

#[derive(Args, Debug)]
pub struct TvStationsArgs {
    /// Filter by country
    #[arg(short, long)]
    pub country: Option<String>,
}

// ============================================================================
// TV AI API Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum TvAiCommand {
    /// Search AI-analyzed content
    Search(TvAiSearchArgs),
    /// Search by visual concepts
    Concepts(TvAiConceptsArgs),
    /// Search by visual entities
    Visual(TvAiVisualArgs),
}

#[derive(Args, Debug)]
pub struct TvAiSearchArgs {
    /// Search query
    pub query: String,

    /// Time span
    #[arg(short, long, default_value = "7d")]
    pub timespan: String,

    /// Search in captions
    #[arg(long, default_value = "true")]
    pub captions: bool,

    /// Search in OCR text
    #[arg(long)]
    pub ocr: bool,

    /// Search in ASR transcripts
    #[arg(long)]
    pub asr: bool,
}

#[derive(Args, Debug)]
pub struct TvAiConceptsArgs {
    /// Concept to search
    pub concept: String,

    /// Time span
    #[arg(short, long, default_value = "7d")]
    pub timespan: String,
}

#[derive(Args, Debug)]
pub struct TvAiVisualArgs {
    /// Visual entity to search
    pub entity: String,

    /// Time span
    #[arg(short, long, default_value = "7d")]
    pub timespan: String,
}

// ============================================================================
// Data Management Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum DataCommand {
    /// Download historical data
    #[command(subcommand)]
    Download(DownloadCommand),
    /// Sync to latest data
    Sync(DataSyncArgs),
    /// Show download status
    Status(DataStatusArgs),
    /// List available date ranges
    List(DataListArgs),
    /// Delete local data
    Delete(DataDeleteArgs),
}

#[derive(Subcommand, Debug)]
pub enum DownloadCommand {
    /// Download events data
    Events(DownloadEventsArgs),
    /// Download GKG data
    Gkg(DownloadGkgArgs),
    /// Download mentions data
    Mentions(DownloadMentionsArgs),
}

#[derive(Args, Debug)]
pub struct DownloadEventsArgs {
    /// Start date (YYYY-MM-DD)
    #[arg(long)]
    pub start: Option<String>,

    /// End date (YYYY-MM-DD)
    #[arg(long)]
    pub end: Option<String>,

    /// Download all available data
    #[arg(long)]
    pub all: bool,

    /// Number of parallel downloads
    #[arg(long, default_value = "4")]
    pub parallel: u8,
}

#[derive(Args, Debug)]
pub struct DownloadGkgArgs {
    /// Start date (YYYY-MM-DD)
    #[arg(long)]
    pub start: Option<String>,

    /// End date (YYYY-MM-DD)
    #[arg(long)]
    pub end: Option<String>,

    /// GKG version (1 or 2)
    #[arg(long, default_value = "2")]
    pub version: u8,

    /// Number of parallel downloads
    #[arg(long, default_value = "4")]
    pub parallel: u8,
}

#[derive(Args, Debug)]
pub struct DownloadMentionsArgs {
    /// Start date (YYYY-MM-DD)
    #[arg(long)]
    pub start: Option<String>,

    /// End date (YYYY-MM-DD)
    #[arg(long)]
    pub end: Option<String>,

    /// Number of parallel downloads
    #[arg(long, default_value = "4")]
    pub parallel: u8,
}

#[derive(Args, Debug)]
pub struct DataSyncArgs {
    /// Data type to sync
    #[arg(short, long, value_enum)]
    pub data_type: Option<DataType>,

    /// Quick sync: only fetch last 24 hours of data (fast)
    #[arg(long)]
    pub quick: bool,

    /// Number of days to sync (default: sync all available)
    #[arg(long)]
    pub days: Option<u32>,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum DataType {
    Events,
    Gkg,
    Mentions,
    All,
}

#[derive(Args, Debug)]
pub struct DataStatusArgs {
    /// Show detailed status
    #[arg(long)]
    pub detailed: bool,
}

#[derive(Args, Debug)]
pub struct DataListArgs {
    /// Data type to list
    #[arg(short, long, value_enum)]
    pub data_type: Option<DataType>,
}

#[derive(Args, Debug)]
pub struct DataDeleteArgs {
    /// Data type to delete
    #[arg(short, long, value_enum)]
    pub data_type: DataType,

    /// Start date
    #[arg(long)]
    pub start: Option<String>,

    /// End date
    #[arg(long)]
    pub end: Option<String>,

    /// Delete all data of this type
    #[arg(long)]
    pub all: bool,
}

// ============================================================================
// Events Query Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum EventsCommand {
    /// Query events from local database
    Query(EventsQueryArgs),
    /// Lookup event by ID
    Lookup(EventsLookupArgs),
    /// Query by actor
    Actors(EventsActorsArgs),
    /// Query by country
    Countries(EventsCountriesArgs),
    /// CAMEO code reference
    #[command(subcommand)]
    Codes(CodesCommand),
}

#[derive(Args, Debug)]
pub struct EventsQueryArgs {
    /// Filter by actor code
    #[arg(short, long)]
    pub actor: Option<String>,

    /// Filter by event code (supports wildcards like "14*")
    #[arg(short, long)]
    pub event_code: Option<String>,

    /// Filter by quad class (1-4)
    #[arg(long)]
    pub quad_class: Option<u8>,

    /// Filter by country
    #[arg(short, long)]
    pub country: Option<String>,

    /// Start date (YYYY-MM-DD)
    #[arg(long)]
    pub start: Option<String>,

    /// End date (YYYY-MM-DD)
    #[arg(long)]
    pub end: Option<String>,

    /// Minimum Goldstein scale (-10 to 10)
    #[arg(long)]
    pub goldstein_min: Option<f64>,

    /// Maximum Goldstein scale
    #[arg(long)]
    pub goldstein_max: Option<f64>,

    /// Maximum results
    #[arg(short = 'n', long, default_value = "100")]
    pub limit: u32,

    /// Offset for pagination
    #[arg(long, default_value = "0")]
    pub offset: u32,
}

#[derive(Args, Debug)]
pub struct EventsLookupArgs {
    /// Global event ID
    pub event_id: String,
}

#[derive(Args, Debug)]
pub struct EventsActorsArgs {
    /// Actor code pattern
    pub actor: Option<String>,

    /// Include statistics
    #[arg(long)]
    pub stats: bool,

    /// Limit results
    #[arg(short = 'n', long, default_value = "50")]
    pub limit: u32,
}

#[derive(Args, Debug)]
pub struct EventsCountriesArgs {
    /// Country code
    pub country: Option<String>,

    /// Date range start
    #[arg(long)]
    pub start: Option<String>,

    /// Date range end
    #[arg(long)]
    pub end: Option<String>,
}

#[derive(Subcommand, Debug)]
pub enum CodesCommand {
    /// List CAMEO codes
    List(CodesListArgs),
    /// Search codes by description
    Search(CodesSearchArgs),
    /// Describe a specific code
    Describe(CodesDescribeArgs),
}

#[derive(Args, Debug)]
pub struct CodesListArgs {
    /// Code type (event, actor, country)
    #[arg(short = 't', long, value_enum)]
    pub code_type: Option<CodeType>,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum CodeType {
    Event,
    Actor,
    Country,
    Ethnic,
    Religion,
}

#[derive(Args, Debug)]
pub struct CodesSearchArgs {
    /// Search pattern
    pub pattern: String,
}

#[derive(Args, Debug)]
pub struct CodesDescribeArgs {
    /// Code to describe
    pub code: String,
}

// ============================================================================
// GKG Query Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum GkgCommand {
    /// Query GKG records
    Query(GkgQueryArgs),
    /// Query by themes
    Themes(GkgThemesArgs),
    /// Query person mentions
    Persons(GkgPersonsArgs),
    /// Query organization mentions
    Organizations(GkgOrganizationsArgs),
    /// Query location mentions
    Locations(GkgLocationsArgs),
}

#[derive(Args, Debug)]
pub struct GkgQueryArgs {
    /// Filter by theme
    #[arg(short, long)]
    pub theme: Option<String>,

    /// Filter by person
    #[arg(short, long)]
    pub person: Option<String>,

    /// Filter by organization
    #[arg(short, long)]
    pub org: Option<String>,

    /// Start date
    #[arg(long)]
    pub start: Option<String>,

    /// End date
    #[arg(long)]
    pub end: Option<String>,

    /// Maximum results
    #[arg(short = 'n', long, default_value = "100")]
    pub limit: u32,
}

#[derive(Args, Debug)]
pub struct GkgThemesArgs {
    /// Theme pattern to search
    pub pattern: Option<String>,

    /// Minimum occurrence count
    #[arg(long, default_value = "10")]
    pub min_count: u32,

    /// Date range start
    #[arg(long)]
    pub start: Option<String>,

    /// Date range end
    #[arg(long)]
    pub end: Option<String>,
}

#[derive(Args, Debug)]
pub struct GkgPersonsArgs {
    /// Person name pattern
    pub pattern: Option<String>,

    /// Minimum occurrence count
    #[arg(long, default_value = "5")]
    pub min_count: u32,

    /// Limit results
    #[arg(short = 'n', long, default_value = "50")]
    pub limit: u32,
}

#[derive(Args, Debug)]
pub struct GkgOrganizationsArgs {
    /// Organization name pattern
    pub pattern: Option<String>,

    /// Minimum occurrence count
    #[arg(long, default_value = "5")]
    pub min_count: u32,

    /// Limit results
    #[arg(short = 'n', long, default_value = "50")]
    pub limit: u32,
}

#[derive(Args, Debug)]
pub struct GkgLocationsArgs {
    /// Location name pattern
    pub pattern: Option<String>,

    /// Filter by country
    #[arg(short, long)]
    pub country: Option<String>,

    /// Limit results
    #[arg(short = 'n', long, default_value = "50")]
    pub limit: u32,
}

// ============================================================================
// Database Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum DbCommand {
    /// Show database statistics
    Stats(DbStatsArgs),
    /// Optimize database
    Vacuum(DbVacuumArgs),
    /// Export data to file
    Export(DbExportArgs),
    /// Import data from file
    Import(DbImportArgs),
    /// Run raw SQL query
    Query(DbQueryArgs),
}

#[derive(Args, Debug)]
pub struct DbStatsArgs {
    /// Show detailed statistics
    #[arg(long)]
    pub detailed: bool,
}

#[derive(Args, Debug)]
pub struct DbVacuumArgs {
    /// Analyze and optimize
    #[arg(long)]
    pub analyze: bool,
}

#[derive(Args, Debug)]
pub struct DbExportArgs {
    /// Table to export
    pub table: String,

    /// Output file path
    #[arg(short, long)]
    pub output: PathBuf,

    /// Export format
    #[arg(short, long, value_enum, default_value = "parquet")]
    pub format: ExportFormat,

    /// Filter query (WHERE clause)
    #[arg(long)]
    pub filter: Option<String>,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum ExportFormat {
    Parquet,
    Csv,
    Json,
}

#[derive(Args, Debug)]
pub struct DbImportArgs {
    /// Input file path
    pub input: PathBuf,

    /// Target table
    #[arg(short, long)]
    pub table: String,

    /// Import format (auto-detected from extension if not specified)
    #[arg(short, long, value_enum)]
    pub format: Option<ExportFormat>,
}

#[derive(Args, Debug)]
pub struct DbQueryArgs {
    /// SQL query to execute
    pub query: String,
}

// ============================================================================
// Serve & Daemon Commands
// ============================================================================

#[derive(Args, Debug)]
pub struct ServeArgs {
    /// Transport type
    #[arg(short, long, value_enum, default_value = "stdio")]
    pub transport: Transport,

    /// Port for HTTP/SSE transport
    #[arg(short, long, default_value = "8080")]
    pub port: u16,

    /// Host to bind to
    #[arg(long, default_value = "127.0.0.1")]
    pub host: String,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum Transport {
    Stdio,
    Sse,
    Http,
}

#[derive(Subcommand, Debug)]
pub enum DaemonCommand {
    /// Start the daemon
    Start(DaemonStartArgs),
    /// Stop the daemon
    Stop,
    /// Restart the daemon
    Restart,
    /// Show daemon status
    Status,
    /// View daemon logs
    Logs(DaemonLogsArgs),
    /// Install as system service
    Install(DaemonInstallArgs),
    /// Uninstall system service
    Uninstall,
    /// Run daemon (internal use)
    #[command(hide = true)]
    Run,
}

#[derive(Args, Debug)]
pub struct DaemonStartArgs {
    /// Enable MCP server
    #[arg(long, default_value = "true")]
    pub mcp: bool,

    /// Enable background sync
    #[arg(long)]
    pub sync: bool,

    /// HTTP port
    #[arg(long, default_value = "8080")]
    pub port: u16,
}

#[derive(Args, Debug)]
pub struct DaemonLogsArgs {
    /// Number of lines to show
    #[arg(short = 'n', long, default_value = "50")]
    pub tail: u32,

    /// Follow log output
    #[arg(short, long)]
    pub follow: bool,
}

#[derive(Args, Debug)]
pub struct DaemonInstallArgs {
    /// Service manager type
    #[arg(long, value_enum)]
    pub service_type: Option<ServiceType>,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum ServiceType {
    Systemd,
    Launchd,
}

// ============================================================================
// Skill Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum SkillCommand {
    /// Install Claude Code skill
    Install(SkillInstallArgs),
    /// Uninstall skill
    Uninstall,
    /// Update skill files
    Update,
    /// Show skill status
    Status,
}

#[derive(Args, Debug)]
pub struct SkillInstallArgs {
    /// Install for current project only
    #[arg(long)]
    pub project: bool,

    /// Force overwrite existing skill
    #[arg(short, long)]
    pub force: bool,
}

// ============================================================================
// Analytics Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum AnalyticsCommand {
    /// Trend analysis
    Trends(AnalyticsTrendsArgs),
    /// Entity extraction
    Entities(AnalyticsEntitiesArgs),
    /// Sentiment analysis
    Sentiment(AnalyticsSentimentArgs),
    /// Compare topics (A vs B)
    Compare(AnalyticsCompareArgs),
    /// Generate reports
    #[command(subcommand)]
    Report(ReportCommand),
}

#[derive(Args, Debug)]
pub struct AnalyticsTrendsArgs {
    /// Topic(s) to analyze
    pub topics: Vec<String>,

    /// Data source
    #[arg(short, long, value_enum, default_value = "doc")]
    pub source: AnalyticsSource,

    /// Time span
    #[arg(short, long, default_value = "30d")]
    pub timespan: String,

    /// Granularity
    #[arg(short, long, value_enum, default_value = "day")]
    pub granularity: Granularity,

    /// Normalize to percentage
    #[arg(long)]
    pub normalize: bool,

    /// Detect anomalies
    #[arg(long)]
    pub detect_anomalies: bool,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum AnalyticsSource {
    Doc,
    Tv,
    Events,
    Gkg,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum Granularity {
    Hour,
    Day,
    Week,
    Month,
}

#[derive(Args, Debug)]
pub struct AnalyticsEntitiesArgs {
    /// Data source
    #[arg(short, long, value_enum, default_value = "doc")]
    pub source: AnalyticsSource,

    /// Entity type
    #[arg(short, long, value_enum, default_value = "all")]
    pub entity_type: EntityTypeArg,

    /// Minimum occurrence count
    #[arg(long, default_value = "5")]
    pub min_count: u32,

    /// Maximum entities to return
    #[arg(short = 'n', long, default_value = "50")]
    pub limit: u32,

    /// Time span
    #[arg(short, long, default_value = "7d")]
    pub timespan: String,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum EntityTypeArg {
    Person,
    Organization,
    Location,
    Actor,
    Theme,
    All,
}

#[derive(Args, Debug)]
pub struct AnalyticsSentimentArgs {
    /// Topic to analyze
    pub topic: String,

    /// Aggregation dimension
    #[arg(short, long, value_enum, default_value = "time")]
    pub dimension: SentimentDimension,

    /// Time span
    #[arg(short, long, default_value = "30d")]
    pub timespan: String,

    /// Granularity (for time dimension)
    #[arg(short, long, value_enum, default_value = "day")]
    pub granularity: Granularity,

    /// Compare with another topic
    #[arg(long)]
    pub compare_with: Option<String>,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum SentimentDimension {
    Time,
    Region,
    Source,
    Entity,
}

#[derive(Args, Debug)]
pub struct AnalyticsCompareArgs {
    /// First topic
    pub topic_a: String,

    /// Second topic
    pub topic_b: String,

    /// Time span
    #[arg(short, long, default_value = "30d")]
    pub timespan: String,
}

#[derive(Subcommand, Debug)]
pub enum ReportCommand {
    /// Generate daily report
    Daily(ReportArgs),
    /// Generate weekly report
    Weekly(ReportArgs),
    /// Generate custom report
    Custom(ReportCustomArgs),
}

#[derive(Args, Debug)]
pub struct ReportArgs {
    /// Topics to include
    #[arg(short, long)]
    pub topics: Vec<String>,

    /// Output file
    #[arg(short, long)]
    pub output: Option<PathBuf>,
}

#[derive(Args, Debug)]
pub struct ReportCustomArgs {
    /// Start date
    #[arg(long)]
    pub start: String,

    /// End date
    #[arg(long)]
    pub end: String,

    /// Topics to include
    #[arg(short, long)]
    pub topics: Vec<String>,

    /// Output file
    #[arg(short, long)]
    pub output: Option<PathBuf>,
}

// ============================================================================
// Enrich Command
// ============================================================================

#[derive(Args, Debug)]
pub struct EnrichArgs {
    /// Article URL(s) to enrich
    #[arg(required_unless_present = "stdin")]
    pub urls: Vec<String>,

    /// Read URLs from stdin (one per line)
    #[arg(long)]
    pub stdin: bool,

    /// Fetch full article text
    #[arg(long)]
    pub fetch_text: bool,

    /// Concurrent fetch limit
    #[arg(long, default_value = "5")]
    pub concurrency: usize,
}

// ============================================================================
// Config Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum ConfigCommand {
    /// Show current configuration
    Show,
    /// Get a configuration value
    Get(ConfigGetArgs),
    /// Set a configuration value
    Set(ConfigSetArgs),
    /// Reset configuration to defaults
    Reset,
    /// Validate configuration file
    Validate,
}

#[derive(Args, Debug)]
pub struct ConfigGetArgs {
    /// Configuration key
    pub key: String,
}

#[derive(Args, Debug)]
pub struct ConfigSetArgs {
    /// Configuration key
    pub key: String,
    /// Value to set
    pub value: String,
}

// ============================================================================
// Schema Commands
// ============================================================================

#[derive(Subcommand, Debug)]
pub enum SchemaCommand {
    /// List all commands
    Commands,
    /// Get schema for a specific command
    Command(SchemaCommandArgs),
    /// Get output schema for a command
    Output(SchemaOutputArgs),
    /// List all exit codes
    Codes,
    /// List MCP tool definitions
    Tools,
}

#[derive(Args, Debug)]
pub struct SchemaCommandArgs {
    /// Command name (e.g., "doc search")
    pub command: String,
}

#[derive(Args, Debug)]
pub struct SchemaOutputArgs {
    /// Command name
    pub command: String,
}

// ============================================================================
// Completions Command
// ============================================================================

#[derive(Args, Debug)]
pub struct CompletionsArgs {
    /// Shell to generate completions for
    #[arg(value_enum)]
    pub shell: Shell,
}

#[derive(Debug, Clone, Copy, ValueEnum)]
pub enum Shell {
    Bash,
    Zsh,
    Fish,
    PowerShell,
}
