//! "Send to" delivery — push the loaded `.lbr` to the user's desktop EDA tools
//! via the adom-desktop bridge. The EAGLE-family tools (Fusion 360 / Altium /
//! OrCAD) import the `.lbr` directly. KiCad doesn't read EAGLE libraries, so we
//! convert it to a native `.kicad_sym` first (the same import path as the CLI).
//! Best-effort: a clear message when the bridge is offline.

use serde_json::{json, Value};
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")
}

/// Deliver the `.lbr` to `target` ("kicad" | "fusion360" | "altium" | "orcad").
pub fn deliver(library_name: &str, lbr: &str, target: &str) -> Value {
    if lbr.is_empty() {
        return json!({ "ok": false, "error": "no library loaded" });
    }
    let dir = std::env::temp_dir().join(format!("adom-lbr-deliver-{}", std::process::id()));
    let _ = std::fs::create_dir_all(&dir);
    let safe = library_name.replace(['/', ' '], "_");

    // KiCad: convert the EAGLE library to a native .kicad_sym.
    if target == "kicad" {
        let parsed = match crate::parse_eagle_lbr(lbr) {
            Ok(p) => p,
            Err(e) => return json!({ "ok": false, "error": format!("could not convert .lbr for KiCad: {e}") }),
        };
        let kicad_sym = crate::generate_kicad_sym(&parsed);
        let sym_path = dir.join(format!("{safe}.kicad_sym"));
        if std::fs::write(&sym_path, &kicad_sym).is_err() {
            return json!({ "ok": false, "error": "could not write temp symbol" });
        }
        let send = ad("send_files", json!({ "filePaths": [sym_path.to_string_lossy()], "targetApp": "kicad", "destinationFolder": "symbols" }));
        let inst = ad("kicad_install_library", json!({ "libraryPath": sym_path.to_string_lossy(), "libraryName": library_name, "libraryType": "symbol" }));
        return summarize("KiCad", "symbol", &[send, inst]);
    }

    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}") }),
    };

    let lbr_path = dir.join(format!("{safe}.lbr"));
    if std::fs::write(&lbr_path, lbr).is_err() {
        return json!({ "ok": false, "error": "could not write temp .lbr" });
    }
    if app == "altium" || app == "orcad" {
        return bridge_not_built(tool, &lbr_path.to_string_lossy());
    }
    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)
}

/// Altium / OrCAD have no Adom Desktop bridge yet — the .lbr is ready, but invite
/// the user to build the bridge and contribute it on the wiki.
fn bridge_not_built(tool: &str, file: &str) -> Value {
    json!({
        "ok": false,
        "needsBridge": true,
        "target": tool,
        "file": file,
        "contribute": "https://wiki.adom.inc/adom/adom-desktop",
        "message": format!("Your EAGLE .lbr for {tool} is built and saved — but the {tool} ↔ Adom Desktop bridge isn't built yet. Want {tool} connectivity in the Adom ecosystem? Be the one to build the bridge and contribute it on the wiki.")
    })
}

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}.") })
}