use clap::{Args, Parser, Subcommand};

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore issues -n 10                     # List 10 most recently updated issues
  lore issues -s opened -l bug          # Open issues labeled 'bug'
  lore issues 42 -p group/repo          # Show issue #42 in a specific project
  lore issues --since 7d -a jsmith      # Issues updated in last 7 days by jsmith")]
pub struct IssuesArgs {
    /// Issue IID (omit to list, provide to show details)
    pub iid: Option<i64>,

    /// Maximum results
    #[arg(
        short = 'n',
        long = "limit",
        default_value = "50",
        help_heading = "Output"
    )]
    pub limit: usize,

    /// Select output fields (comma-separated, or 'minimal' preset: iid,title,state,updated_at_iso)
    #[arg(long, help_heading = "Output", value_delimiter = ',')]
    pub fields: Option<Vec<String>>,

    /// Filter by state (opened, closed, all)
    #[arg(short = 's', long, help_heading = "Filters", value_parser = ["opened", "closed", "all"])]
    pub state: Option<String>,

    /// Filter by project path
    #[arg(short = 'p', long, help_heading = "Filters")]
    pub project: Option<String>,

    /// Filter by author username
    #[arg(short = 'a', long, help_heading = "Filters")]
    pub author: Option<String>,

    /// Filter by assignee username
    #[arg(short = 'A', long, help_heading = "Filters")]
    pub assignee: Option<String>,

    /// Filter by label (repeatable, AND logic)
    #[arg(short = 'l', long, help_heading = "Filters")]
    pub label: Option<Vec<String>>,

    /// Filter by milestone title
    #[arg(short = 'm', long, help_heading = "Filters")]
    pub milestone: Option<String>,

    /// Filter by work-item status name (repeatable, OR logic)
    #[arg(long, help_heading = "Filters")]
    pub status: Vec<String>,

    /// Filter by time (7d, 2w, 1m, or YYYY-MM-DD)
    #[arg(long, help_heading = "Filters")]
    pub since: Option<String>,

    /// Filter by due date (before this date, YYYY-MM-DD)
    #[arg(long = "due-before", help_heading = "Filters")]
    pub due_before: Option<String>,

    /// Show only issues with a due date
    #[arg(
        long = "has-due",
        help_heading = "Filters",
        overrides_with = "no_has_due"
    )]
    pub has_due: bool,

    #[arg(long = "no-has-due", hide = true, overrides_with = "has_due")]
    pub no_has_due: bool,

    /// Sort field (updated, created, iid)
    #[arg(long, value_parser = ["updated", "created", "iid"], default_value = "updated", help_heading = "Sorting")]
    pub sort: String,

    /// Sort ascending (default: descending)
    #[arg(long, help_heading = "Sorting", overrides_with = "no_asc")]
    pub asc: bool,

    #[arg(long = "no-asc", hide = true, overrides_with = "asc")]
    pub no_asc: bool,

    /// Open first matching item in browser
    #[arg(
        short = 'o',
        long,
        help_heading = "Actions",
        overrides_with = "no_open"
    )]
    pub open: bool,

    #[arg(long = "no-open", hide = true, overrides_with = "open")]
    pub no_open: bool,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore mrs -s opened                    # List open merge requests
  lore mrs -s merged --since 2w         # MRs merged in the last 2 weeks
  lore mrs 99 -p group/repo             # Show MR !99 in a specific project
  lore mrs -D --reviewer jsmith         # Non-draft MRs reviewed by jsmith")]
pub struct MrsArgs {
    /// MR IID (omit to list, provide to show details)
    pub iid: Option<i64>,

    /// Maximum results
    #[arg(
        short = 'n',
        long = "limit",
        default_value = "50",
        help_heading = "Output"
    )]
    pub limit: usize,

    /// Select output fields (comma-separated, or 'minimal' preset: iid,title,state,updated_at_iso)
    #[arg(long, help_heading = "Output", value_delimiter = ',')]
    pub fields: Option<Vec<String>>,

    /// Filter by state (opened, merged, closed, locked, all)
    #[arg(short = 's', long, help_heading = "Filters", value_parser = ["opened", "merged", "closed", "locked", "all"])]
    pub state: Option<String>,

    /// Filter by project path
    #[arg(short = 'p', long, help_heading = "Filters")]
    pub project: Option<String>,

    /// Filter by author username
    #[arg(short = 'a', long, help_heading = "Filters")]
    pub author: Option<String>,

    /// Filter by assignee username
    #[arg(short = 'A', long, help_heading = "Filters")]
    pub assignee: Option<String>,

    /// Filter by reviewer username
    #[arg(short = 'r', long, help_heading = "Filters")]
    pub reviewer: Option<String>,

    /// Filter by label (repeatable, AND logic)
    #[arg(short = 'l', long, help_heading = "Filters")]
    pub label: Option<Vec<String>>,

    /// Filter by time (7d, 2w, 1m, or YYYY-MM-DD)
    #[arg(long, help_heading = "Filters")]
    pub since: Option<String>,

    /// Show only draft MRs
    #[arg(
        short = 'd',
        long,
        conflicts_with = "no_draft",
        help_heading = "Filters"
    )]
    pub draft: bool,

    /// Exclude draft MRs
    #[arg(
        short = 'D',
        long = "no-draft",
        conflicts_with = "draft",
        help_heading = "Filters"
    )]
    pub no_draft: bool,

    /// Filter by target branch
    #[arg(long, help_heading = "Filters")]
    pub target: Option<String>,

    /// Filter by source branch
    #[arg(long, help_heading = "Filters")]
    pub source: Option<String>,

    /// Sort field (updated, created, iid)
    #[arg(long, value_parser = ["updated", "created", "iid"], default_value = "updated", help_heading = "Sorting")]
    pub sort: String,

    /// Sort ascending (default: descending)
    #[arg(long, help_heading = "Sorting", overrides_with = "no_asc")]
    pub asc: bool,

    #[arg(long = "no-asc", hide = true, overrides_with = "asc")]
    pub no_asc: bool,

    /// Open first matching item in browser
    #[arg(
        short = 'o',
        long,
        help_heading = "Actions",
        overrides_with = "no_open"
    )]
    pub open: bool,

    #[arg(long = "no-open", hide = true, overrides_with = "open")]
    pub no_open: bool,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore notes                                  # List 50 most recent notes
  lore notes --author alice --since 7d        # Notes by alice in last 7 days
  lore notes --for-issue 42 -p group/repo     # Notes on issue #42
  lore notes --path src/ --resolution unresolved  # Unresolved diff notes in src/")]
pub struct NotesArgs {
    /// Maximum results
    #[arg(
        short = 'n',
        long = "limit",
        default_value = "50",
        help_heading = "Output"
    )]
    pub limit: usize,

    /// Select output fields (comma-separated, or 'minimal' preset: id,author_username,body,created_at_iso)
    #[arg(long, help_heading = "Output", value_delimiter = ',')]
    pub fields: Option<Vec<String>>,

    /// Filter by author username
    #[arg(short = 'a', long, help_heading = "Filters")]
    pub author: Option<String>,

    /// Filter by note type (DiffNote, DiscussionNote)
    #[arg(long, help_heading = "Filters")]
    pub note_type: Option<String>,

    /// Filter by body text (substring match)
    #[arg(long, help_heading = "Filters")]
    pub contains: Option<String>,

    /// Filter by internal note ID
    #[arg(long, help_heading = "Filters")]
    pub note_id: Option<i64>,

    /// Filter by GitLab note ID
    #[arg(long, help_heading = "Filters")]
    pub gitlab_note_id: Option<i64>,

    /// Filter by discussion ID
    #[arg(long, help_heading = "Filters")]
    pub discussion_id: Option<String>,

    /// Include system notes (excluded by default)
    #[arg(long, help_heading = "Filters")]
    pub include_system: bool,

    /// Filter to notes on a specific issue IID (requires --project or default_project)
    #[arg(long, conflicts_with = "for_mr", help_heading = "Filters")]
    pub for_issue: Option<i64>,

    /// Filter to notes on a specific MR IID (requires --project or default_project)
    #[arg(long, conflicts_with = "for_issue", help_heading = "Filters")]
    pub for_mr: Option<i64>,

    /// Filter by project path
    #[arg(short = 'p', long, help_heading = "Filters")]
    pub project: Option<String>,

    /// Filter by time (7d, 2w, 1m, or YYYY-MM-DD)
    #[arg(long, help_heading = "Filters")]
    pub since: Option<String>,

    /// Filter until date (YYYY-MM-DD, inclusive end-of-day)
    #[arg(long, help_heading = "Filters")]
    pub until: Option<String>,

    /// Filter by file path (exact match or prefix with trailing /)
    #[arg(long, help_heading = "Filters")]
    pub path: Option<String>,

    /// Filter by resolution status (any, unresolved, resolved)
    #[arg(
        long,
        value_parser = ["any", "unresolved", "resolved"],
        help_heading = "Filters"
    )]
    pub resolution: Option<String>,

    /// Sort field (created, updated)
    #[arg(
        long,
        value_parser = ["created", "updated"],
        default_value = "created",
        help_heading = "Sorting"
    )]
    pub sort: String,

    /// Sort ascending (default: descending)
    #[arg(long, help_heading = "Sorting")]
    pub asc: bool,

    /// Open first matching item in browser
    #[arg(long, help_heading = "Actions")]
    pub open: bool,
}

#[derive(Parser)]
pub struct IngestArgs {
    /// Entity to ingest (issues, mrs). Omit to ingest everything
    #[arg(value_parser = ["issues", "mrs"])]
    pub entity: Option<String>,

    /// Filter to single project
    #[arg(short = 'p', long)]
    pub project: Option<String>,

    /// Override stale sync lock
    #[arg(short = 'f', long, overrides_with = "no_force")]
    pub force: bool,

    #[arg(long = "no-force", hide = true, overrides_with = "force")]
    pub no_force: bool,

    /// Full re-sync: reset cursors and fetch all data from scratch
    #[arg(long, overrides_with = "no_full")]
    pub full: bool,

    #[arg(long = "no-full", hide = true, overrides_with = "full")]
    pub no_full: bool,

    /// Preview what would be synced without making changes
    #[arg(long, overrides_with = "no_dry_run")]
    pub dry_run: bool,

    #[arg(long = "no-dry-run", hide = true, overrides_with = "dry_run")]
    pub no_dry_run: bool,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore stats                              # Show document and index statistics
  lore stats --check                      # Run integrity checks
  lore stats --repair --dry-run           # Preview what repair would fix
  lore --robot stats                      # JSON output for automation")]
pub struct StatsArgs {
    /// Run integrity checks
    #[arg(long, overrides_with = "no_check")]
    pub check: bool,

    #[arg(long = "no-check", hide = true, overrides_with = "check")]
    pub no_check: bool,

    /// Repair integrity issues (auto-enables --check)
    #[arg(long)]
    pub repair: bool,

    /// Preview what would be repaired without making changes (requires --repair)
    #[arg(long, overrides_with = "no_dry_run")]
    pub dry_run: bool,

    #[arg(long = "no-dry-run", hide = true, overrides_with = "dry_run")]
    pub no_dry_run: bool,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore search 'authentication bug'               # Hybrid search (default)
  lore search 'deploy' --mode lexical --type mr   # Lexical search, MRs only
  lore search 'API rate limit' --since 30d        # Recent results only
  lore search 'config' -p group/repo --explain    # With ranking explanation")]
pub struct SearchArgs {
    /// Search query string
    pub query: String,

    /// Search mode (lexical, hybrid, semantic)
    #[arg(long, default_value = "hybrid", value_parser = ["lexical", "hybrid", "semantic"], help_heading = "Mode")]
    pub mode: String,

    /// Filter by source type (issue, mr, discussion, note)
    #[arg(long = "type", value_name = "TYPE", value_parser = ["issue", "mr", "discussion", "note"], help_heading = "Filters")]
    pub source_type: Option<String>,

    /// Filter by author username
    #[arg(long, help_heading = "Filters")]
    pub author: Option<String>,

    /// Filter by project path
    #[arg(short = 'p', long, help_heading = "Filters")]
    pub project: Option<String>,

    /// Filter by label (repeatable, AND logic)
    #[arg(long, action = clap::ArgAction::Append, help_heading = "Filters")]
    pub label: Vec<String>,

    /// Filter by file path (trailing / for prefix match)
    #[arg(long, help_heading = "Filters")]
    pub path: Option<String>,

    /// Filter by created since (7d, 2w, or YYYY-MM-DD)
    #[arg(long, help_heading = "Filters")]
    pub since: Option<String>,

    /// Filter by updated since (7d, 2w, or YYYY-MM-DD)
    #[arg(long = "updated-since", help_heading = "Filters")]
    pub updated_since: Option<String>,

    /// Maximum results (default 20, max 100)
    #[arg(
        short = 'n',
        long = "limit",
        default_value = "20",
        help_heading = "Output"
    )]
    pub limit: usize,

    /// Select output fields (comma-separated, or 'minimal' preset: document_id,title,source_type,score)
    #[arg(long, help_heading = "Output", value_delimiter = ',')]
    pub fields: Option<Vec<String>>,

    /// Show ranking explanation per result
    #[arg(long, help_heading = "Output", overrides_with = "no_explain")]
    pub explain: bool,

    #[arg(long = "no-explain", hide = true, overrides_with = "explain")]
    pub no_explain: bool,

    /// FTS query mode: safe (default) or raw
    #[arg(long = "fts-mode", default_value = "safe", value_parser = ["safe", "raw"], help_heading = "Mode")]
    pub fts_mode: String,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore generate-docs                      # Generate docs for dirty entities
  lore generate-docs --full               # Full rebuild of all documents
  lore generate-docs --full -p group/repo # Full rebuild for one project")]
pub struct GenerateDocsArgs {
    /// Full rebuild: seed all entities into dirty queue, then drain
    #[arg(long)]
    pub full: bool,

    /// Filter to single project
    #[arg(short = 'p', long)]
    pub project: Option<String>,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore sync                             # Full pipeline: ingest + docs + embed
  lore sync --no-embed                  # Skip embedding step
  lore sync --no-status                 # Skip work-item status enrichment
  lore sync --full --force              # Full re-sync, override stale lock
  lore sync --dry-run                   # Preview what would change
  lore sync --issue 42 -p group/repo    # Surgically sync one issue
  lore sync --mr 10 --mr 20 -p g/r     # Surgically sync two MRs")]
pub struct SyncArgs {
    /// Reset cursors, fetch everything
    #[arg(long, overrides_with = "no_full")]
    pub full: bool,

    #[arg(long = "no-full", hide = true, overrides_with = "full")]
    pub no_full: bool,

    /// Override stale lock
    #[arg(long, overrides_with = "no_force")]
    pub force: bool,

    #[arg(long = "no-force", hide = true, overrides_with = "force")]
    pub no_force: bool,

    /// Skip embedding step
    #[arg(long)]
    pub no_embed: bool,

    /// Skip document regeneration
    #[arg(long)]
    pub no_docs: bool,

    /// Skip resource event fetching (overrides config)
    #[arg(long = "no-events")]
    pub no_events: bool,

    /// Skip MR file change fetching (overrides config)
    #[arg(long = "no-file-changes")]
    pub no_file_changes: bool,

    /// Skip work-item status enrichment via GraphQL (overrides config)
    #[arg(long = "no-status")]
    pub no_status: bool,

    /// Preview what would be synced without making changes
    #[arg(long, overrides_with = "no_dry_run")]
    pub dry_run: bool,

    #[arg(long = "no-dry-run", hide = true, overrides_with = "dry_run")]
    pub no_dry_run: bool,

    /// Show detailed timing breakdown for sync stages
    #[arg(short = 't', long = "timings")]
    pub timings: bool,

    /// Acquire file lock before syncing (skip if another sync is running)
    #[arg(long)]
    pub lock: bool,

    /// Surgically sync specific issues by IID (repeatable, must be positive)
    #[arg(long, value_parser = clap::value_parser!(u64).range(1..), action = clap::ArgAction::Append)]
    pub issue: Vec<u64>,

    /// Surgically sync specific merge requests by IID (repeatable, must be positive)
    #[arg(long, value_parser = clap::value_parser!(u64).range(1..), action = clap::ArgAction::Append)]
    pub mr: Vec<u64>,

    /// Scope to a single project (required when --issue or --mr is used)
    #[arg(short = 'p', long)]
    pub project: Option<String>,

    /// Validate remote entities exist without DB writes (preflight only)
    #[arg(long)]
    pub preflight_only: bool,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore embed                              # Embed new/changed documents
  lore embed --full                       # Re-embed all documents from scratch
  lore embed --retry-failed               # Retry previously failed embeddings")]
pub struct EmbedArgs {
    /// Re-embed all documents (clears existing embeddings first)
    #[arg(long, overrides_with = "no_full")]
    pub full: bool,

    #[arg(long = "no-full", hide = true, overrides_with = "full")]
    pub no_full: bool,

    /// Retry previously failed embeddings
    #[arg(long, overrides_with = "no_retry_failed")]
    pub retry_failed: bool,

    #[arg(long = "no-retry-failed", hide = true, overrides_with = "retry_failed")]
    pub no_retry_failed: bool,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore timeline 'deployment'                          # Search-based seeding
  lore timeline issue:42                              # Direct: issue #42 and related entities
  lore timeline i:42                                  # Shorthand for issue:42
  lore timeline mr:99                                 # Direct: MR !99 and related entities
  lore timeline 'auth' --since 30d -p group/repo      # Scoped to project and time
  lore timeline 'migration' --depth 2              # Deep cross-reference expansion
  lore timeline 'auth' --no-mentions               # Only 'closes' and 'related' edges")]
pub struct TimelineArgs {
    /// Search text or entity reference (issue:N, i:N, mr:N, m:N)
    pub query: String,

    /// Scope to a specific project (fuzzy match)
    #[arg(short = 'p', long, help_heading = "Filters")]
    pub project: Option<String>,

    /// Only show events after this date (e.g. "6m", "2w", "2024-01-01")
    #[arg(long, help_heading = "Filters")]
    pub since: Option<String>,

    /// Cross-reference expansion depth (0 = no expansion)
    #[arg(long, default_value = "1", help_heading = "Expansion")]
    pub depth: u32,

    /// Skip 'mentioned' edges during expansion (only follow 'closes' and 'related')
    #[arg(long = "no-mentions", help_heading = "Expansion")]
    pub no_mentions: bool,

    /// Maximum number of events to display
    #[arg(
        short = 'n',
        long = "limit",
        default_value = "100",
        help_heading = "Output"
    )]
    pub limit: usize,

    /// Select output fields (comma-separated, or 'minimal' preset: timestamp,type,entity_iid,detail)
    #[arg(long, help_heading = "Output", value_delimiter = ',')]
    pub fields: Option<Vec<String>>,

    /// Maximum seed entities from search
    #[arg(long = "max-seeds", default_value = "10", help_heading = "Expansion")]
    pub max_seeds: usize,

    /// Maximum expanded entities via cross-references
    #[arg(
        long = "max-entities",
        default_value = "50",
        help_heading = "Expansion"
    )]
    pub max_entities: usize,

    /// Maximum evidence notes included
    #[arg(
        long = "max-evidence",
        default_value = "10",
        help_heading = "Expansion"
    )]
    pub max_evidence: usize,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore who src/features/auth/           # Who knows about this area?
  lore who @asmith                      # What is asmith working on?
  lore who @asmith --reviews            # What review patterns does asmith have?
  lore who --active                     # What discussions need attention?
  lore who --overlap src/features/auth/ # Who else is touching these files?
  lore who --path README.md             # Expert lookup for a root file
  lore who --path Makefile              # Expert lookup for a dotless root file")]
pub struct WhoArgs {
    /// Username or file path (path if contains /)
    pub target: Option<String>,

    /// Force expert mode for a file/directory path.
    /// Root files (README.md, LICENSE, Makefile) are treated as exact matches.
    /// Use a trailing `/` to force directory-prefix matching.
    #[arg(long, help_heading = "Mode", conflicts_with_all = ["active", "overlap", "reviews"])]
    pub path: Option<String>,

    /// Show active unresolved discussions
    #[arg(long, help_heading = "Mode", conflicts_with_all = ["target", "overlap", "reviews", "path"])]
    pub active: bool,

    /// Find users with MRs/notes touching this file path
    #[arg(long, help_heading = "Mode", conflicts_with_all = ["target", "active", "reviews", "path"])]
    pub overlap: Option<String>,

    /// Show review pattern analysis (requires username target)
    #[arg(long, help_heading = "Mode", requires = "target", conflicts_with_all = ["active", "overlap", "path"])]
    pub reviews: bool,

    /// Time window (7d, 2w, 6m, YYYY-MM-DD). Default varies by mode.
    #[arg(long, help_heading = "Filters")]
    pub since: Option<String>,

    /// Scope to a project (supports fuzzy matching)
    #[arg(short = 'p', long, help_heading = "Filters")]
    pub project: Option<String>,

    /// Maximum results per section (1..=500); omit for unlimited
    #[arg(
        short = 'n',
        long = "limit",
        value_parser = clap::value_parser!(u16).range(1..=500),
        help_heading = "Output"
    )]
    pub limit: Option<u16>,

    /// Select output fields (comma-separated, or 'minimal' preset; varies by mode)
    #[arg(long, help_heading = "Output", value_delimiter = ',')]
    pub fields: Option<Vec<String>>,

    /// Show per-MR detail breakdown (expert mode only)
    #[arg(
        long,
        help_heading = "Output",
        overrides_with = "no_detail",
        conflicts_with = "explain_score"
    )]
    pub detail: bool,

    #[arg(long = "no-detail", hide = true, overrides_with = "detail")]
    pub no_detail: bool,

    /// Score as if "now" is this date (ISO 8601 or duration like 30d). Expert mode only.
    #[arg(long = "as-of", help_heading = "Scoring")]
    pub as_of: Option<String>,

    /// Show per-component score breakdown in output. Expert mode only.
    #[arg(long = "explain-score", help_heading = "Scoring")]
    pub explain_score: bool,

    /// Include bot users in results (normally excluded via scoring.excluded_usernames).
    #[arg(long = "include-bots", help_heading = "Scoring")]
    pub include_bots: bool,

    /// Include discussions on closed issues and merged/closed MRs
    #[arg(long, help_heading = "Filters")]
    pub include_closed: bool,

    /// Remove the default time window (query all history). Conflicts with --since.
    #[arg(
        long = "all-history",
        help_heading = "Filters",
        conflicts_with = "since"
    )]
    pub all_history: bool,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore me                                 # Full dashboard (default project or all)
  lore me --issues                        # Issues section only
  lore me --mrs                           # MRs section only
  lore me --activity                      # Activity feed only
  lore me --all                           # All synced projects
  lore me --since 2d                      # Activity window (default: 30d)
  lore me --project group/repo            # Scope to one project
  lore me --user jdoe                     # Override configured username")]
pub struct MeArgs {
    /// Show open issues section
    #[arg(long, help_heading = "Sections")]
    pub issues: bool,

    /// Show authored + reviewing MRs section
    #[arg(long, help_heading = "Sections")]
    pub mrs: bool,

    /// Show activity feed section
    #[arg(long, help_heading = "Sections")]
    pub activity: bool,

    /// Show items you're @mentioned in (not assigned/authored/reviewing)
    #[arg(long, help_heading = "Sections")]
    pub mentions: bool,

    /// Activity window (e.g. 7d, 2w, 30d). Default: 30d. Only affects activity section.
    #[arg(long, help_heading = "Filters")]
    pub since: Option<String>,

    /// Scope to a project (supports fuzzy matching)
    #[arg(short = 'p', long, help_heading = "Filters", conflicts_with = "all")]
    pub project: Option<String>,

    /// Show all synced projects (overrides default_project)
    #[arg(long, help_heading = "Filters", conflicts_with = "project")]
    pub all: bool,

    /// Override configured username
    #[arg(long = "user", help_heading = "Filters")]
    pub user: Option<String>,

    /// Select output fields (comma-separated, or 'minimal' preset)
    #[arg(long, help_heading = "Output", value_delimiter = ',')]
    pub fields: Option<Vec<String>>,

    /// Reset the since-last-check cursor (next run shows no new events)
    #[arg(long, help_heading = "Output")]
    pub reset_cursor: bool,
}

impl MeArgs {
    /// Returns true if no section flags were passed (show all sections).
    pub fn show_all_sections(&self) -> bool {
        !self.issues && !self.mrs && !self.activity && !self.mentions
    }
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore file-history src/main.rs                  # MRs that touched this file
  lore file-history src/auth/ -p group/repo      # Scoped to project
  lore file-history src/foo.rs --discussions      # Include DiffNote snippets
  lore file-history src/bar.rs --no-follow-renames  # Skip rename chain")]
pub struct FileHistoryArgs {
    /// File path to trace history for
    pub path: String,

    /// Scope to a specific project (fuzzy match)
    #[arg(short = 'p', long, help_heading = "Filters")]
    pub project: Option<String>,

    /// Include discussion snippets from DiffNotes on this file
    #[arg(long, help_heading = "Output")]
    pub discussions: bool,

    /// Disable rename chain resolution
    #[arg(long = "no-follow-renames", help_heading = "Filters")]
    pub no_follow_renames: bool,

    /// Only show merged MRs
    #[arg(long, help_heading = "Filters")]
    pub merged: bool,

    /// Maximum results
    #[arg(
        short = 'n',
        long = "limit",
        default_value = "50",
        help_heading = "Output"
    )]
    pub limit: usize,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore trace src/main.rs                      # Why was this file changed?
  lore trace src/auth/ -p group/repo          # Scoped to project
  lore trace src/foo.rs --discussions          # Include DiffNote context
  lore trace src/bar.rs:42                    # Line hint (Tier 2 warning)")]
pub struct TraceArgs {
    /// File path to trace (supports :line suffix for future Tier 2)
    pub path: String,

    /// Scope to a specific project (fuzzy match)
    #[arg(short = 'p', long, help_heading = "Filters")]
    pub project: Option<String>,

    /// Include DiffNote discussion snippets
    #[arg(long, help_heading = "Output")]
    pub discussions: bool,

    /// Disable rename chain resolution
    #[arg(long = "no-follow-renames", help_heading = "Filters")]
    pub no_follow_renames: bool,

    /// Maximum trace chains to display
    #[arg(
        short = 'n',
        long = "limit",
        default_value = "20",
        help_heading = "Output"
    )]
    pub limit: usize,
}

#[derive(Parser)]
#[command(after_help = "\x1b[1mExamples:\x1b[0m
  lore count issues                       # Total issues in local database
  lore count notes --for mr               # Notes on merge requests only
  lore count discussions --for issue       # Discussions on issues only")]
pub struct CountArgs {
    /// Entity type to count (issues, mrs, discussions, notes, events)
    #[arg(value_parser = ["issues", "mrs", "discussions", "notes", "events"])]
    pub entity: String,

    /// Parent type filter: issue or mr (for discussions/notes)
    #[arg(short = 'f', long = "for", value_parser = ["issue", "mr"])]
    pub for_entity: Option<String>,
}

#[derive(Parser)]
pub struct CronArgs {
    #[command(subcommand)]
    pub action: CronAction,
}

#[derive(Subcommand)]
pub enum CronAction {
    /// Install cron job for automatic syncing
    Install {
        /// Sync interval in minutes (default: 8)
        #[arg(long, default_value = "8")]
        interval: u32,
    },

    /// Remove cron job
    Uninstall,

    /// Show current cron configuration
    Status,
}

#[derive(Args)]
pub struct TokenArgs {
    #[command(subcommand)]
    pub action: TokenAction,
}

#[derive(Subcommand)]
pub enum TokenAction {
    /// Store a GitLab token in the config file
    Set {
        /// Token value (reads from stdin if omitted in non-interactive mode)
        #[arg(long)]
        token: Option<String>,
    },

    /// Show the current token (masked by default)
    Show {
        /// Show the full unmasked token
        #[arg(long)]
        unmask: bool,
    },
}
