using LiteCharms.Features.Abstractions; using LiteCharms.Features.Browser; using LiteCharms.Features.Hasher; using LiteCharms.Features.MidrandBooks.Authors.Models; using LiteCharms.Features.MidrandBooks.Payments.Models; using LiteCharms.Features.MidrandBooks.Products.Models; namespace LiteCharms.Features.MidrandBooks.Payments; public sealed class CartService(LocalStorageService localStorage) : IService { private readonly string CartStorageKey = HashService.ToMd5Hash(nameof(Cart)).Value; public Cart ShoppingCart { get; private set; } = new(); public event Action? OnCartChanged; public static Func GetCartItemQuantity = (shoppingCart, productPriceId) => shoppingCart.Items.FirstOrDefault(p => p.Price!.Id == productPriceId)?.Quantity ?? 1; public Cart GetCart() => ShoppingCart; public void NotifyStateChanged() => OnCartChanged?.Invoke(); public async Task LoadCartFromStorageAsync() { var loadResult = await localStorage.GetAsync(CartStorageKey); if (loadResult.IsFailed) await localStorage.SaveAsync(CartStorageKey, ShoppingCart); if (loadResult.IsSuccess) ShoppingCart = loadResult.Value; NotifyStateChanged(); } public async Task SaveCartToStorageAsync() => await localStorage.SaveAsync(CartStorageKey, ShoppingCart); public void AddItem(ProductPrice productPrice, Product product, Author author) { var itemExists = false; for (var i = 0; i < ShoppingCart.Items.Count; i++) { if (ShoppingCart.Items[i].Price!.Id == productPrice.Id) { ShoppingCart.Items[i].Quantity++; ShoppingCart.Items[i].Amount += productPrice.Amount; itemExists = true; break; } } if (!itemExists) ShoppingCart.Items.Add(new CartItem { Product = product, Author = author, Price = productPrice, Amount = productPrice.Amount, Quantity = 1, }); CalculateTotalPrice(); NotifyStateChanged(); } public void UpdateQuantity(long productPriceId, int delta) { for (var i = 0; i < ShoppingCart.Items.Count; i++) { if (ShoppingCart.Items[i].Price!.Id == productPriceId) { var oldQuantity = ShoppingCart.Items[i].Quantity; var pricePerUnit = ShoppingCart.Items[i].Price!.Amount; ShoppingCart.Items[i].Quantity += delta; ShoppingCart.Items[i].Amount = pricePerUnit * ShoppingCart.Items[i].Quantity; break; } } CalculateTotalPrice(); NotifyStateChanged(); } public void RemoveOneItem(long productPriceId) { for (var i = 0; i < ShoppingCart.Items.Count; i++) { if (ShoppingCart.Items[i].Price!.Id == productPriceId) { if (ShoppingCart.Items[i].Quantity <= 1) { ShoppingCart.Items.Remove(ShoppingCart.Items[i]); break; } else { ShoppingCart.Items[i].Quantity--; ShoppingCart.Items[i].Amount -= ShoppingCart.Items[i].Price!.Amount; } break; } } CalculateTotalPrice(); NotifyStateChanged(); } public void RemoveAllSameItem(long productPriceId) { if (ShoppingCart.Items.Count == 0) return; var item = ShoppingCart.Items.FirstOrDefault(i => i.Price?.Id == productPriceId); if (item is not null) ShoppingCart.Items.Remove(item); CalculateTotalPrice(); NotifyStateChanged(); } public void Clear() { if(ShoppingCart.CustomerId is not null || ShoppingCart.OrderId is not null) { ShoppingCart.TotalAmount = 0; ShoppingCart.TotalVat = 0; ShoppingCart.Items.Clear(); return; } ShoppingCart = new Cart(); NotifyStateChanged(); } public decimal CalculateTotalPrice() { if (ShoppingCart.Items.Count == 0) return 0; var gross = ShoppingCart.Items.Sum(i => i.Amount); if (!ShoppingCart.IsVatInclusive) ShoppingCart.TotalVat = gross * ShoppingCart.VatRate; ShoppingCart.TotalAmount = gross + ShoppingCart.TotalVat; return ShoppingCart.TotalAmount; } }