//! Arguments for `mcptest diff`.

use std::path::PathBuf;

use clap::{Args, ValueEnum};

/// Arguments for `mcptest diff`.
///
/// Reads two JSON snapshots of a `tools/list` response and reports which
/// tools were added, removed, or reshaped, flagging each change as breaking
/// or non-breaking so a CI job can fail loudly on a real regression.
#[derive(Debug, Args)]
pub struct DiffArgs {
    /// Path to the old snapshot (the baseline).
    pub old: PathBuf,

    /// Path to the new snapshot (the candidate).
    pub new: PathBuf,

    /// Output format for the diff report.
    #[arg(
        long,
        value_enum,
        value_name = "FORMAT",
        default_value_t = DiffFormat::Pretty
    )]
    pub format: DiffFormat,

    /// Exit code 1 when at least one change is breaking. Set to false (with
    /// `--fail-on-breaking=false`) to always exit 0, for example when the
    /// report is for advisory CI output rather than a hard gate.
    #[arg(
        long = "fail-on-breaking",
        value_name = "BOOL",
        default_value_t = true,
        action = clap::ArgAction::Set
    )]
    pub fail_on_breaking: bool,

    /// Append a release scorecard to the report: an A+/A/B/C/D/F letter
    /// grade aggregated from the breaking-change count, plus per-tool
    /// added / removed / regressed lists.
    #[arg(long)]
    pub scorecard: bool,

    /// After the drift report, print regenerated draft tests so the suite
    /// can be repaired by paste-merge instead of from scratch: a fresh
    /// draft per added tool, and with `--suite-file` also a regenerated
    /// draft per schema-changed tool plus the names of suite tests
    /// touching changed or removed tools. Drafts go to stdout, notes to
    /// stderr; exit codes are unchanged.
    #[arg(long = "suggest-regen")]
    pub suggest_regen: bool,

    /// Existing suite YAML to analyze for tests referencing changed or
    /// removed tools. Only read, never modified: drafts are additive
    /// snippets to merge by hand or via `generate suite --update`. Named
    /// `--suite-file` because the global `--suite` is an alias of
    /// `--config`.
    #[arg(long = "suite-file", value_name = "PATH", requires = "suggest_regen")]
    pub suite: Option<PathBuf>,

    /// Protocol revision the old snapshot was captured against (a
    /// `YYYY-MM-DD` date stamp, for example `2024-11-05`). When both this
    /// and `--new-protocol-version` are set, fields a snapshot's revision
    /// could not express (structured output, annotations, titles, server
    /// instructions) are skipped and footnoted instead of reported as
    /// spurious changes. Both flags must be given together.
    #[arg(
        long = "old-protocol-version",
        value_name = "VERSION",
        requires = "new_protocol_version"
    )]
    pub old_protocol_version: Option<String>,

    /// Protocol revision the new snapshot was captured against (a
    /// `YYYY-MM-DD` date stamp). See `--old-protocol-version`; both flags
    /// must be given together to enable version-gated comparison.
    #[arg(
        long = "new-protocol-version",
        value_name = "VERSION",
        requires = "old_protocol_version"
    )]
    pub new_protocol_version: Option<String>,
}

/// Output formats accepted by `mcptest diff --format`.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, ValueEnum)]
#[value(rename_all = "kebab-case")]
pub enum DiffFormat {
    /// Human-friendly grouped output (default).
    #[default]
    Pretty,
    /// Pretty-printed JSON of the [`DiffReport`].
    ///
    /// [`DiffReport`]: mcptest_core::diff::DiffReport
    Json,
    /// GitHub-flavored Markdown table for PR comments and job summaries.
    Markdown,
}
