using CMSMicroservice.Protobuf.Protos.UserAddress; using CMSMicroservice.Protobuf.Protos.UserOrder; using FrontOffice.Main.Shared; using FrontOffice.Main.Utilities; using Microsoft.AspNetCore.Components; using MudBlazor; using Messages = CMSMicroservice.Protobuf.Protos; namespace FrontOffice.Main.Pages.Store; public partial class CheckoutSummary : ComponentBase { [Inject] private CartService Cart { get; set; } = default!; [Inject] private OrderService OrderService { get; set; } = default!; [Inject] private VATService VAT { get; set; } = default!; [Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!; [Inject] private UserOrderContract.UserOrderContractClient UserOrderContract { get; set; } = default!; [Inject] private AuthDialogService AuthDialogService { get; set; } = default!; [Inject] private AuthService AuthService { get; set; } = default!; // Snackbar and Navigation are injected via _Imports.razor private List _addresses = new(); private CustomerAddressModel? _selectedAddress; private bool _loadingAddresses; private long walletBalance; private Messages.PaymentMethod _payment = Messages.PaymentMethod.Wallet; private bool CanPlaceOrder => Cart.Items.Count > 0 && _selectedAddress != null; protected override async Task OnInitializedAsync() { if (!await AuthService.IsAuthenticatedAsync()) { await AuthDialogService.ShowAuthDialogAsync(); } await Cart.EnsureInitializedAsync(); await LoadAddresses(); await LoadWalletBalance(); } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await VAT.LoadAsync(); } await base.OnAfterRenderAsync(firstRender); } private async Task LoadWalletBalance() { var walletResult = await WalletService.GetBalancesAsync(); walletBalance = walletResult.CreditBalance; } private async Task LoadAddresses() { _loadingAddresses = true; try { var response = await UserAddressContract.GetCustomerAddressesAsync(new()); if (response?.Models?.Any() == true) { _addresses = response.Models.ToList(); _selectedAddress = _addresses.FirstOrDefault(a => a.IsDefault) ?? _addresses.First(); } else { _addresses = new(); } } catch (Exception ex) { Snackbar.Add($"خطا در بارگذاری آدرس‌ها: {ex.Message}", Severity.Error); _addresses = new(); } finally { _loadingAddresses = false; await InvokeAsync(StateHasChanged); } } private async Task PlaceOrder() { if (!CanPlaceOrder || _selectedAddress is null) { Snackbar.Add("لطفاً آدرس را انتخاب کنید و سبد خرید را بررسی کنید.", Severity.Warning); return; } var totalRequired = VAT.AddVAT(Cart.Total); if (await TryHandleInsufficientBalanceAsync(totalRequired)) return; try { var request = new SubmitShopBuyOrderRequest { TotalAmount = totalRequired }; var response = await UserOrderContract.SubmitShopBuyOrderAsync(request); await Cart.Clear(); Snackbar.Add("سفارش با موفقیت ثبت شد.", Severity.Success); Navigation.NavigateTo($"{RouteConstants.Store.OrderDetail}{response.Id}"); } catch (Exception ex) { if (CreditChargeNavigation.IsInsufficientWalletBalance(ex)) { await LoadWalletBalance(); await TryHandleInsufficientBalanceAsync(totalRequired); return; } Snackbar.Add($"خطا در ثبت سفارش: {ex.Message}", Severity.Error); } } private async Task TryHandleInsufficientBalanceAsync(long totalRequired) { if (walletBalance >= totalRequired) return false; var shortfall = totalRequired - walletBalance; var parameters = new DialogParameters { { x => x.CurrentBalance, walletBalance }, { x => x.RequiredAmount, totalRequired }, { x => x.ShortfallAmount, shortfall } }; var dialog = await DialogService.ShowAsync( "موجودی کافی نیست", parameters, new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small, FullWidth = true }); var result = await dialog.Result; if (result is { Canceled: false } && result.Data is long chargeShortfall) { var chargeAmount = CreditChargeNavigation.NormalizeChargeAmount(chargeShortfall); Navigation.NavigateTo(CreditChargeNavigation.BuildChargeUrl( chargeAmount, RouteConstants.Store.CheckoutSummary)); } return true; } private static string FormatPrice(long price) => string.Format("{0:N0} تومان", price); private long CalculateVAT() => VAT.CalculateVAT(Cart.Total); private static string GetProductImageUrl(string? imageUrl) => string.IsNullOrWhiteSpace(imageUrl) ? "/images/product-placeholder.svg" : imageUrl.TrimStart('/'); }