//! Pipeline runner: render the chip's 3D thumbnails + transparent icons for one
//! MPN, write a `.thumb-errors.json` sidecar on failure, clear the
//! `.thumb-pending` marker on success.
//!
//! chip-thumbnailer renders CHIP icons (the 3D body), NOT schematic symbols or
//! PCB footprints. Symbol/footprint thumbnails are owned by adom-symbol and
//! adom-footprint; chip-fetcher shells those directly.

use crate::library::{self, ChipPaths};
use crate::ui::{ok, warn};
use crate::{manifest, render_3d};
use anyhow::Result;

#[derive(Debug, Default)]
pub struct RenderReport {
    pub mpn: String,
    pub three_d_ok: bool,
    pub errors: Vec<(&'static str, String)>,
}

impl RenderReport {
    pub fn all_ok(&self) -> bool {
        self.three_d_ok
    }
}

pub fn render_one(mpn: &str) -> Result<RenderReport> {
    let chip = ChipPaths::for_mpn(mpn)?;
    let mut report = RenderReport {
        mpn: mpn.to_string(),
        ..Default::default()
    };

    if chip.step.is_some() {
        match render_3d::render(&chip) {
            Ok(_) => {
                report.three_d_ok = true;
                ok(format!("3d   → {}", chip.three_d_thumb().display()));
            }
            Err(e) => {
                report.errors.push(("3d", format!("{e}")));
                warn(format!("3d   failed: {e}"));
            }
        }
    } else {
        report.errors.push(("3d", "no .step in chip dir".into()));
        warn("3d   skipped: no .step");
    }

    if report.all_ok() {
        library::clear_pending(mpn)?;
        library::clear_errors(mpn);
    } else if !report.errors.is_empty() {
        let kinds: Vec<(&str, String)> = report
            .errors
            .iter()
            .map(|(k, v)| (*k, v.clone()))
            .collect();
        let _ = library::write_errors(mpn, &kinds);
    }

    // Always (re)write the manifest — even on partial render, so downstream
    // apps can see what's available and what's missing.
    match manifest::write(&chip) {
        Ok(path) => ok(format!("manifest → {}", path.display())),
        Err(e) => warn(format!("manifest write failed: {e}")),
    }

    Ok(report)
}

pub fn render_pending() -> Result<usize> {
    let mut n = 0;
    for mpn in library::pending_chips()? {
        let _ = render_one(&mpn);
        n += 1;
    }
    Ok(n)
}