use crate::github;
use crate::models::{Account, Config, save_config, set_token};
use crate::tui::{
enter_raw_mode, exit_raw_mode, raw_confirm, raw_input, raw_password, raw_println, raw_select,
};
use colored::Colorize;
pub fn run(config: &mut Config) {
enter_raw_mode();
raw_println("");
raw_println(&format!(" {}", "Add Git Account".bold()));
raw_println(&format!(" {}", "─".repeat(48).dimmed()));
raw_println("");
let methods = vec![
"Manual Input".to_string(),
"GitHub Browser Login".to_string(),
];
let selection = raw_select("Authentication Method", &methods, 0);
match selection {
Some(0) => {
add_manual(config);
exit_raw_mode();
}
Some(1) => {
exit_raw_mode();
add_github(config);
}
_ => {
exit_raw_mode();
}
}
}
fn add_github(config: &mut Config) {
let Some((username, email, _name, token)) = github::login() else {
return;
};
println!(
" Authenticated as: {} <{}>",
username.cyan(),
email.dimmed()
);
enter_raw_mode();
let alias = raw_input("Alias (optional)", "").unwrap_or_default();
let alias = if alias.is_empty() { None } else { Some(alias) };
let existing_idx = config
.accounts
.iter()
.position(|a| a.username == username && a.alias == alias);
if existing_idx.is_some() {
let prompt = format!(
"Account '{}' (alias: {}) already exists. Overwrite?",
username.yellow(),
alias.as_deref().unwrap_or("none").yellow()
);
if raw_confirm(&prompt, false) != Some(true) {
raw_println(&format!("\n {}\n", "Cancelled.".dimmed()));
exit_raw_mode();
return;
}
}
let account = Account {
username: username.clone(),
email,
alias: alias.clone(),
host: None,
};
set_token(&username, alias.as_deref(), &token);
if let Some(idx) = existing_idx {
upsert_account_raw(config, account, Some(idx));
} else {
upsert_account_raw(config, account, None);
}
exit_raw_mode();
}
fn add_manual(config: &mut Config) {
let Some(username) = raw_input("Username", "").filter(|u| !u.is_empty()) else {
return;
};
let Some(email) = raw_input("Email", "").filter(|e| !e.is_empty()) else {
return;
};
let alias = raw_input("Alias (optional)", "").unwrap_or_default();
let alias = if alias.is_empty() { None } else { Some(alias) };
let existing_idx = config
.accounts
.iter()
.position(|a| a.username == username && a.alias == alias);
if existing_idx.is_some() {
let prompt = format!(
"Account '{}' (alias: {}) already exists. Overwrite?",
username.yellow(),
alias.as_deref().unwrap_or("none").yellow()
);
if raw_confirm(&prompt, false) != Some(true) {
raw_println(&format!("\n {}\n", "Cancelled.".dimmed()));
return;
}
}
let token = raw_password("Token/PAT (optional)").unwrap_or_default();
let host_in = raw_input("Host", "github.com").unwrap_or_else(|| "github.com".to_string());
let host = if host_in == "github.com" || host_in.is_empty() {
None
} else {
Some(host_in)
};
let account = Account {
username: username.clone(),
email,
alias: alias.clone(),
host,
};
if !token.is_empty() {
set_token(&username, alias.as_deref(), &token);
} else {
crate::models::delete_token(&username, alias.as_deref());
}
if let Some(idx) = existing_idx {
upsert_account_raw(config, account, Some(idx));
} else {
upsert_account_raw(config, account, None);
}
}
fn upsert_account_raw(config: &mut Config, account: Account, index: Option<usize>) {
let username = account.username.clone();
if let Some(idx) = index {
config.accounts[idx] = account;
raw_println(&format!(
"\n {} Account '{}' updated successfully.\n",
"✓".green().bold(),
username.cyan()
));
} else {
config.accounts.push(account);
raw_println(&format!(
"\n {} Account '{}' added successfully.\n",
"✓".green().bold(),
username.cyan()
));
}
save_config(config);
}