using CMSMicroservice.Application.Common.Exceptions; using CMSMicroservice.Application.Common.Interfaces; using CMSMicroservice.Domain.Entities; using CMSMicroservice.Domain.Entities.Payment; using CMSMicroservice.Domain.Enums; using Microsoft.EntityFrameworkCore; namespace CMSMicroservice.Application.ManualPaymentCQ.Commands.ProcessManualMembershipPayment; public class ProcessManualMembershipPaymentCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly ICurrentUserService _currentUser; private readonly ILogger _logger; public ProcessManualMembershipPaymentCommandHandler( IApplicationDbContext context, ICurrentUserService currentUser, ILogger logger) { _context = context; _currentUser = currentUser; _logger = logger; } public async Task Handle( ProcessManualMembershipPaymentCommand request, CancellationToken cancellationToken) { try { _logger.LogInformation( "Processing manual membership payment for UserId: {UserId}, Amount: {Amount}", request.UserId, request.Amount); // 1. دریافت شناسه ادمین از کاربر جاری var currentUserId = _currentUser.UserId; if (string.IsNullOrEmpty(currentUserId)) { throw new UnauthorizedAccessException("کاربر احراز هویت نشده است"); } if (!long.TryParse(currentUserId, out var adminUserId)) { throw new UnauthorizedAccessException("شناسه کاربر نامعتبر است"); } // 2. بررسی وجود کاربر var user = await _context.Users .FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken); if (user == null) { _logger.LogError("User not found: {UserId}", request.UserId); throw new NotFoundException($"کاربر با شناسه {request.UserId} یافت نشد"); } // 3. ایجاد ManualPayment با وضعیت Approved var manualPayment = new ManualPayment { UserId = request.UserId, Amount = request.Amount, Type = ManualPaymentType.CashDeposit, Description = request.Description ?? "پرداخت دستی عضویت", ReferenceNumber = request.ReferenceNumber, Status = ManualPaymentStatus.Approved, RequestedBy = adminUserId, ApprovedBy = adminUserId, ApprovedAt = DateTime.Now }; _context.ManualPayments.Add(manualPayment); await _context.SaveChangesAsync(cancellationToken); // 4. پیدا کردن یا ایجاد کیف پول var wallet = await _context.UserWallets .FirstOrDefaultAsync(w => w.UserId == request.UserId, cancellationToken); if (wallet == null) { _logger.LogError("Wallet not found for UserId: {UserId}", request.UserId); throw new NotFoundException($"کیف پول کاربر {request.UserId} یافت نشد"); } // 6. ثبت تراکنش var transaction = new Transaction { Amount = request.Amount, Description = $"پرداخت دستی عضویت - {manualPayment.Description} - مرجع: {request.ReferenceNumber}", PaymentStatus = PaymentStatus.Success, PaymentDate = DateTime.Now, RefId = request.ReferenceNumber, Type = TransactionType.DepositExternal1 }; _context.Transactions.Add(transaction); await _context.SaveChangesAsync(cancellationToken); // 7. اعمال تغییرات بر کیف پول var oldBalance = wallet.Balance; var oldDiscountBalance = wallet.DiscountBalance; wallet.Balance += request.Amount; wallet.DiscountBalance += request.Amount; // 8. ثبت لاگ Balance var balanceLog = new UserWalletChangeLog { WalletId = wallet.Id, CurrentBalance = wallet.Balance, ChangeValue = request.Amount, CurrentNetworkBalance = wallet.NetworkBalance, ChangeNerworkValue = 0, CurrentDiscountBalance = wallet.DiscountBalance, ChangeDiscountValue = request.Amount, IsIncrease = true, RefrenceId = transaction.Id }; await _context.UserWalletChangeLogs.AddAsync(balanceLog, cancellationToken); // 10. به‌روزرسانی ManualPayment با TransactionId manualPayment.TransactionId = transaction.Id; await _context.SaveChangesAsync(cancellationToken); // 11. پیدا کردن یا ایجاد آدرس پیشفرض کاربر var userAddress = await _context.UserAddresses .Where(a => a.UserId == request.UserId) .OrderByDescending(a => a.IsDefault) .ThenBy(a => a.Id) .FirstOrDefaultAsync(cancellationToken); if (userAddress == null) { userAddress = new UserAddress { UserId = request.UserId, Title = "آدرس پیشفرض", Address = "پرداخت دستی عضویت - آدرس موقت", PostalCode = "0000000000", IsDefault = true, CityId = 1 }; await _context.UserAddresses.AddAsync(userAddress, cancellationToken); await _context.SaveChangesAsync(cancellationToken); } // 12. ثبت سفارش var order = new UserOrder { UserId = request.UserId, Amount = request.Amount, TransactionId = transaction.Id, PaymentStatus = PaymentStatus.Success, PaymentDate = DateTime.Now, PaymentMethod = PaymentMethod.Deposit, DeliveryStatus = DeliveryStatus.None, UserAddressId = userAddress.Id, DeliveryDescription = $"پرداخت دستی عضویت - مرجع: {request.ReferenceNumber}" }; _context.UserOrders.Add(order); await _context.SaveChangesAsync(cancellationToken); _logger.LogInformation( "Manual membership payment processed successfully. UserId: {UserId}, Amount: {Amount}, ManualPaymentId: {ManualPaymentId}, TransactionId: {TransactionId}, OrderId: {OrderId}, AdminUserId: {AdminUserId}", request.UserId, request.Amount, manualPayment.Id, transaction.Id, order.Id, adminUserId); return new ProcessManualMembershipPaymentResponseDto { TransactionId = transaction.Id, OrderId = order.Id, NewWalletBalance = wallet.Balance, Message = "پرداخت دستی با موفقیت ثبت شد" }; } catch (Exception ex) when (ex is not NotFoundException) { _logger.LogError(ex, "Error processing manual membership payment for UserId: {UserId}, Amount: {Amount}", request.UserId, request.Amount); throw; } } }