using Schaad.Accounting;
using Schaad.Accounting.Datasets.Charts;
namespace Schaad.Accounting.UI.Components.Pages.Charts;
///
/// Swiss (de-CH) formatting for chart labels/tooltips, plus the top-N + "Andere"
/// folding used to keep pies and stacked series legible. Plotly's own d3-format
/// tokens can't produce the apostrophe thousands separator, so values are
/// pre-formatted here in C# and passed to Plotly as literal text.
///
public static class ChartFormatting
{
private static readonly string[] MonthAbbreviations =
[
"Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"
];
public static string MonthLabel(DateOnly date) => $"{MonthAbbreviations[date.Month - 1]} {date.Year % 100:00}";
public static string Chf(decimal value) => $"{value.ToFormattedString()} CHF";
///
/// Sorts by magnitude descending and, past ,
/// collapses the remainder into a single "Andere" entry so a pie/legend never
/// has to carry more slices than the categorical palette can distinguish.
///
public static IReadOnlyList FoldTail(IReadOnlyList items)
{
var sorted = items.OrderByDescending(i => Math.Abs(i.Value)).ToList();
if (sorted.Count <= ChartTheme.MaxCategories)
{
return sorted;
}
var head = sorted.Take(ChartTheme.MaxCategories - 1).ToList();
var tailTotal = sorted.Skip(ChartTheme.MaxCategories - 1).Sum(i => i.Value);
head.Add(new CategoryTotal(ChartTheme.OtherLabel, tailTotal));
return head;
}
///
/// Same idea as for a set of
/// monthly series (e.g. a stacked bar chart): series are ranked by total magnitude
/// across all months, and everything past the cap is summed month-by-month into
/// a single "Andere" series.
///
public static IReadOnlyList FoldTail(IReadOnlyList series)
{
if (series.Count <= ChartTheme.MaxCategories)
{
return series;
}
var ranked = series.OrderByDescending(s => s.Y.Sum(Math.Abs)).ToList();
var head = ranked.Take(ChartTheme.MaxCategories - 1).ToList();
var tail = ranked.Skip(ChartTheme.MaxCategories - 1).ToList();
var x = tail[0].X;
var otherY = new decimal[x.Count];
foreach (var serie in tail)
{
for (var i = 0; i < x.Count; i++)
{
otherY[i] += serie.Y[i];
}
}
head.Add(new DataSerie(ChartTheme.OtherLabel, ChartTheme.OtherLabel, x, otherY));
return head;
}
}