use serde_json::Value;
use std::collections::HashMap;
use std::fs;
use std::path::Path;
use crate::avatars::emojis::pick_emoji;
use crate::avatars::{get_random_emoji_for_name, load_avatars, save_avatars, MAIN_EMOJI};
use crate::commands::utils::input::{ask_string, ask_yes_no, default_yes};
use crate::renderer::table::render_table;
use colored::*;
use serde_json::json;
pub fn count_messages_per_avatar() -> HashMap<String, usize> {
let mut counts = HashMap::new();
let messages_dir = Path::new(".fur/messages");
if !messages_dir.exists() {
return counts;
}
if let Ok(entries) = fs::read_dir(messages_dir) {
for entry in entries.flatten() {
if let Ok(content) = fs::read_to_string(entry.path()) {
if let Ok(json) = serde_json::from_str::<Value>(&content) {
if let Some(avatar) = json["avatar"].as_str() {
*counts.entry(avatar.to_string()).or_insert(0) += 1;
}
}
}
}
}
counts
}
pub fn run_avatar_view() {
let avatars = load_avatars();
if let Some(map) = avatars.as_object() {
if map.is_empty() {
println!("(no avatars yet)");
return;
}
let mut rows = Vec::new();
let mut active_idx = None;
let msg_counts = count_messages_per_avatar();
for (i, (name, val)) in map.iter().enumerate() {
if name == "main" {
if let Some(target) = val.as_str() {
let count = msg_counts.get(target).copied().unwrap_or(0);
rows.push(vec![
"⭐ main".to_string(),
target.to_string(),
count.to_string(),
]);
active_idx = Some(i);
}
} else {
let emoji = val.as_str().unwrap_or("🐾");
let count = msg_counts.get(name).copied().unwrap_or(0);
rows.push(vec![name.to_string(), emoji.to_string(), count.to_string()]);
}
}
render_table("Avatars", &["Role", "Emoji", "Messages"], rows, active_idx);
}
}
pub fn run_avatar_onboarding() {
let mut avatars = load_avatars();
println!("\n{}", "== Create Avatar ==".bright_magenta().bold());
println!(
"{}",
"A secondary avatar is anyone who isn’t you (the main user).\n\
Examples: an AI, your boss, your therapist, or your cat. \n\
If you choose [n], you’re creating or replacing the *main* avatar."
.bright_cyan()
);
let is_secondary = ask_yes_no("Secondary avatar? [Y/n]: ", default_yes);
if is_secondary {
create_secondary_avatar(&mut avatars);
} else {
create_main_avatar(&mut avatars);
}
save_avatars(&avatars);
println!("✅ Avatar creation complete. Use `fur avatar --view` to list all avatars.");
}
fn create_main_avatar(avatars: &mut serde_json::Value) {
let name = ask_string("Main avatar name [me]: ", Some("me"));
avatars["main"] = json!(name);
avatars[name.clone()] = json!(MAIN_EMOJI);
println!("[OK] Main avatar set: {}", name);
}
fn create_secondary_avatar(avatars: &mut serde_json::Value) {
let name = ask_string("Choose name [ai]: ", Some("ai"));
let suggested = get_random_emoji_for_name(&name);
let skip = ask_yes_no(
&format!("Use suggested emoji {}? [Y/n]: ", suggested),
default_yes,
);
let emoji = if skip {
suggested
} else {
pick_emoji("Your choice: ", None)
};
avatars[name.clone()] = json!(emoji);
println!(
"[OK] Other avatar '{}' created with emoji '{}'",
name, emoji
);
}