use crate::core::conversions::{f64_to_money_with_currency, i64_to_datetime};
use crate::history::wire::Events;
use paft::market::action::Action;
use paft::money::Currency;
#[allow(clippy::cast_possible_truncation)]
pub fn extract_actions(
events: Option<&Events>,
currency: &Currency,
) -> (Vec<Action>, Vec<(i64, f64)>) {
let mut out: Vec<Action> = Vec::new();
let mut split_events: Vec<(i64, f64)> = Vec::new();
let Some(ev) = events else {
return (out, split_events);
};
if let Some(divs) = ev.dividends.as_ref() {
for (k, d) in divs {
let ts = k.parse::<i64>().unwrap_or_else(|_| d.date.unwrap_or(0));
if let Some(amount) = d.amount {
out.push(Action::Dividend {
ts: i64_to_datetime(ts),
amount: f64_to_money_with_currency(amount, currency.clone()),
});
}
}
}
if let Some(gains) = ev.capital_gains.as_ref() {
for (k, g) in gains {
let ts = k.parse::<i64>().unwrap_or_else(|_| g.date.unwrap_or(0));
if let Some(gain) = g.amount {
out.push(Action::CapitalGain {
ts: i64_to_datetime(ts),
gain: f64_to_money_with_currency(gain, currency.clone()),
});
}
}
}
if let Some(splits) = ev.splits.as_ref() {
for (k, s) in splits {
let ts = k.parse::<i64>().unwrap_or_else(|_| s.date.unwrap_or(0));
let (num, den) = if let (Some(n), Some(d)) = (s.numerator, s.denominator) {
(n as u32, d as u32)
} else if let Some(r) = s.split_ratio.as_deref() {
let mut it = r.split('/');
let n = it.next().and_then(|x| x.parse::<u32>().ok()).unwrap_or(1);
let d = it.next().and_then(|x| x.parse::<u32>().ok()).unwrap_or(1);
(n, d)
} else {
(1, 1)
};
out.push(Action::Split {
ts: i64_to_datetime(ts),
numerator: num,
denominator: den,
});
let ratio = if den == 0 {
1.0
} else {
f64::from(num) / f64::from(den)
};
split_events.push((ts, ratio));
}
}
out.sort_by_key(|a| match a {
Action::Dividend { ts, .. } | Action::Split { ts, .. } | Action::CapitalGain { ts, .. } => {
ts.timestamp()
}
});
split_events.sort_by_key(|(ts, _)| *ts);
(out, split_events)
}