/// Centralized metadata for a tool type.
///
/// Covers both client-side tools (ones the CLI executes locally) and
/// server-side tools (ones the API executes remotely). This is the single
/// source of truth for display text and classification.
pub(crate) struct ToolDescriptor {
    /// Canonical wire names for this tool (the names the server sends).
    pub canonical_names: &'static [&'static str],
    /// The capability string the client must advertise for this tool to be
    /// accepted. `None` for server-side tools (always accepted).
    pub capability: Option<&'static str>,
    /// Imperative verb for permission prompts (e.g. "read", "run").
    pub display_verb: &'static str,
    /// Present-tense progressive verb for spinners (e.g. "Reading file...").
    pub progressive_verb: &'static str,
    /// Past-tense verb for summaries (e.g. "Read file").
    pub past_verb: &'static str,
    /// Whether this tool is executed client-side (by the CLI).
    #[expect(dead_code)]
    pub is_client: bool,
}

// ── Client-side tool descriptors ──

pub(crate) const READ: &ToolDescriptor = &ToolDescriptor {
    canonical_names: &["read_file"],
    capability: Some("client_v1_read_file"),
    display_verb: "read",
    progressive_verb: "Reading file...",
    past_verb: "Read file",
    is_client: true,
};

pub(crate) const EDIT: &ToolDescriptor = &ToolDescriptor {
    canonical_names: &["edit_file"],
    capability: Some("client_v1_edit_file"),
    display_verb: "edit",
    progressive_verb: "Editing file...",
    past_verb: "Edited file",
    is_client: true,
};

pub(crate) const WRITE: &ToolDescriptor = &ToolDescriptor {
    canonical_names: &["write_file"],
    capability: Some("client_v1_write_file"),
    display_verb: "write to",
    progressive_verb: "Writing file...",
    past_verb: "Wrote file",
    is_client: true,
};

pub(crate) const SHELL: &ToolDescriptor = &ToolDescriptor {
    canonical_names: &["execute_shell_command"],
    capability: Some("client_v1_execute_shell_command"),
    display_verb: "run",
    progressive_verb: "Running command...",
    past_verb: "Ran command",
    is_client: true,
};

pub(crate) const ATUIN_HISTORY: &ToolDescriptor = &ToolDescriptor {
    canonical_names: &["atuin_history"],
    capability: Some("client_v1_atuin_history"),
    display_verb: "search your Atuin history for",
    progressive_verb: "Searching...",
    past_verb: "Searched",
    is_client: true,
};

pub(crate) const ATUIN_OUTPUT: &ToolDescriptor = &ToolDescriptor {
    canonical_names: &["atuin_output"],
    capability: Some("client_v1_atuin_output"),
    display_verb: "view the output for command",
    progressive_verb: "Viewing output...",
    past_verb: "Viewed output",
    is_client: true,
};

pub(crate) const LOAD_SKILL: &ToolDescriptor = &ToolDescriptor {
    canonical_names: &["load_skill"],
    capability: Some("client_v1_load_skill"),
    display_verb: "load skill",
    progressive_verb: "Loading skill...",
    past_verb: "Loaded skill",
    is_client: true,
};

// ── Server-side tool descriptors ──
// These appear in tool summaries but aren't client-side tools.

pub(crate) const SERVER_SEARCH: &ToolDescriptor = &ToolDescriptor {
    canonical_names: &["web_search"],
    capability: None,
    display_verb: "search",
    progressive_verb: "Searching...",
    past_verb: "Searched",
    is_client: false,
};

pub(crate) const SERVER_SCRAPE: &ToolDescriptor = &ToolDescriptor {
    canonical_names: &["web_scrape"],
    capability: None,
    display_verb: "scrape",
    progressive_verb: "Scraping...",
    past_verb: "Scraped",
    is_client: false,
};

/// All known tool descriptors, for lookup by name.
const ALL_DESCRIPTORS: &[&ToolDescriptor] = &[
    READ,
    EDIT,
    WRITE,
    SHELL,
    ATUIN_HISTORY,
    ATUIN_OUTPUT,
    LOAD_SKILL,
    SERVER_SEARCH,
    SERVER_SCRAPE,
];

/// Look up a tool descriptor by its canonical wire name.
/// Returns None for unknown tool names.
pub(crate) fn by_name(name: &str) -> Option<&'static ToolDescriptor> {
    ALL_DESCRIPTORS
        .iter()
        .find(|d| d.canonical_names.contains(&name))
        .copied()
}
