using DateTimeConverterCL; using CMSMicroservice.Protobuf.Protos.UserCarts; using Google.Protobuf.WellKnownTypes; using Blazored.LocalStorage; namespace FrontOffice.Main.Utilities; public record CartItem(long cartId,long ProductId, string Title, string ImageUrl, long UnitPrice, int Quantity) { public long LineTotal => UnitPrice * Quantity; public long DiscountValue => (Discount*(UnitPrice * Quantity))/100; public int Discount { get; init; } public string Created { get; init; } = string.Empty; public string Description { get; init; } = string.Empty; } public class CartService { private readonly UserCartsContract.UserCartsContractClient _client; private readonly ILocalStorageService _localStorage; private readonly List _items = new(); private const string TokenStorageKey = "auth:token"; private bool _isInitialized; public event Action? OnChange; public CartService(CMSMicroservice.Protobuf.Protos.UserCarts.UserCartsContract.UserCartsContractClient client, ILocalStorageService localStorage) { _client = client; _localStorage = localStorage; // لود سبد خرید به صورت lazy انجام میشه - نه در constructor } public IReadOnlyList Items => _items.AsReadOnly(); public long Total => _items.Sum(i => i.LineTotal); public long TotalDiscount => _items.Sum(i => i.DiscountValue); public int Count => _items.Sum(i => i.Quantity); public async Task Add(Product product, int quantity = 1) { if (quantity <= 0) return; // اطمینان از لود شدن سبد خرید await EnsureInitializedAsync(); // چک لاگین بودن کاربر if (!await IsAuthenticatedAsync()) return; var existing = _items.FirstOrDefault(i => i.ProductId == product.Id); int newQuantity; if (existing is null) { newQuantity = quantity; _items.Add(new CartItem(0,product.Id, product.Title, product.ImageUrl, product.Price, newQuantity) { Discount = product.Discount, Created = DateTime.Now.MiladiToJalali(), Description = product.Description }); } else { var idx = _items.IndexOf(existing); newQuantity = existing.Quantity + quantity; _items[idx] = existing with { Quantity = newQuantity }; } Notify(); try { if (existing is null) { await _client.AddNewUserCartForCustomerAsync(new AddNewUserCartForCustomerRequest { ProductId = product.Id, Count = newQuantity }); await LoadFromServerAsync(); } else { await _client.UpdateUserCartForCustomerAsync(new UpdateUserCartForCustomerRequest { CartItemId = existing.cartId, Count = newQuantity }); } } catch { // Best-effort sync with backend; keep local state on failure } } public async Task UpdateQuantity(long productId, int quantity) { // چک لاگین بودن کاربر if (!await IsAuthenticatedAsync()) return; var existing = _items.FirstOrDefault(i => i.ProductId == productId); if (existing is null) return; if (quantity <= 0) { await Remove(existing.cartId); return; } var idx = _items.IndexOf(existing); _items[idx] = existing with { Quantity = quantity }; Notify(); try { await _client.UpdateUserCartForCustomerAsync(new UpdateUserCartForCustomerRequest { CartItemId = existing.cartId, Count = quantity }); } catch { // Best-effort sync with backend; keep local state on failure } } public async Task Remove(long cartId) { // چک لاگین بودن کاربر if (!await IsAuthenticatedAsync()) return; _items.RemoveAll(i => i.cartId == cartId); Notify(); try { // Use dedicated remove endpoint await _client.RemoveUserCartForCustomerAsync(new RemoveUserCartForCustomerRequest { CartItemId = cartId }); } catch { // Best-effort sync with backend; keep local state on failure } } public async Task Clear() { // چک لاگین بودن کاربر if (!await IsAuthenticatedAsync()) return; var productIds = _items.Select(i => i.ProductId).ToList(); _items.Clear(); Notify(); try { foreach (var item in productIds) { await _client.RemoveUserCartForCustomerAsync(new RemoveUserCartForCustomerRequest { CartItemId = item }); } } catch { // Best-effort sync with backend; keep local state on failure } } private void Notify() => OnChange?.Invoke(); /// /// بررسی اینکه کاربر لاگین کرده یا نه /// private async Task IsAuthenticatedAsync() { try { var token = await _localStorage.GetItemAsync(TokenStorageKey); return !string.IsNullOrWhiteSpace(token); } catch { return false; } } /// /// اطمینان از لود شدن سبد خرید - فقط اگر کاربر لاگین کرده باشد /// public async Task EnsureInitializedAsync() { if (_isInitialized) return; if (await IsAuthenticatedAsync()) { await LoadFromServerAsync(); } _isInitialized = true; } private async Task LoadFromServerAsync() { // ابتدا چک کن که کاربر لاگین کرده if (!await IsAuthenticatedAsync()) { return; } try { var response = await _client.GetCustomerCartAsync(new GetUserCartForCustomerRequest()); _items.Clear(); foreach (var model in response.Models) { var item = new CartItem( cartId:model.Id, ProductId: model.ProductId, Title: model.ProductTitle ?? string.Empty, ImageUrl: model.ProductThumbnailPath, UnitPrice: model.ProductPrice, Quantity: model.Count > 0 ? model.Count : 1) { Discount = model.ProductDiscount, Created = model.Created.ToDateTime().MiladiToJalali(), Description = model.ProductShortInfomation }; _items.Add(item); } Notify(); } catch { // If backend is unreachable or user is unauthenticated, fall back to local-only cart. } } }