using DateTimeConverterCL; using CMSMicroservice.Protobuf.Protos.UserWallet; using CMSMicroservice.Protobuf.Protos.UserWalletChangeLog; using Google.Protobuf.WellKnownTypes; namespace FrontOffice.Main.Utilities; public record WalletBalances(long CreditBalance, long DiscountBalance, long NetworkBalance); public record WalletTransaction( string Date, long CreditChange, long CreditBalance, long NetworkChange, long NetworkBalance, long DiscountChange, long DiscountBalance, string Channel, string Description ); public record WalletWithdrawal(long Id, long WeekDefinitionId, string WeekDisplayName, long Amount, int Status, int? Method, string? Iban, string Created); public enum WithdrawalMethodClient { Cash = 0, Diamond = 1 } public record WithdrawalSettings(long MinWithdrawalAmount); public class WalletService { private readonly CMSMicroservice.Protobuf.Protos.UserWallet.UserWalletContract.UserWalletContractClient _client; public WalletService(CMSMicroservice.Protobuf.Protos.UserWallet.UserWalletContract.UserWalletContractClient client) { _client = client; } public async Task GetBalancesAsync() { try { var response = await _client.GetCustomerWalletAsync(new Empty()); return new WalletBalances(response.Balance, response.DiscountBalance, response.NetworkBalance); } catch { // Return zero balances if backend is unavailable return new WalletBalances(0, 0, 0); } } public async Task> GetTransactionsAsync(long? referenceId = null, bool? isIncrease = null) { try { var request = new GetCustomerWalletChangeLogRequest(); if (referenceId.HasValue) { request.ReferenceId = referenceId.Value; } if (isIncrease.HasValue) { request.IsIncrease = isIncrease.Value; } var response = await _client.GetCustomerWalletChangeLogAsync(request); return response.Models .Select(log => new WalletTransaction( ResolveTransactionDate(log), log.ChangeValue, log.CurrentBalance, log.ChangeNerworkValue, log.CurrentNetworkBalance, log.ChangeDiscountValue, log.CurrentDiscountBalance, log.RefrenceId?.ToString() ?? "-", ResolveDescription(log) )) .OrderByDescending(t => t.Date) .ToList(); } catch { // Return empty list if backend is unavailable return new List(); } } private static string ResolveTransactionDate(CustomerWalletChangeLogModel model) { if (model.CreatedAt is not null) { try { var utcDate = model.CreatedAt.ToDateTime(); return utcDate.ToLocalTime().MiladiToJalaliWithTime(); } catch { // ignore conversion issues and fall through to default } } return DateTime.Now.MiladiToJalaliWithTime(); } private static string ResolveDescription(CustomerWalletChangeLogModel model) { var parts = new List(); if (model.ChangeValue != 0) parts.Add(model.ChangeValue > 0 ? "شارژ عادی" : "برداشت عادی"); if (model.ChangeNerworkValue != 0) parts.Add(model.ChangeNerworkValue > 0 ? "دریافت شبکه" : "برداشت شبکه"); if (model.ChangeDiscountValue != 0) parts.Add(model.ChangeDiscountValue > 0 ? "شارژ اعتباری" : "خرید اعتباری"); return parts.Count > 0 ? string.Join(" | ", parts) : "تراکنش کیف پول"; } public async Task RequestWithdrawalAsync(long payoutId, WithdrawalMethodClient method, string? iban) { var request = new CustomerWithdrawBalanceRequest { PayoutId = payoutId, WithdrawalMethod = (int)method }; if (!string.IsNullOrWhiteSpace(iban)) { request.IbanNumber = iban; } try { await _client.CustomerWithdrawBalanceAsync(request); return true; } catch (Grpc.Core.RpcException ex) { throw new InvalidOperationException(ex.Status.Detail ?? "خطا در ثبت برداشت", ex); } } public async Task> GetWithdrawalsAsync(int? status = null) { try { var request = new GetCustomerWithdrawalsRequest(); if (status.HasValue) { request.Status = status.Value; } var response = await _client.GetCustomerWithdrawalsAsync(request); return response.Models .Select(m => new WalletWithdrawal( m.Id, m.WeekDefinitionId, m.WeekDisplayName, m.TotalAmount, m.Status, m.WithdrawalMethod, m.IbanNumber, m.Created?.ToDateTime().MiladiToJalaliWithTime() ?? "-")) .ToList(); } catch { return new List(); } } public async Task GetWithdrawalSettingsAsync() { try { var response = await _client.GetCustomerWithdrawalSettingsAsync(new Empty()); return new WithdrawalSettings(response.MinWithdrawalAmount); } catch { // Return default settings if backend is unavailable return new WithdrawalSettings(0); } } }