use crate::cli::{err, hint, ok, DEFAULT_PORT};
use crate::cli::eval::eval_snippet;
use anyhow::Result;
use clap::Parser;

/// Sign off the currently-loaded chip — runs the same gate-check flow as
/// the Sign-off button. Writes <mpn>.chipsmith.json sidecar and (if the
/// service-step2glb /bake endpoint is deployed) the canonical
/// <mpn>.chipsmith.step. Per the plan, every downstream Adom tool must
/// prefer the baked .chipsmith.step over the original input.
#[derive(Parser)]
pub struct Args {
    /// Skip the canSignOff() gate check and force the sidecar write
    /// anyway. ONLY for triage / dry-run debugging — bypasses pin-1 +
    /// measurement + footprint validation.
    #[arg(long)]
    pub force: bool,
    #[arg(long, default_value_t = DEFAULT_PORT)]
    pub port: u16,
}

pub fn run(args: Args) -> Result<()> {
    let snippet = if args.force {
        // Skip canSignOff — invoke the underlying API directly.
        "{ \
           const payload = { \
             mpn: window.adomChipsmith?.state?.spec?.mpn, \
             measurements: window.adomChipsmith?.state?.measurements, \
             user_placed_pin1: window.adomChipsmith?.state?.userPin1Corner ? { corner: window.adomChipsmith.state.userPin1Corner } : null, \
             decorative_product_names: window.adomChipsmith?.state?.decorativeProductNames || [], \
             signed_at: new Date().toISOString(), \
             forced: true, \
           }; \
           const r = await fetch('api/signoff', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(payload) }); \
           return r.json(); \
         }".to_string()
    } else {
        "return await window.adomChipsmith.signoff.signOff();".to_string()
    };
    let v = eval_snippet(&snippet, 30, args.port, true)?;
    if let Some(blockers) = v.get("blockers").and_then(|x| x.as_array()) {
        if !blockers.is_empty() {
            err(format!("sign-off blocked by {} gate(s)", blockers.len()));
            for b in blockers {
                if let Some(s) = b.as_str() { hint(s.to_string()); }
            }
            hint("re-run with --force to bypass gates (debug only)".to_string());
            return Err(anyhow::anyhow!("blocked"));
        }
    }
    if let Some(e) = v.get("error").and_then(|x| x.as_str()) {
        err(format!("sign-off: {e}"));
        return Err(anyhow::anyhow!("signoff failed"));
    }
    if let Some(p) = v.get("sidecar_path").and_then(|x| x.as_str()) {
        ok(format!("sidecar: {p}"));
    }
    if let Some(s) = v.get("bake_status").and_then(|x| x.as_str()) {
        if !s.is_empty() { ok(format!("bake: {s}")); }
    }
    if v.get("step_baked").and_then(|x| x.as_bool()).unwrap_or(false) {
        if let Some(p) = v.get("step_path").and_then(|x| x.as_str()) {
            ok(format!("baked .chipsmith.step: {p}"));
        }
    }
    ok(format!("sign-off complete"));
    Ok(())
}