using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using WheresMyMoney.Maui.Core; namespace WheresMyMoney.Maui; public partial class BalanceHistoryPage : ContentPage { private DateTime _nearestPayday = DateTime.MinValue; private decimal _balanceAmount = 0; public ObservableCollection GroupedBalanceChangeViewModels { get; } = []; private static readonly GroupedBalanceChangeViewModel Empty = new("Pusto", []); public BalanceHistoryPage() { InitializeComponent(); BindingContext = this; UpdateUi(); Repository.Instance.DataChanged += OnDataChanged; } private void OnDataChanged(object? sender, EventArgs e) { UpdateUi(); } private void UpdateUi() { GroupedBalanceChangeViewModels.Clear(); var balances = Repository.Instance.GetAllBalances().GroupBy(x => x.Date.Date).OrderBy(x => x.Key); var now = DateTime.Now; _nearestPayday = Repository.Instance.GetNearestPayday(now); var allPlannedPayments = Repository.Instance.GetAllPlannedPayments().OrderBy(x => x.DateStart).ToList(); var plannedPayments = allPlannedPayments.Where(x => (!x.IsSubscription && x.DateStart <= _nearestPayday) || (x.IsSubscription && (x.DateEnd == null || x.DateEnd >= now))) .SelectMany(x => x.ExpandSubscription(balances.FirstOrDefault()?.Key.Date ?? DateTime.MinValue, _nearestPayday)) .OrderBy(x => x.DateStart).ToList(); _balanceAmount = 0; foreach (var balanceGroup in balances) { var balanceDate = balanceGroup.Key.Date; var payments = plannedPayments.Where(x => x.DateStart.Date < balanceDate).ToList(); foreach (var paymentGroup in payments.GroupBy(x => x.DateStart.Date).OrderBy(x => x.Key)) { var paymentDate = paymentGroup.Key.Date; var paymentVm = new GroupedBalanceChangeViewModel(paymentDate.ToString("yyyy MMMM dd"), []); foreach (var payment in paymentGroup) { _balanceAmount -= payment.Amount; paymentVm.BalanceChanges.Add(new BalanceChangeViewModel(payment.Name, $"{(payment.Amount < 0 ? "+" : "")}{payment.Amount * -1m:C}", _balanceAmount.ToString("C"), payment.Amount >= 0, _balanceAmount < 0)); } GroupedBalanceChangeViewModels.Add(paymentVm); } plannedPayments = plannedPayments.Except(payments).ToList(); var vm = new GroupedBalanceChangeViewModel(balanceDate.ToString("yyyy MMMM dd"), []); foreach (var thisBalanceAmount in balanceGroup.Select(x => x.Amount)) { var change = thisBalanceAmount - _balanceAmount; _balanceAmount = thisBalanceAmount; vm.BalanceChanges.Add(new BalanceChangeViewModel("Zmiana salda", $"{(change < 0 ? "" : "+")}{change:C}", thisBalanceAmount.ToString("C"), change < 0, _balanceAmount < 0)); } payments = plannedPayments.Where(x => x.DateStart.Date == balanceDate).ToList(); foreach (var payment in payments) { _balanceAmount -= payment.Amount; vm.BalanceChanges.Add(new BalanceChangeViewModel(payment.Name, $"{(payment.Amount < 0 ? "+" : "")}{payment.Amount * -1m:C}", _balanceAmount.ToString("C"), payment.Amount >= 0, _balanceAmount < 0)); } GroupedBalanceChangeViewModels.Add(vm); plannedPayments = plannedPayments.Except(payments).ToList(); } foreach (var paymentGroup in plannedPayments.GroupBy(x => x.DateStart.Date).OrderBy(x => x.Key)) { var paymentDate = paymentGroup.Key.Date; var paymentVm = new GroupedBalanceChangeViewModel(paymentDate.ToString("yyyy MMMM dd"), []); foreach (var payment in paymentGroup) { _balanceAmount -= payment.Amount; paymentVm.BalanceChanges.Add(new BalanceChangeViewModel(payment.Name, $"{(payment.Amount < 0 ? "+" : "")}{payment.Amount * -1m:C}", _balanceAmount.ToString("C"), payment.Amount >= 0, _balanceAmount < 0)); } GroupedBalanceChangeViewModels.Add(paymentVm); } if (!GroupedBalanceChangeViewModels.Any()) { GroupedBalanceChangeViewModels.Add(Empty); } } private void ItemsView_OnRemainingItemsThresholdReached(object? sender, EventArgs e) { Debug.WriteLine($"ItemsView_OnRemainingItemsThresholdReached"); var start = _nearestPayday.AddDays(1); _nearestPayday = _nearestPayday.AddMonths(1); Debug.WriteLine($"Start: {start}"); Debug.WriteLine($"End: {_nearestPayday}"); var plannedPayments = Repository.Instance.GetAllPlannedPayments().Where(x => (!x.IsSubscription && x.DateStart >= start && x.DateStart <= _nearestPayday) || (x.IsSubscription && (x.DateEnd == null || x.DateEnd >= start))) .SelectMany(x => x.ExpandSubscription(start, _nearestPayday)) .OrderBy(x => x.DateStart).ToList(); if (GroupedBalanceChangeViewModels.FirstOrDefault() == Empty) { GroupedBalanceChangeViewModels.Clear(); } foreach (var paymentGroup in plannedPayments.GroupBy(x => x.DateStart.Date).OrderBy(x => x.Key)) { var paymentDate = paymentGroup.Key.Date; var paymentVm = new GroupedBalanceChangeViewModel(paymentDate.ToString("yyyy MMMM dd"), []); foreach (var payment in paymentGroup) { _balanceAmount -= payment.Amount; paymentVm.BalanceChanges.Add(new BalanceChangeViewModel(payment.Name, $"{(payment.Amount < 0 ? "+" : "")}{payment.Amount * -1m:C}", _balanceAmount.ToString("C"), payment.Amount >= 0, _balanceAmount < 0)); } GroupedBalanceChangeViewModels.Add(paymentVm); } if (!GroupedBalanceChangeViewModels.Any()) { GroupedBalanceChangeViewModels.Add(Empty); } } } public record GroupedBalanceChangeViewModel(string DateText, List BalanceChanges); public record BalanceChangeViewModel( string Name, string AmountText, string BalanceText, bool IsPayment, bool IsBalanceNegative);