//! Arguments for `mcptest manifest`: emit and diff a capability SBOM.

use std::path::PathBuf;

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

/// Emit a capability manifest for a server (tools classified by side-effect),
/// or diff two saved manifests to surface capability drift.
#[derive(Debug, Args)]
pub struct ManifestArgs {
    /// A `tools/list`-style JSON snapshot to classify. Omit when using `--url`
    /// or the `diff` subcommand.
    #[arg(value_name = "SNAPSHOT")]
    pub snapshot: Option<PathBuf>,

    /// Connect to a live MCP server over Streamable HTTP and classify its tools.
    #[arg(long, value_name = "URL", conflicts_with = "snapshot")]
    pub url: Option<String>,

    /// Env var holding a bearer token to use with `--url`.
    #[arg(long, value_name = "VAR")]
    pub bearer_token_env: Option<String>,

    /// Output format for the manifest.
    #[arg(long, value_enum, default_value_t = ManifestFormat::Yaml)]
    pub format: ManifestFormat,

    /// Diff two saved manifests instead of emitting one.
    #[command(subcommand)]
    pub command: Option<ManifestCommand>,
}

/// Subcommands under `mcptest manifest`.
#[derive(Debug, Subcommand)]
pub enum ManifestCommand {
    /// Diff two capability manifests and flag escalations.
    Diff(ManifestDiffArgs),
}

/// Arguments for `mcptest manifest diff`.
#[derive(Debug, Args)]
pub struct ManifestDiffArgs {
    /// The earlier manifest (YAML or JSON).
    #[arg(value_name = "OLD")]
    pub old: PathBuf,
    /// The later manifest (YAML or JSON).
    #[arg(value_name = "NEW")]
    pub new: PathBuf,
    /// Output format for the diff.
    #[arg(long, value_enum, default_value_t = ManifestFormat::Pretty)]
    pub format: ManifestFormat,
    /// Exit non-zero when the diff contains a capability escalation (a new
    /// destructive tool, a class escalation, or a newly exposed tier).
    #[arg(long)]
    pub fail_on_escalation: bool,
}

/// Output formats for capability manifests and diffs.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, ValueEnum)]
#[value(rename_all = "kebab-case")]
pub enum ManifestFormat {
    /// YAML: the diffable, human-readable manifest (default for emit).
    #[default]
    Yaml,
    /// JSON.
    Json,
    /// Human-friendly summary (default for diff; emits YAML for a manifest).
    Pretty,
}
