#![expect(clippy::unwrap_used, clippy::panic)]

use super::*;
use crate::types::ProductListType;
use clap::{CommandFactory, Parser};

/// Doc-comment coverage for items already converted to multi-paragraph
/// `long_about` per docs/dev/cli-doc-style.md. Phase 1 + 2a of the
/// CLI doc-expansion plan; extend as phases 2b/2c land. When this list
/// covers every leaf subcommand, drop the explicit list and walk the
/// command tree instead.
const COVERED_PATHS: &[&[&str]] = &[
    // Phase 1: top-level + 14 group variants
    &[],
    &["bug"],
    &["comment"],
    &["attachment"],
    &["config"],
    &["product"],
    &["field"],
    &["user"],
    &["group"],
    &["whoami"],
    &["server"],
    &["classification"],
    &["component"],
    &["template"],
    &["query"],
    // Phase 2a: bug.rs actions
    &["bug", "list"],
    &["bug", "view"],
    &["bug", "search"],
    &["bug", "history"],
    &["bug", "create"],
    &["bug", "my"],
    &["bug", "clone"],
    &["bug", "update"],
    // Phase 2a: config.rs actions
    &["config", "set-server"],
    &["config", "set-default"],
    &["config", "show"],
    &["config", "set-keyring"],
    &["config", "unset-keyring"],
    &["config", "migrate-to-keyring"],
    // Phase 2a: query.rs actions
    &["query", "save"],
    &["query", "list"],
    &["query", "show"],
    &["query", "delete"],
    &["query", "run"],
    // Phase 2b: attachment.rs actions
    &["attachment", "list"],
    &["attachment", "download"],
    &["attachment", "upload"],
    &["attachment", "update"],
    // Phase 2b: comment.rs actions
    &["comment", "list"],
    &["comment", "add"],
    &["comment", "tag"],
    &["comment", "search-tags"],
    // Phase 2b: user.rs actions
    &["user", "search"],
    &["user", "create"],
    &["user", "update"],
    // Phase 2b: group.rs actions
    &["group", "add-user"],
    &["group", "remove-user"],
    &["group", "list-users"],
    &["group", "view"],
    &["group", "create"],
    &["group", "update"],
    // Phase 2b: product.rs actions
    &["product", "list"],
    &["product", "view"],
    &["product", "create"],
    &["product", "update"],
    // Phase 2b: template.rs actions
    &["template", "save"],
    &["template", "list"],
    &["template", "show"],
    &["template", "delete"],
    // Phase 2b: component.rs actions
    &["component", "create"],
    &["component", "update"],
    // Phase 2c: trivial files
    &["whoami", "show"],
    &["server", "info"],
    &["classification", "view"],
    &["field", "aliases"],
    &["field", "list"],
];

#[test]
fn cli_doc_long_about_coverage() {
    let cmd = Cli::command();
    for path in COVERED_PATHS {
        let mut current = &cmd;
        for &name in *path {
            let next = current.get_subcommands().find(|c| c.get_name() == name);
            current =
                next.unwrap_or_else(|| panic!("subcommand path {path:?} not found in clap tree"));
        }
        let about = current.get_about().map(ToString::to_string);
        let long_about = current.get_long_about().map(ToString::to_string);
        assert!(
            long_about.is_some(),
            "subcommand path {path:?} is missing long_about (multi-paragraph doc comment required)"
        );
        assert_ne!(
            about, long_about,
            "subcommand path {path:?} has long_about identical to about (single-paragraph doc -- expand to multi-paragraph per docs/dev/cli-doc-style.md)"
        );
    }
}

#[test]
fn parse_bug_list_minimal() {
    let cli = Cli::try_parse_from(["bzr", "bug", "list"]).unwrap();
    assert!(matches!(
        cli.command,
        Commands::Bug {
            action: BugAction::List { .. }
        }
    ));
}

#[test]
fn parse_bug_view_by_id() {
    let cli = Cli::try_parse_from(["bzr", "bug", "view", "12345"]).unwrap();
    match cli.command {
        Commands::Bug {
            action: BugAction::View { id, .. },
        } => assert_eq!(id, "12345"),
        _ => panic!("expected Bug View"),
    }
}

#[test]
fn parse_global_json_flag() {
    let cli = Cli::try_parse_from(["bzr", "--json", "bug", "list"]).unwrap();
    assert!(cli.json);
}

#[test]
fn parse_global_server_flag() {
    let cli = Cli::try_parse_from(["bzr", "--server", "myserver", "bug", "list"]).unwrap();
    assert_eq!(cli.server.as_deref(), Some("myserver"));
}

#[test]
fn parse_config_set_server() {
    let cli = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "prod",
        "--url",
        "https://bz.example.com",
        "--api-key",
        "secret123",
    ])
    .unwrap();
    assert!(matches!(
        cli.command,
        Commands::Config {
            action: ConfigAction::SetServer { .. }
        }
    ));
}

#[test]
fn parse_config_set_server_with_env_var() {
    let cli = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "prod",
        "--url",
        "https://bz.example.com",
        "--api-key-env",
        "BZR_API_KEY",
    ])
    .unwrap();
    assert!(matches!(
        cli.command,
        Commands::Config {
            action: ConfigAction::SetServer { .. }
        }
    ));
}

#[test]
fn parse_unknown_command_fails() {
    let result = Cli::try_parse_from(["bzr", "nonexistent"]);
    assert!(result.is_err());
}

#[test]
fn parse_whoami() {
    let cli = Cli::try_parse_from(["bzr", "whoami", "show"]).unwrap();
    assert!(matches!(cli.command, Commands::Whoami { action: _ }));
}

#[test]
fn parse_bug_search() {
    let cli = Cli::try_parse_from(["bzr", "bug", "search", "crash"]).unwrap();
    match cli.command {
        Commands::Bug {
            action: BugAction::Search { query, limit, .. },
        } => {
            assert_eq!(query.as_deref(), Some("crash"));
            assert_eq!(limit, None);
        }
        _ => panic!("expected Bug Search"),
    }
}

#[test]
fn parse_bug_search_with_limit() {
    let cli = Cli::try_parse_from(["bzr", "bug", "search", "crash", "--limit", "10"]).unwrap();
    match cli.command {
        Commands::Bug {
            action: BugAction::Search { limit, .. },
        } => assert_eq!(limit, Some(10)),
        _ => panic!("expected Bug Search"),
    }
}

#[test]
fn parse_bug_history() {
    let cli = Cli::try_parse_from(["bzr", "bug", "history", "42"]).unwrap();
    match cli.command {
        Commands::Bug {
            action: BugAction::History { id, since },
        } => {
            assert_eq!(id, 42);
            assert!(since.is_none());
        }
        _ => panic!("expected Bug History"),
    }
}

#[test]
fn parse_bug_create() {
    let cli = Cli::try_parse_from([
        "bzr",
        "bug",
        "create",
        "--product",
        "TestProduct",
        "--component",
        "General",
        "--summary",
        "Test bug",
    ])
    .unwrap();
    match cli.command {
        Commands::Bug {
            action:
                BugAction::Create {
                    product,
                    component,
                    summary,
                    version,
                    ..
                },
        } => {
            assert_eq!(product.as_deref(), Some("TestProduct"));
            assert_eq!(component.as_deref(), Some("General"));
            assert_eq!(summary, "Test bug");
            assert_eq!(version, None);
        }
        _ => panic!("expected Bug Create"),
    }
}

#[test]
fn parse_bug_update_with_flags() {
    let cli = Cli::try_parse_from([
        "bzr", "bug", "update", "42", "--status", "RESOLVED", "--flag", "review+",
    ])
    .unwrap();
    match cli.command {
        Commands::Bug {
            action: BugAction::Update {
                ids, status, flag, ..
            },
        } => {
            assert_eq!(ids, vec![42]);
            assert_eq!(status.as_deref(), Some("RESOLVED"));
            assert_eq!(flag, vec!["review+"]);
        }
        _ => panic!("expected Bug Update"),
    }
}

#[test]
fn parse_comment_list() {
    let cli = Cli::try_parse_from(["bzr", "comment", "list", "99"]).unwrap();
    match cli.command {
        Commands::Comment {
            action: CommentAction::List { bug_id, .. },
        } => assert_eq!(bug_id, 99),
        _ => panic!("expected Comment List"),
    }
}

#[test]
fn parse_comment_add_with_body() {
    let cli = Cli::try_parse_from(["bzr", "comment", "add", "42", "--body", "This is a comment"])
        .unwrap();
    match cli.command {
        Commands::Comment {
            action:
                CommentAction::Add {
                    bug_id,
                    body,
                    private,
                },
        } => {
            assert_eq!(bug_id, 42);
            assert_eq!(body.as_deref(), Some("This is a comment"));
            assert!(!private);
        }
        _ => panic!("expected Comment Add"),
    }
}

#[test]
fn parse_comment_add_with_private() {
    let cli = Cli::try_parse_from([
        "bzr",
        "comment",
        "add",
        "42",
        "--body",
        "secret note",
        "--private",
    ])
    .unwrap();
    match cli.command {
        Commands::Comment {
            action:
                CommentAction::Add {
                    bug_id,
                    body,
                    private,
                },
        } => {
            assert_eq!(bug_id, 42);
            assert_eq!(body.as_deref(), Some("secret note"));
            assert!(private);
        }
        _ => panic!("expected Comment Add"),
    }
}

#[test]
fn parse_attachment_list() {
    let cli = Cli::try_parse_from(["bzr", "attachment", "list", "42"]).unwrap();
    match cli.command {
        Commands::Attachment {
            action: AttachmentAction::List { bug_id },
        } => assert_eq!(bug_id, 42),
        _ => panic!("expected Attachment List"),
    }
}

#[test]
fn parse_attachment_download() {
    let cli = Cli::try_parse_from(["bzr", "attachment", "download", "100"]).unwrap();
    match cli.command {
        Commands::Attachment {
            action: AttachmentAction::Download { id, out },
        } => {
            assert_eq!(id, 100);
            assert!(out.is_none());
        }
        _ => panic!("expected Attachment Download"),
    }
}

#[test]
fn parse_product_list() {
    let cli = Cli::try_parse_from(["bzr", "product", "list"]).unwrap();
    match cli.command {
        Commands::Product {
            action: ProductAction::List { r#type },
        } => assert_eq!(r#type, ProductListType::Accessible),
        _ => panic!("expected Product List"),
    }
}

#[test]
fn parse_product_view() {
    let cli = Cli::try_parse_from(["bzr", "product", "view", "Firefox"]).unwrap();
    match cli.command {
        Commands::Product {
            action: ProductAction::View { name },
        } => assert_eq!(name, "Firefox"),
        _ => panic!("expected Product View"),
    }
}

#[test]
fn parse_user_search() {
    let cli = Cli::try_parse_from(["bzr", "user", "search", "alice"]).unwrap();
    match cli.command {
        Commands::User {
            action: UserAction::Search { query, details },
        } => {
            assert_eq!(query, "alice");
            assert!(!details);
        }
        _ => panic!("expected User Search"),
    }
}

#[test]
fn parse_group_add_user() {
    let cli = Cli::try_parse_from([
        "bzr",
        "group",
        "add-user",
        "--group",
        "admin",
        "--user",
        "alice@test.com",
    ])
    .unwrap();
    match cli.command {
        Commands::Group {
            action: GroupAction::AddUser { group, user },
        } => {
            assert_eq!(group, "admin");
            assert_eq!(user, "alice@test.com");
        }
        _ => panic!("expected Group AddUser"),
    }
}

#[test]
fn parse_field_list() {
    let cli = Cli::try_parse_from(["bzr", "field", "list", "status"]).unwrap();
    match cli.command {
        Commands::Field {
            action: FieldAction::List { name },
        } => assert_eq!(name, "status"),
        _ => panic!("expected Field List"),
    }
}

#[test]
fn parse_server_info() {
    let cli = Cli::try_parse_from(["bzr", "server", "info"]).unwrap();
    assert!(matches!(
        cli.command,
        Commands::Server {
            action: ServerAction::Info
        }
    ));
}

#[test]
fn parse_classification_view() {
    let cli = Cli::try_parse_from(["bzr", "classification", "view", "Unclassified"]).unwrap();
    match cli.command {
        Commands::Classification {
            action: ClassificationAction::View { name },
        } => assert_eq!(name, "Unclassified"),
        _ => panic!("expected Classification View"),
    }
}

#[test]
fn parse_component_create() {
    let cli = Cli::try_parse_from([
        "bzr",
        "component",
        "create",
        "--product",
        "TestProduct",
        "--name",
        "Backend",
        "--description",
        "Backend component",
        "--default-assignee",
        "dev@test.com",
    ])
    .unwrap();
    match cli.command {
        Commands::Component {
            action:
                ComponentAction::Create {
                    product,
                    name,
                    description,
                    default_assignee,
                },
        } => {
            assert_eq!(product, "TestProduct");
            assert_eq!(name, "Backend");
            assert_eq!(description, "Backend component");
            assert_eq!(default_assignee, "dev@test.com");
        }
        _ => panic!("expected Component Create"),
    }
}

#[test]
fn parse_verbose_flag() {
    let cli = Cli::try_parse_from(["bzr", "-vvv", "whoami", "show"]).unwrap();
    assert_eq!(cli.verbose, 3);
}

#[test]
fn parse_no_color_flag() {
    let cli = Cli::try_parse_from(["bzr", "--no-color", "whoami", "show"]).unwrap();
    assert!(cli.no_color);
}

#[test]
fn parse_quiet_flag() {
    let cli = Cli::try_parse_from(["bzr", "--quiet", "whoami", "show"]).unwrap();
    assert!(cli.quiet);
}

#[test]
fn parse_api_override() {
    let cli = Cli::try_parse_from(["bzr", "--api", "xmlrpc", "whoami", "show"]).unwrap();
    assert_eq!(cli.api, Some(ApiMode::XmlRpc));
}

#[test]
fn parse_config_set_default() {
    let cli = Cli::try_parse_from(["bzr", "config", "set-default", "prod"]).unwrap();
    match cli.command {
        Commands::Config {
            action: ConfigAction::SetDefault { name },
        } => assert_eq!(name, "prod"),
        _ => panic!("expected Config SetDefault"),
    }
}

#[test]
fn parse_config_show() {
    let cli = Cli::try_parse_from(["bzr", "config", "show"]).unwrap();
    assert!(matches!(
        cli.command,
        Commands::Config {
            action: ConfigAction::Show
        }
    ));
}

#[test]
fn parse_bug_list_with_filters() {
    let cli = Cli::try_parse_from([
        "bzr",
        "bug",
        "list",
        "--product",
        "Firefox",
        "--status",
        "NEW",
        "--limit",
        "25",
    ])
    .unwrap();
    match cli.command {
        Commands::Bug {
            action:
                BugAction::List {
                    product,
                    status,
                    limit,
                    ..
                },
        } => {
            assert_eq!(product, vec!["Firefox"]);
            assert_eq!(status, vec!["NEW"]);
            assert_eq!(limit, 25);
        }
        _ => panic!("expected Bug List"),
    }
}

#[test]
fn parse_comment_tag() {
    let cli = Cli::try_parse_from([
        "bzr", "comment", "tag", "200", "--add", "spam", "--remove", "good",
    ])
    .unwrap();
    match cli.command {
        Commands::Comment {
            action:
                CommentAction::Tag {
                    comment_id,
                    add,
                    remove,
                },
        } => {
            assert_eq!(comment_id, 200);
            assert_eq!(add, vec!["spam"]);
            assert_eq!(remove, vec!["good"]);
        }
        _ => panic!("expected Comment Tag"),
    }
}

#[test]
fn parse_bug_my_defaults() {
    let cli = Cli::try_parse_from(["bzr", "bug", "my"]).unwrap();
    match cli.command {
        Commands::Bug {
            action:
                BugAction::My {
                    created,
                    cc,
                    all,
                    limit,
                    ..
                },
        } => {
            assert!(!created);
            assert!(!cc);
            assert!(!all);
            assert_eq!(limit, 50);
        }
        _ => panic!("expected Bug My"),
    }
}

#[test]
fn parse_bug_my_all_conflicts_with_created() {
    let result = Cli::try_parse_from(["bzr", "bug", "my", "--all", "--created"]);
    assert!(result.is_err(), "--all should conflict with --created");
}

#[test]
fn parse_bug_my_all_conflicts_with_cc() {
    let result = Cli::try_parse_from(["bzr", "bug", "my", "--all", "--cc"]);
    assert!(result.is_err(), "--all should conflict with --cc");
}

#[test]
fn parse_bug_clone_minimal() {
    let cli = Cli::try_parse_from(["bzr", "bug", "clone", "123"]).unwrap();
    match cli.command {
        Commands::Bug {
            action: BugAction::Clone { id, summary, .. },
        } => {
            assert_eq!(id, "123");
            assert!(summary.is_none());
        }
        _ => panic!("expected Bug Clone"),
    }
}

#[test]
fn parse_template_save_with_fields() {
    let cli = Cli::try_parse_from([
        "bzr",
        "template",
        "save",
        "security-bug",
        "--product",
        "Security",
        "--component",
        "Vulnerabilities",
        "--severity",
        "critical",
    ])
    .unwrap();
    match cli.command {
        Commands::Template {
            action:
                TemplateAction::Save {
                    name,
                    product,
                    component,
                    severity,
                    ..
                },
        } => {
            assert_eq!(name, "security-bug");
            assert_eq!(product.as_deref(), Some("Security"));
            assert_eq!(component.as_deref(), Some("Vulnerabilities"));
            assert_eq!(severity.as_deref(), Some("critical"));
        }
        _ => panic!("expected Template Save"),
    }
}

#[test]
fn parse_query_save_list_kind() {
    let cli = Cli::try_parse_from([
        "bzr",
        "query",
        "save",
        "firefox-new",
        "--product",
        "Firefox",
        "--status",
        "NEW",
        "--limit",
        "25",
    ])
    .unwrap();
    match cli.command {
        Commands::Query {
            action:
                QueryAction::Save {
                    name,
                    product,
                    status,
                    limit,
                    ..
                },
        } => {
            assert_eq!(name, "firefox-new");
            assert_eq!(product, vec!["Firefox"]);
            assert_eq!(status, vec!["NEW"]);
            assert_eq!(limit, Some(25));
        }
        _ => panic!("expected Query Save"),
    }
}

#[test]
fn parse_query_save_search_kind() {
    let cli = Cli::try_parse_from([
        "bzr",
        "query",
        "save",
        "crashes",
        "--search",
        "crash in tab",
        "--limit",
        "10",
    ])
    .unwrap();
    match cli.command {
        Commands::Query {
            action:
                QueryAction::Save {
                    name,
                    search,
                    limit,
                    ..
                },
        } => {
            assert_eq!(name, "crashes");
            assert_eq!(search.as_deref(), Some("crash in tab"));
            assert_eq!(limit, Some(10));
        }
        _ => panic!("expected Query Save"),
    }
}

#[test]
fn parse_query_run() {
    let cli = Cli::try_parse_from(["bzr", "query", "run", "firefox-new"]).unwrap();
    match cli.command {
        Commands::Query {
            action: QueryAction::Run { name, limit, .. },
        } => {
            assert_eq!(name, "firefox-new");
            assert!(limit.is_none());
        }
        _ => panic!("expected Query Run"),
    }
}

#[test]
fn parse_query_run_with_limit_override() {
    let cli = Cli::try_parse_from(["bzr", "query", "run", "firefox-new", "--limit", "10"]).unwrap();
    match cli.command {
        Commands::Query {
            action: QueryAction::Run { name, limit, .. },
        } => {
            assert_eq!(name, "firefox-new");
            assert_eq!(limit, Some(10));
        }
        _ => panic!("expected Query Run"),
    }
}

#[test]
fn parse_query_list() {
    let cli = Cli::try_parse_from(["bzr", "query", "list"]).unwrap();
    assert!(matches!(
        cli.command,
        Commands::Query {
            action: QueryAction::List
        }
    ));
}

#[test]
fn parse_query_show() {
    let cli = Cli::try_parse_from(["bzr", "query", "show", "firefox-new"]).unwrap();
    match cli.command {
        Commands::Query {
            action: QueryAction::Show { name },
        } => {
            assert_eq!(name, "firefox-new");
        }
        _ => panic!("expected Query Show"),
    }
}

#[test]
fn parse_query_delete() {
    let cli = Cli::try_parse_from(["bzr", "query", "delete", "firefox-new"]).unwrap();
    match cli.command {
        Commands::Query {
            action: QueryAction::Delete { name },
        } => {
            assert_eq!(name, "firefox-new");
        }
        _ => panic!("expected Query Delete"),
    }
}

#[test]
fn parse_set_server_tls_ca_cert() {
    let cli = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "test",
        "--url",
        "https://example.com",
        "--api-key",
        "key",
        "--tls-ca-cert",
        "/path/to/ca.pem",
    ])
    .unwrap();
    match cli.command {
        Commands::Config {
            action: ConfigAction::SetServer { tls_ca_cert, .. },
        } => assert_eq!(tls_ca_cert.as_deref(), Some("/path/to/ca.pem")),
        _ => panic!("expected Config SetServer"),
    }
}

#[test]
fn parse_set_server_tls_insecure_conflicts_with_ca_cert() {
    let result = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "test",
        "--url",
        "https://example.com",
        "--api-key",
        "key",
        "--tls-insecure",
        "--tls-ca-cert",
        "/path/to/ca.pem",
    ]);
    assert!(result.is_err(), "should conflict");
}

#[test]
fn parse_set_server_tls_pin_now() {
    let cli = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "test",
        "--url",
        "https://example.com",
        "--api-key",
        "key",
        "--tls-pin-now",
    ])
    .unwrap();
    match cli.command {
        Commands::Config {
            action: ConfigAction::SetServer { tls_pin_now, .. },
        } => assert!(tls_pin_now),
        _ => panic!("expected Config SetServer"),
    }
}

#[test]
fn parse_set_server_tls_pin_sha256() {
    let cli = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "test",
        "--url",
        "https://example.com",
        "--api-key",
        "key",
        "--tls-pin-sha256",
        "sha256//abc123",
    ])
    .unwrap();
    match cli.command {
        Commands::Config {
            action: ConfigAction::SetServer { tls_pin_sha256, .. },
        } => assert_eq!(tls_pin_sha256.as_deref(), Some("sha256//abc123")),
        _ => panic!("expected Config SetServer"),
    }
}

#[test]
fn parse_set_server_tls_pin_clear() {
    let cli = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "test",
        "--url",
        "https://example.com",
        "--api-key",
        "key",
        "--tls-pin-clear",
    ])
    .unwrap();
    match cli.command {
        Commands::Config {
            action: ConfigAction::SetServer { tls_pin_clear, .. },
        } => assert!(tls_pin_clear),
        _ => panic!("expected Config SetServer"),
    }
}

#[test]
fn parse_set_server_tls_pin_sha256_conflicts_with_tls_insecure() {
    let result = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "test",
        "--url",
        "https://example.com",
        "--api-key",
        "key",
        "--tls-insecure",
        "--tls-pin-sha256",
        "sha256//abc123",
    ]);
    assert!(
        result.is_err(),
        "--tls-insecure should conflict with --tls-pin-sha256"
    );
}

#[test]
fn parse_set_server_tls_pin_now_conflicts_with_tls_pin_sha256() {
    let result = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "test",
        "--url",
        "https://example.com",
        "--api-key",
        "key",
        "--tls-pin-now",
        "--tls-pin-sha256",
        "sha256//abc123",
    ]);
    assert!(
        result.is_err(),
        "--tls-pin-now should conflict with --tls-pin-sha256"
    );
}

#[test]
fn parse_set_server_tls_pin_clear_conflicts_with_tls_pin_now() {
    let result = Cli::try_parse_from([
        "bzr",
        "config",
        "set-server",
        "test",
        "--url",
        "https://example.com",
        "--api-key",
        "key",
        "--tls-pin-clear",
        "--tls-pin-now",
    ]);
    assert!(
        result.is_err(),
        "--tls-pin-clear should conflict with --tls-pin-now"
    );
}

#[test]
fn parse_whoami_without_subcommand() {
    let cli = Cli::try_parse_from(["bzr", "whoami"]).unwrap();
    match cli.command {
        Commands::Whoami { action } => assert!(action.is_none()),
        _ => panic!("expected Whoami"),
    }
}

#[test]
fn parse_attachment_upload_with_summary() {
    let cli = Cli::try_parse_from([
        "bzr",
        "attachment",
        "upload",
        "42",
        "patch.diff",
        "--summary",
        "Fix crash",
    ])
    .unwrap();
    match cli.command {
        Commands::Attachment {
            action:
                AttachmentAction::Upload {
                    bug_id,
                    file,
                    summary,
                    ..
                },
        } => {
            assert_eq!(bug_id, 42);
            assert_eq!(file, "patch.diff");
            assert_eq!(summary.as_deref(), Some("Fix crash"));
        }
        _ => panic!("expected Attachment Upload"),
    }
}

#[test]
fn parse_attachment_upload_with_private_flag() {
    let cli = Cli::try_parse_from([
        "bzr",
        "attachment",
        "upload",
        "42",
        "secret.bin",
        "--private",
    ])
    .unwrap();
    match cli.command {
        Commands::Attachment {
            action: AttachmentAction::Upload {
                bug_id, private, ..
            },
        } => {
            assert_eq!(bug_id, 42);
            assert!(private, "--private should set the flag to true");
        }
        _ => panic!("expected Attachment Upload"),
    }
}

#[test]
fn parse_attachment_upload_without_private_defaults_to_false() {
    let cli = Cli::try_parse_from(["bzr", "attachment", "upload", "42", "f.txt"]).unwrap();
    match cli.command {
        Commands::Attachment {
            action: AttachmentAction::Upload { private, .. },
        } => assert!(!private, "--private absent should default to false"),
        _ => panic!("expected Attachment Upload"),
    }
}

#[test]
fn parse_template_delete() {
    let cli = Cli::try_parse_from(["bzr", "template", "delete", "security-bug"]).unwrap();
    match cli.command {
        Commands::Template {
            action: TemplateAction::Delete { name },
        } => assert_eq!(name, "security-bug"),
        _ => panic!("expected Template Delete"),
    }
}
