//! CLI surface for driving the dashboard from a terminal / from the AI.
//! `list` works standalone; `mount`/`unmount` POST to a running `app` server so
//! the webview updates live (same endpoints the UI buttons fire).

use crate::devices;
use crate::{hint, note, ok, MountArgs, UnmountArgs};
use std::collections::HashMap;

pub fn run_list(demo: bool) -> Result<(), String> {
    let snap = devices::snapshot(demo, &HashMap::new());
    note!("{}", serde_json::to_string_pretty(&snap).unwrap_or_default());
    Ok(())
}

fn post(port: u16, path: &str, body: serde_json::Value) -> Result<serde_json::Value, String> {
    let url = format!("http://127.0.0.1:{}{}", port, path);
    match ureq::post(&url).send_json(body) {
        Ok(resp) => resp.into_json::<serde_json::Value>().map_err(|e| format!("parse response: {}", e)),
        Err(ureq::Error::Status(code, resp)) => {
            let v: serde_json::Value = resp.into_json().unwrap_or(serde_json::json!({}));
            Err(format!("server returned {}: {}", code, v.get("error").and_then(|e| e.as_str()).unwrap_or("")))
        }
        Err(e) => Err(format!("could not reach the dashboard on port {} ({}). Start it with: adom-usb app", port, e)),
    }
}

pub fn run_mount(a: MountArgs) -> Result<(), String> {
    let resp = post(a.port, "/mount", serde_json::json!({"device_id": a.device_id, "target_id": a.target_id}))?;
    ok(format!("mounted {} → {}", a.device_id, a.target_id));
    if let Some(cmd) = resp.get("command").and_then(|v| v.as_str()) {
        note!("  agent command: {}", cmd);
    }
    Ok(())
}

pub fn run_flash(a: crate::FlashArgs) -> Result<(), String> {
    let resp = post(a.port, "/flash", serde_json::json!({"device_id": a.device_id, "persona": a.persona}))?;
    ok(format!("flashing {} -> persona '{}' via {}", a.device_id, a.persona,
        resp.get("plugin").and_then(|v| v.as_str()).unwrap_or("?")));
    if let Some(cmd) = resp.get("command").and_then(|v| v.as_str()) { note!("  agent command: {}", cmd); }
    hint("after flashing, the device re-enumerates as the persona's USB class — run `adom-usb list` to see it");
    Ok(())
}

pub fn run_plugins(sub: crate::PluginsCmd) -> Result<(), String> {
    match sub {
        crate::PluginsCmd::List => {
            let ps = crate::plugins::discover_installed();
            if ps.is_empty() {
                note!("no plugins installed. Search the wiki: adom-usb plugins search");
            } else {
                for p in &ps {
                    note!("{}  v{}  [{}]  matches {}", p.slug, p.version, p.kind,
                        serde_json::to_string(&p.matches).unwrap_or_default());
                }
            }
            ok(format!("{} plugin(s) installed", ps.len()));
        }
        crate::PluginsCmd::Search => {
            let installed = crate::plugins::discover_installed();
            let avail = crate::plugins::discover_registry(&installed);
            if avail.is_empty() {
                note!("no installable plugins found on the wiki (tag: {})", crate::plugins::PLUGIN_TAG);
            } else {
                for p in &avail { note!("{}  {}  — adompkg install {}", p.slug, p.description, p.slug); }
            }
            ok(format!("{} plugin(s) available to install", avail.len()));
        }
    }
    Ok(())
}

pub fn run_health(port: u16) -> Result<(), String> {
    let url = format!("http://127.0.0.1:{}/health", port);
    match ureq::get(&url).call() {
        Ok(resp) => {
            let v: serde_json::Value = resp.into_json().unwrap_or(serde_json::json!({}));
            ok(format!("dashboard healthy on port {} (devices: {})", port,
                v.get("devices").and_then(|d| d.as_u64()).unwrap_or(0)));
            Ok(())
        }
        Err(e) => Err(format!("no dashboard on port {} ({}). Start it with: adom-usb app", port, e)),
    }
}

pub fn run_unmount(a: UnmountArgs) -> Result<(), String> {
    let resp = post(a.port, "/unmount", serde_json::json!({"device_id": a.device_id}))?;
    ok(format!("unmounted {}", a.device_id));
    if let Some(cmd) = resp.get("command").and_then(|v| v.as_str()) {
        note!("  agent command: {}", cmd);
    }
    hint("see `adom-usb list` or the dashboard for the updated mount state");
    Ok(())
}