use clap::Subcommand;
use crate::display::account::{format_account_details, format_account_list};
use crate::error::EnvelopeResult;
use crate::models::{AccountType, Money};
use crate::services::AccountService;
use crate::storage::Storage;
#[derive(Subcommand)]
pub enum AccountCommands {
Create {
name: String,
#[arg(short = 't', long, default_value = "checking")]
account_type: String,
#[arg(short, long, default_value = "0")]
balance: String,
#[arg(long)]
off_budget: bool,
},
List {
#[arg(short, long)]
all: bool,
#[arg(short, long)]
pretty: bool,
},
Show {
account: String,
},
Edit {
account: String,
#[arg(short, long)]
name: Option<String>,
},
Archive {
account: String,
},
Unarchive {
account: String,
},
}
pub fn handle_account_command(storage: &Storage, cmd: AccountCommands) -> EnvelopeResult<()> {
let service = AccountService::new(storage);
match cmd {
AccountCommands::Create {
name,
account_type,
balance,
off_budget,
} => {
let account_type = AccountType::parse(&account_type).ok_or_else(|| {
crate::error::EnvelopeError::Validation(format!(
"Invalid account type: '{}'. Valid types: checking, savings, credit, cash, investment, line_of_credit, other",
account_type
))
})?;
let mut starting_balance = Money::parse(&balance).map_err(|e| {
crate::error::EnvelopeError::Validation(format!(
"Invalid balance format: '{}'. Use format like '1000.00' or '1000'. Error: {}",
balance, e
))
})?;
if account_type.is_liability() && starting_balance.cents() > 0 {
starting_balance = Money::from_cents(-starting_balance.cents());
}
let account = service.create(&name, account_type, starting_balance, !off_budget)?;
println!("Created account: {}", account.name);
println!(" Type: {}", account.account_type);
println!(" Starting Balance: {}", account.starting_balance);
println!(
" On Budget: {}",
if account.on_budget { "Yes" } else { "No" }
);
println!(" ID: {}", account.id);
}
AccountCommands::List { all, pretty } => {
let summaries = service.list_with_balances(all)?;
print!("{}", format_account_list(&summaries, pretty));
}
AccountCommands::Show { account } => {
let found = service
.find(&account)?
.ok_or_else(|| crate::error::EnvelopeError::account_not_found(&account))?;
let summary = service.get_summary(&found)?;
print!("{}", format_account_details(&summary));
}
AccountCommands::Edit { account, name } => {
let found = service
.find(&account)?
.ok_or_else(|| crate::error::EnvelopeError::account_not_found(&account))?;
if name.is_none() {
println!("No changes specified. Use --name to change the account name.");
return Ok(());
}
let updated = service.update(found.id, name.as_deref())?;
println!("Updated account: {}", updated.name);
}
AccountCommands::Archive { account } => {
let found = service
.find(&account)?
.ok_or_else(|| crate::error::EnvelopeError::account_not_found(&account))?;
let archived = service.archive(found.id)?;
println!("Archived account: {}", archived.name);
}
AccountCommands::Unarchive { account } => {
let found = service
.find(&account)?
.ok_or_else(|| crate::error::EnvelopeError::account_not_found(&account))?;
let unarchived = service.unarchive(found.id)?;
println!("Unarchived account: {}", unarchived.name);
}
}
Ok(())
}