//! adom-sfconvert — convert foreign EDA libraries into standard KiCad symbol +
//! footprint, so the Adom EDA family (adom-symbol / adom-footprint) can render
//! and compare them. Named like ds2sf: "sf" = symbol + footprint.
//!
//! Supported today:
//!   • EAGLE / Fusion 360  .lbr   → KiCad   (native, faithful — renders own geometry)
//! Detected but not yet converted (honest):
//!   • Altium  .SchLib / .PcbLib  → needs KiCad's Altium importer (OLE binary)

mod altium;
mod eagle;

use anyhow::{anyhow, Context, Result};
use std::path::PathBuf;

fn main() {
    if let Err(e) = run() {
        eprintln!("ERROR: {e:#}");
        std::process::exit(1);
    }
}

fn usage() -> ! {
    eprintln!(
        "adom-sfconvert {}\n\n\
         USAGE:\n  \
         adom-sfconvert convert <library-file> [--out-dir <dir>] [--name <name>]\n  \
         adom-sfconvert version\n\n\
         Converts EAGLE/Fusion 360 .lbr (and, soon, Altium .SchLib/.PcbLib) into\n  \
         <name>.kicad_sym + <name>.kicad_mod — the standard format every Adom EDA\n  \
         app renders. Original files are never modified.",
        env!("CARGO_PKG_VERSION")
    );
    std::process::exit(2);
}

fn run() -> Result<()> {
    let args: Vec<String> = std::env::args().skip(1).collect();
    match args.first().map(String::as_str) {
        Some("version") | Some("--version") | Some("-V") => {
            println!("adom-sfconvert {}", env!("CARGO_PKG_VERSION"));
            Ok(())
        }
        Some("convert") => convert(&args[1..]),
        _ => usage(),
    }
}

fn convert(args: &[String]) -> Result<()> {
    let mut file: Option<PathBuf> = None;
    let mut out_dir: Option<PathBuf> = None;
    let mut name: Option<String> = None;
    let mut i = 0;
    while i < args.len() {
        match args[i].as_str() {
            "--out-dir" => { out_dir = args.get(i + 1).map(PathBuf::from); i += 2; }
            "--name" => { name = args.get(i + 1).cloned(); i += 2; }
            s if file.is_none() => { file = Some(PathBuf::from(s)); i += 1; }
            _ => i += 1,
        }
    }
    let file = file.ok_or_else(|| anyhow!("convert needs a library file"))?;
    let out_dir = out_dir.unwrap_or_else(|| file.parent().map(PathBuf::from).unwrap_or_else(|| PathBuf::from(".")));
    let stem = name.unwrap_or_else(|| file.file_stem().map(|s| s.to_string_lossy().to_string()).unwrap_or_else(|| "part".into()));

    let ext = file.extension().and_then(|e| e.to_str()).unwrap_or("").to_lowercase();
    let bytes = std::fs::read(&file).with_context(|| format!("reading {}", file.display()))?;

    // Altium = OLE compound binary (magic d0 cf 11 e0). Read it NATIVELY with
    // altium-schlib / altium-pcblib — pure Rust, no KiCad, no service round-trip.
    // Emits the native SVG thumbnail + .kicad_sym/.kicad_mod (export).
    let is_ole = bytes.starts_with(&[0xD0, 0xCF, 0x11, 0xE0]);
    if ext == "schlib" || ext == "pcblib" || ext == "intlib" || is_ole {
        let out = altium::convert(&file, &out_dir, &stem, &ext, true)?;
        println!("OK: {} (Altium → KiCad, native) → {}", file.display(), out.files.join(" + "));
        return Ok(());
    }

    let text = String::from_utf8_lossy(&bytes);
    if ext == "lbr" || text.contains("<eagle") {
        let (sym, modf) = eagle::convert(&text, &stem)?;
        std::fs::create_dir_all(&out_dir).ok();
        let mut wrote = Vec::new();
        if !sym.is_empty() {
            let p = out_dir.join(format!("{stem}.kicad_sym"));
            std::fs::write(&p, &sym).with_context(|| format!("writing {}", p.display()))?;
            wrote.push(p.display().to_string());
        }
        if !modf.is_empty() {
            let p = out_dir.join(format!("{stem}.kicad_mod"));
            std::fs::write(&p, &modf).with_context(|| format!("writing {}", p.display()))?;
            wrote.push(p.display().to_string());
        }
        // Native SVG thumbnails — drawn straight from the EAGLE geometry, no
        // KiCad round-trip (same as the Altium path).
        let sym_svg = eagle::render_symbol_svg(&text, &stem);
        if !sym_svg.is_empty() {
            let p = out_dir.join(format!("{stem}-symbol.svg"));
            std::fs::write(&p, &sym_svg).ok();
            wrote.push(p.display().to_string());
        }
        let fp_svg = eagle::render_footprint_svg(&text, &stem);
        if !fp_svg.is_empty() {
            let p = out_dir.join(format!("{stem}-footprint.svg"));
            std::fs::write(&p, &fp_svg).ok();
            wrote.push(p.display().to_string());
        }
        if wrote.is_empty() {
            return Err(anyhow!("EAGLE library had no <symbol> or <package> to convert"));
        }
        println!("OK: {} (EAGLE/Fusion, native) → {}", file.display(), wrote.join(" + "));
        return Ok(());
    }

    Err(anyhow!("unrecognized library format: {} (expected .lbr / .SchLib / .PcbLib)", file.display()))
}