//! Handler for `mcptest badge`: emit a CI status badge.

use anyhow::{bail, Context, Result};
use serde_json::Value;

use mcptest_core::badge::{color_for_score, render_svg, ShieldsBadge};

use crate::cli::args::{BadgeArgs, BadgeFormat};

/// Emit a CI status badge from a score or a saved report.
pub(crate) fn badge_command(args: BadgeArgs) -> Result<i32> {
    let score = resolve_score(&args)?;
    let s = score.clamp(0.0, 100.0).round() as u8;
    let badge = ShieldsBadge::new(args.label.clone(), format!("{s}/100"), color_for_score(s));
    match args.format {
        BadgeFormat::Json => println!("{}", serde_json::to_string_pretty(&badge)?),
        BadgeFormat::Svg => print!("{}", render_svg(&badge)),
    }
    Ok(0)
}

/// Resolve the 0-100 score from `--score` or a report file's `numeric_score`
/// (compliance) or `score` field.
fn resolve_score(args: &BadgeArgs) -> Result<f64> {
    if let Some(score) = args.score {
        return Ok(score);
    }
    let Some(path) = &args.report else {
        bail!("provide --score <0-100> or a report path");
    };
    let body =
        std::fs::read_to_string(path).with_context(|| format!("reading {}", path.display()))?;
    let value: Value =
        serde_json::from_str(&body).with_context(|| format!("parsing {}", path.display()))?;
    value
        .get("numeric_score")
        .or_else(|| value.get("score"))
        .and_then(Value::as_f64)
        .with_context(|| format!("{} has no numeric_score or score field", path.display()))
}
