mod cli;
mod server;

use anyhow::Result;
use clap::{Parser, Subcommand};

/// adom-step — Fusion 360-style STEP file viewer.
///
/// Loads a .step / .stp file by piping it through service-step2glb, renders
/// the resulting GLB in the canonical Adom Babylon9 viewer, and adds a
/// Fusion-feel components browser, measure tool, hover/inspect HUD, and
/// section/clip planes on top.
///
/// Every UI verb has a JS API helper, an HTTP endpoint, and a CLI
/// subcommand, so an AI agent can drive the viewer headlessly.
#[derive(Parser)]
#[command(name = "adom-step", version, about, long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Command,
}

#[derive(Subcommand)]
enum Command {
    /// Open a STEP file in the Hydrogen webview tab. Converts via
    /// service-step2glb (cached on disk by content hash) then loads.
    View(cli::view::Args),
    /// Open a STEP from the service-kicad library by `<Library>/<Name>`.
    /// Example: `adom-step view-library Package_QFP/LQFP-64_10x10mm_P0.5mm`.
    ViewLibrary(cli::view_library::Args),
    /// Stop a running adom-step server on the given port.
    Stop(cli::stop::Args),
    /// Print status of the running adom-step server.
    Status(cli::status::Args),
    /// Re-attach the webview tab without restarting the server.
    Open(cli::open::Args),
    /// Health check against a running server.
    Health(cli::health::Args),
    /// Install binary to ~/.local/bin/, drop SKILL.md, install completions.
    Install(cli::install::Args),
    /// Print the discovered scene-graph component tree (one row per node).
    ListComponents(cli::list_components::Args),
    /// Hide every other top-level subtree and frame the camera on the named node.
    Isolate(cli::isolate::Args),
    /// Show the named node (and its descendants).
    Show(cli::show::Args),
    /// Hide the named node (and its descendants).
    Hide(cli::hide::Args),
    /// Show all nodes (clear visibility overrides).
    ShowAll(cli::show_all::Args),
    /// Frame the camera on a named node, or the whole model when omitted.
    Frame(cli::frame::Args),
    /// Measure the distance between two named nodes.
    /// Snaps each pick to the node's bbox center and commits as a 2-point measurement.
    Measure(cli::measure::Args),
    /// Pin-cluster operations: count | list | isolate <id> | show-all | strobe.
    /// Each "pin" is detected by clustering primitives in the Pins material group
    /// by XY centroid (eps ≈ pin pitch / 2). Useful for footprint matching.
    Pins(cli::pins::Args),
    /// Set the camera to a named view: front | back | left | right | top | bottom | iso | home.
    ViewCube(cli::view_cube::Args),
    /// Save a PNG screenshot of the current canvas.
    Screenshot(cli::screenshot::Args),
    /// Run a JavaScript snippet inside the adom-step webview and print its result.
    Eval(cli::eval::Args),
    /// Print the JavaScript console log forwarded from the adom-step webview.
    Console(cli::console::Args),
}

fn main() -> Result<()> {
    let cli = Cli::parse();
    match cli.command {
        Command::View(a) => cli::view::run(a),
        Command::ViewLibrary(a) => cli::view_library::run(a),
        Command::Stop(a) => cli::stop::run(a),
        Command::Status(a) => cli::status::run(a),
        Command::Open(a) => cli::open::run(a),
        Command::Health(a) => cli::health::run(a),
        Command::Install(a) => cli::install::run(a),
        Command::ListComponents(a) => cli::list_components::run(a),
        Command::Isolate(a) => cli::isolate::run(a),
        Command::Show(a) => cli::show::run(a),
        Command::Hide(a) => cli::hide::run(a),
        Command::ShowAll(a) => cli::show_all::run(a),
        Command::Frame(a) => cli::frame::run(a),
        Command::Measure(a) => cli::measure::run(a),
        Command::Pins(a) => cli::pins::run(a),
        Command::ViewCube(a) => cli::view_cube::run(a),
        Command::Screenshot(a) => cli::screenshot::run(a),
        Command::Eval(a) => cli::eval::run(a),
        Command::Console(a) => cli::console::run(a),
    }
}