//! "Send to" delivery for a fetched chip — push its CAD straight to the user's
//! desktop EDA tools via the adom-desktop bridge. KiCad gets the native
//! `.kicad_sym` + `.kicad_mod`; Fusion 360 gets a true EAGLE `.lbr` (symbol +
//! footprint) built by adom-lbr. Altium / OrCAD have no bridge yet — the `.lbr`
//! is built, but we invite the user to build the bridge and contribute it.

use serde_json::{json, Value};
use std::path::Path;
use std::process::Command;

fn ad(verb: &str, payload: Value) -> Result<Value, String> {
    let out = Command::new("adom-desktop")
        .args([verb, &payload.to_string()])
        .output()
        .map_err(|e| format!("adom-desktop unreachable: {e}"))?;
    let txt = String::from_utf8_lossy(&out.stdout).to_string();
    Ok(serde_json::from_str::<Value>(&txt).unwrap_or_else(|_| json!({ "ok": out.status.success(), "raw": txt })))
}

fn looks_offline(v: &Value) -> bool {
    let s = v.to_string().to_lowercase();
    v.get("bridgeConnected").and_then(|b| b.as_bool()) == Some(false)
        || s.contains("not connected") || s.contains("no client")
        || s.contains("offline") || s.contains("timeout")
}

/// Altium / OrCAD: we generate a real EAGLE `.lbr` and hand it over as a
/// downloadable file with tool-accurate import guidance. Altium imports EAGLE
/// libraries natively (its Import Wizard); OrCAD has no native EAGLE path, so we
/// say so honestly. Either way a desktop *auto-import bridge* would streamline
/// it — that's the contribution CTA.
fn library_export(tool: &str, mpn: &str, lbr_name: &str) -> Value {
    let asset_url = format!("/asset/{mpn}/{lbr_name}");
    let (works, import_hint) = if tool == "Altium" {
        (true, "In Altium: File → Import Wizard → \"EAGLE Projects and Designs\" → select this .lbr → it generates the .SchLib / .PcbLib / .IntLib.")
    } else {
        (false, "OrCAD Capture can't import EAGLE .lbr directly (it uses .olb). For now route it through an EAGLE→OrCAD translator or EDIF; a native OrCAD (.olb) exporter is on the roadmap.")
    };
    json!({
        "ok": false,
        "needsBridge": true,
        "target": tool,
        "assetUrl": asset_url,
        "importHint": import_hint,
        "exportWorks": works,
        "contribute": "https://wiki.adom.inc/adom/adom-desktop",
        "message": format!(
            "Built a real EAGLE .lbr for {tool} (symbol + footprint, lint-passed). {}",
            if works {
                "Download it below and import it — Altium reads EAGLE libraries natively. A one-click Adom Desktop bridge would auto-import it; want to build that? Contribute on the wiki."
            } else {
                "Download it below. A native OrCAD exporter (and an Adom Desktop bridge to auto-import) aren't built yet — want OrCAD in the Adom ecosystem? Contribute on the wiki."
            }
        )
    })
}

/// Deliver chip `mpn` (files in `dir`) to `target`.
pub fn deliver(mpn: &str, dir: &Path, target: &str) -> Value {
    let sym = dir.join(format!("{mpn}.kicad_sym"));
    let md = dir.join(format!("{mpn}.kicad_mod"));
    if !sym.is_file() && !md.is_file() {
        return json!({ "ok": false, "error": format!("no KiCad files for {mpn}") });
    }

    if target == "kicad" {
        let mut steps = Vec::new();
        if sym.is_file() {
            steps.push(ad("send_files", json!({ "filePaths": [sym.to_string_lossy()], "targetApp": "kicad", "destinationFolder": "symbols" })));
            steps.push(ad("kicad_install_library", json!({ "libraryPath": sym.to_string_lossy(), "libraryName": mpn, "libraryType": "symbol" })));
        }
        if md.is_file() {
            steps.push(ad("send_files", json!({ "filePaths": [md.to_string_lossy()], "targetApp": "kicad", "destinationFolder": "footprints" })));
            steps.push(ad("kicad_install_library", json!({ "libraryPath": md.to_string_lossy(), "libraryName": mpn, "libraryType": "footprint" })));
        }
        return summarize("KiCad", "symbol + footprint", &steps);
    }

    let (tool, app, folder) = match target {
        "fusion360" | "fusion" => ("Fusion 360", "fusion360", "fusion"),
        "altium" => ("Altium", "altium", "altium"),
        "orcad" => ("OrCAD", "orcad", "orcad"),
        _ => return json!({ "ok": false, "error": format!("unknown target {target}") }),
    };

    // Build the .lbr (symbol + footprint) via adom-lbr. For Altium/OrCAD write it
    // into the chip's library folder so it's downloadable via /asset/<mpn>/.
    let lbr_name = if app == "altium" || app == "orcad" { format!("{mpn}.lbr") } else { format!("{mpn}.send.lbr") };
    let lbr_path = dir.join(&lbr_name);
    let mut g = Command::new("adom-lbr");
    g.arg("generate");
    if sym.is_file() { g.args(["--sym"]).arg(&sym); }
    if md.is_file() { g.args(["--fp"]).arg(&md); }
    g.args(["--name", mpn]).arg("--output").arg(&lbr_path);
    match g.output() {
        Ok(o) if o.status.success() || lbr_path.is_file() => {}
        Ok(o) => return json!({ "ok": false, "error": "adom-lbr generate failed", "detail": String::from_utf8_lossy(&o.stderr) }),
        Err(e) => return json!({ "ok": false, "error": format!("adom-lbr not available: {e}") }),
    }
    if app == "altium" || app == "orcad" {
        return library_export(tool, mpn, &lbr_name);
    }
    let send = ad("send_files", json!({ "filePaths": [lbr_path.to_string_lossy()], "targetApp": app, "destinationFolder": folder }));
    let win = send.as_ref().ok()
        .and_then(|s| s.get("destinationPaths").and_then(|p| p.as_array()).and_then(|a| a.first()).and_then(|x| x.as_str()).map(String::from))
        .unwrap_or_else(|| lbr_path.to_string_lossy().to_string());
    let mut steps = vec![send];
    if app == "fusion360" {
        steps.push(ad("fusion_open_lbr", json!({ "filePath": win })));
    }
    summarize(tool, "library (.lbr)", &steps)
}

fn summarize(tool: &str, what: &str, results: &[Result<Value, String>]) -> Value {
    for r in results {
        match r {
            Err(e) => return json!({ "ok": false, "target": tool, "error": e, "offline": e.contains("unreachable") }),
            Ok(v) if looks_offline(v) => {
                return json!({ "ok": false, "target": tool, "offline": true,
                    "message": format!("File generated, but Adom Desktop isn't connected to {tool}. Open Adom Desktop on your laptop and try again.") });
            }
            _ => {}
        }
    }
    json!({ "ok": true, "target": tool, "message": format!("Delivered {what} to {tool}.") })
}