using Microsoft.Extensions.Logging;

namespace CMSMicroservice.Application.CommissionCQ.Commands.ProcessWithdrawal;

public class ProcessWithdrawalCommandHandler : IRequestHandler<ProcessWithdrawalCommand, Unit>
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUser;
    private readonly IPaymentGatewayService _paymentGateway;
    private readonly ILogger<ProcessWithdrawalCommandHandler> _logger;

    public ProcessWithdrawalCommandHandler(
        IApplicationDbContext context,
        ICurrentUserService currentUser,
        IPaymentGatewayService paymentGateway,
        ILogger<ProcessWithdrawalCommandHandler> logger)
    {
        _context = context;
        _currentUser = currentUser;
        _paymentGateway = paymentGateway;
        _logger = logger;
    }

    public async Task<Unit> Handle(ProcessWithdrawalCommand request, CancellationToken cancellationToken)
    {
        var payout = await _context.UserCommissionPayouts
            .Include(x => x.User)
            .FirstOrDefaultAsync(x => x.Id == request.PayoutId, cancellationToken);

        if (payout == null)
        {
            throw new NotFoundException(nameof(UserCommissionPayout), request.PayoutId);
        }

        // بررسی وضعیت
        if (payout.Status != CommissionPayoutStatus.WithdrawRequested)
        {
            throw new InvalidOperationException($"فقط درخواست‌های با وضعیت WithdrawRequested قابل پردازش هستند. وضعیت فعلی: {payout.Status}");
        }

        var oldStatus = payout.Status;
        var now = DateTime.Now;

        if (request.IsApproved)
        {
            // تایید برداشت
            if (payout.WithdrawalMethod == WithdrawalMethod.Diamond)
            {
                // روش Diamond: شارژ کیف پول تخفیف
                var wallet = await _context.UserWallets
                    .FirstOrDefaultAsync(x => x.UserId == payout.UserId, cancellationToken);

                if (wallet != null)
                {
                    wallet.DiscountBalance += payout.TotalAmount;
                    _context.UserWallets.Update(wallet);
                }
                
                payout.Status = CommissionPayoutStatus.Withdrawn;
                payout.WithdrawnAt = now;
            }
            else if (payout.WithdrawalMethod == WithdrawalMethod.Cash)
            {
                // روش انتقال بانکی: فراخوانی Payment Gateway
                try
                {
                    _logger.LogInformation("Processing bank transfer for Payout {PayoutId}, User {UserId}, Amount {Amount}", 
                        payout.Id, payout.UserId, payout.TotalAmount);
                    
                    var payoutRequest = new PayoutRequest
                    {
                        Amount = payout.TotalAmount,
                        UserId = payout.UserId,
                        Iban = payout.IbanNumber ?? throw new InvalidOperationException("شماره شبا یافت نشد"),
                        AccountHolderName = $"{payout.User.FirstName} {payout.User.LastName}",
                        Description = $"برداشت کمیسیون هفته {payout.WeekDefinitionId}",
                        InternalRefId = $"PAYOUT-{payout.Id}"
                    };
                    
                    var payoutResult = await _paymentGateway.ProcessPayoutAsync(payoutRequest, cancellationToken);
                    
                    if (payoutResult.IsSuccess)
                    {
                        payout.Status = CommissionPayoutStatus.Withdrawn;
                        payout.WithdrawnAt = now;
                        payout.BankReferenceId = payoutResult.BankRefId;
                        payout.BankTrackingCode = payoutResult.TrackingCode;
                        
                        _logger.LogInformation("Bank transfer successful: Payout {PayoutId}, BankRef {BankRef}", 
                            payout.Id, payoutResult.BankRefId);
                    }
                    else
                    {
                        // خطا در واریز
                        payout.Status = CommissionPayoutStatus.PaymentFailed;
                        payout.PaymentFailureReason = payoutResult.Message;
                        
                        _logger.LogError("Bank transfer failed: Payout {PayoutId}, Reason: {Reason}", 
                            payout.Id, payoutResult.Message);
                        
                        throw new InvalidOperationException($"خطا در واریز: {payoutResult.Message}");
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Exception during bank transfer for Payout {PayoutId}", payout.Id);
                    
                    payout.Status = CommissionPayoutStatus.PaymentFailed;
                    payout.PaymentFailureReason = ex.Message;
                    
                    throw;
                }
            }

            _context.UserCommissionPayouts.Update(payout);
            await _context.SaveChangesAsync(cancellationToken);

            // ثبت تاریخچه
            var history = new CommissionPayoutHistory
            {
                UserCommissionPayoutId = payout.Id,
                UserId = payout.UserId,
                WeekDefinitionId = payout.WeekDefinitionId,
                AmountBefore = payout.TotalAmount,
                AmountAfter = payout.TotalAmount,
                OldStatus = oldStatus,
                NewStatus = payout.Status,
                Action = CommissionPayoutAction.Withdrawn,
                PerformedBy = _currentUser.UserId ?? "Admin",
                Reason = $"تایید برداشت به روش {payout.WithdrawalMethod}"
            };

            await _context.CommissionPayoutHistories.AddAsync(history, cancellationToken);
        }
        else
        {
            // رد برداشت - برگشت به وضعیت Paid
            payout.Status = CommissionPayoutStatus.Paid;
            payout.WithdrawalMethod = null;
            payout.IbanNumber = null;

            _context.UserCommissionPayouts.Update(payout);
            await _context.SaveChangesAsync(cancellationToken);

            // ثبت تاریخچه
            var history = new CommissionPayoutHistory
            {
                UserCommissionPayoutId = payout.Id,
                UserId = payout.UserId,
                WeekDefinitionId = payout.WeekDefinitionId,
                AmountBefore = payout.TotalAmount,
                AmountAfter = payout.TotalAmount,
                OldStatus = oldStatus,
                NewStatus = CommissionPayoutStatus.Paid,
                Action = CommissionPayoutAction.Cancelled,
                PerformedBy = _currentUser.UserId ?? "Admin",
                Reason = request.Reason ?? "درخواست برداشت رد شد"
            };

            await _context.CommissionPayoutHistories.AddAsync(history, cancellationToken);
        }

        await _context.SaveChangesAsync(cancellationToken);

        return Unit.Value;
    }
}
