use crate::client::KoiClient;
pub fn run(json: bool, yes: bool) -> anyhow::Result<()> {
#[allow(clippy::disallowed_methods)]
let data_dir = koi_common::paths::koi_data_dir();
let meta = crate::help::get("factory-reset")
.ok_or_else(|| anyhow::anyhow!("internal: missing meta for 'factory-reset'"))?;
crate::help::confirm::gate_meta(meta, json, yes)?;
let daemon_was_running = try_shutdown_daemon();
if data_dir.exists() {
std::fs::remove_dir_all(&data_dir).map_err(|e| {
anyhow::anyhow!(
"Failed to remove data directory {}: {e}\n\
You may need elevated permissions (run as administrator/root).",
data_dir.display()
)
})?;
}
std::fs::create_dir_all(&data_dir).map_err(|e| {
anyhow::anyhow!(
"Failed to recreate data directory {}: {e}",
data_dir.display()
)
})?;
if json {
println!(
"{}",
serde_json::json!({
"reset": true,
"data_dir": data_dir.display().to_string(),
"daemon_stopped": daemon_was_running,
})
);
} else {
println!("Factory reset complete.");
println!(" Data directory: {}", data_dir.display());
if daemon_was_running {
println!(" Daemon was stopped before reset.");
}
println!();
println!("Koi is now in a clean state. Run `koi install` to reinstall the service.");
}
Ok(())
}
fn try_shutdown_daemon() -> bool {
let breadcrumb = match koi_config::breadcrumb::read_breadcrumb() {
Some(bc) => bc,
None => return false,
};
let client = KoiClient::with_token(&breadcrumb.endpoint, &breadcrumb.token);
match client.shutdown() {
Ok(()) => {
tracing::info!("Daemon shutdown requested successfully");
std::thread::sleep(std::time::Duration::from_secs(2));
true
}
Err(e) => {
tracing::warn!("Could not shut down daemon (may already be stopped): {e}");
true
}
}
}