use bevy_ecs::prelude::{In, Res, ResMut};
use retiretui_engine::optimize::career_at_salary;
use super::people::{HeldClaims, NOBODY, PersonCursor, benefit};
use crate::commands::tui::command::Outcome;
use crate::commands::tui::confirm::Confirm;
use crate::commands::tui::documents::{Browsing, Pickers};
use crate::commands::tui::edit::{Draft, DraftEditor, Importing};
use crate::commands::tui::journal;
pub fn import_statement(
draft: Res<Draft>,
cursor: Res<PersonCursor>,
pickers: Res<Pickers>,
mut browsing: ResMut<Browsing>,
mut importing: ResMut<Importing>,
) -> Outcome {
if let Some(refusal) = draft.refuse_if_read_only() {
return refusal;
}
let Some(person) = cursor.person(&draft.plan) else {
return Outcome::Refused(NOBODY.to_owned());
};
importing.ask(person.id.clone(), &pickers, &mut browsing);
Outcome::Done
}
pub fn fill_career(cursor: Res<PersonCursor>, mut editor: DraftEditor) -> Outcome {
if let Some(refusal) = editor.draft.refuse_if_read_only() {
return refusal;
}
if let Some(issue) = editor.draft.issues().first() {
return Outcome::Refused(format!("not filled: {issue}"));
}
let Some(at) = cursor.index(&editor.draft.plan) else {
return Outcome::Refused(NOBODY.to_owned());
};
let person = &editor.draft.plan.household.people[at];
let id = person.id.clone();
let name = person.display_name().to_owned();
if !person.earnings.is_empty() {
return Outcome::Refused(format!(
"{name} has an earnings record; a statement replaces it"
));
}
let career = match career_at_salary(&editor.draft.plan, &editor.session.tables, &id) {
Ok(career) => career,
Err(reason) => return Outcome::Refused(reason),
};
let years = career.len();
editor.draft.plan.household.people[at].earnings = career;
editor.commit();
journal::say(format!(
"estimated {years} year(s) of earnings for {name} from a career at their salary"
));
Outcome::Done
}
pub fn compute_benefit(cursor: Res<PersonCursor>, mut editor: DraftEditor) -> Outcome {
if let Some(refusal) = editor.draft.refuse_if_read_only() {
return refusal;
}
let Some((id, name)) = cursor
.person(&editor.draft.plan)
.map(|person| (person.id.clone(), person.display_name().to_owned()))
else {
return Outcome::Refused(NOBODY.to_owned());
};
let typed = (editor.draft.plan.income.iter())
.position(|income| income.is_benefit_of(&id) && income.amount.is_some());
let Some(at) = typed else {
return Outcome::Refused(format!("{name} has no typed benefit to compute"));
};
editor.draft.plan.income[at].amount = None;
editor.commit();
journal::say(format!("{name}'s benefit is computed from their record"));
Outcome::Done
}
pub fn clear_record(
cursor: Res<PersonCursor>,
draft: Res<Draft>,
mut confirm: ResMut<Confirm>,
) -> Outcome {
if let Some(refusal) = draft.refuse_if_read_only() {
return refusal;
}
let Some(person) = cursor.person(&draft.plan) else {
return Outcome::Refused(NOBODY.to_owned());
};
let id = person.id.clone();
let name = person.display_name().to_owned();
if person.earnings.is_empty() {
return Outcome::Refused(format!("{name} has no earnings record"));
}
let question = format!("Clear {name}'s earnings record?");
confirm.ask(question, "Clear", move |commands| {
commands.run_system_cached_with(clear_now, id);
});
Outcome::Done
}
fn clear_now(In(id): In<String>, mut editor: DraftEditor) {
let name = editor.draft.plan.person_name(&id).to_owned();
let people = &editor.draft.plan.household.people;
let Some(at) = people.iter().position(|person| person.id == id) else {
return;
};
editor.draft.plan.household.people[at].earnings.clear();
editor.commit();
journal::say(format!("cleared {name}'s earnings record"));
}
pub fn remove_benefit(
cursor: Res<PersonCursor>,
draft: Res<Draft>,
mut confirm: ResMut<Confirm>,
) -> Outcome {
if let Some(refusal) = draft.refuse_if_read_only() {
return refusal;
}
let Some(person) = cursor.person(&draft.plan) else {
return Outcome::Refused(NOBODY.to_owned());
};
let id = person.id.clone();
let name = person.display_name().to_owned();
if benefit(&draft.plan, &id).is_none() {
return Outcome::Refused(format!("{name} has no Social Security income"));
}
let question = format!("Remove {name}'s Social Security income?");
confirm.ask(question, "Remove", move |commands| {
commands.run_system_cached_with(remove_now, id);
});
Outcome::Done
}
fn remove_now(In(id): In<String>, mut editor: DraftEditor) {
let name = editor.draft.plan.person_name(&id).to_owned();
let incomes = &editor.draft.plan.income;
let Some(at) = incomes.iter().position(|income| income.is_benefit_of(&id)) else {
return;
};
editor.draft.plan.income.remove(at);
editor.commit();
journal::say(format!("removed {name}'s Social Security income"));
}
pub fn hold_claim(
cursor: Res<PersonCursor>,
draft: Res<Draft>,
mut held: ResMut<HeldClaims>,
) -> Outcome {
let Some(person) = cursor.person(&draft.plan) else {
return Outcome::Refused(NOBODY.to_owned());
};
let id = person.id.clone();
let name = person.display_name().to_owned();
if held.0.remove(&id) {
journal::say(format!("{name}'s claim is searched again"));
} else {
journal::say(format!("{name}'s claim is held as the plan states it"));
held.0.insert(id);
}
Outcome::Done
}