using CMSMicroservice.Domain.Events;
using CMSMicroservice.Domain.Enums;

namespace CMSMicroservice.Application.TransactionsCQ.Commands.RefundTransaction;

public class RefundTransactionCommandHandler : IRequestHandler<RefundTransactionCommand, RefundTransactionResponseDto>
{
    private readonly IApplicationDbContext _context;

    public RefundTransactionCommandHandler(IApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<RefundTransactionResponseDto> Handle(RefundTransactionCommand request, CancellationToken cancellationToken)
    {
        // پیدا کردن تراکنش اصلی
        var originalTransaction = await _context.Transactions
            .FirstOrDefaultAsync(t => t.Id == request.TransactionId, cancellationToken);
        
        if (originalTransaction == null)
        {
            throw new NotFoundException(nameof(Transaction), request.TransactionId);
        }
        
        // چک کردن که تراکنش Success باشد
        if (originalTransaction.PaymentStatus != PaymentStatus.Success)
        {
            throw new InvalidOperationException($"فقط تراکنش‌های موفق قابل استرداد هستند. وضعیت فعلی: {originalTransaction.PaymentStatus}");
        }
        
        // محاسبه مبلغ استرداد
        var refundAmount = request.RefundAmount ?? originalTransaction.Amount;
        
        if (refundAmount > originalTransaction.Amount)
        {
            throw new InvalidOperationException("مبلغ استرداد نمی‌تواند بیشتر از مبلغ اصلی باشد");
        }
        
        // ایجاد تراکنش استرداد جدید
        var refundTransaction = new Transaction
        {
            Amount = -refundAmount, // مبلغ منفی برای استرداد
            Description = $"استرداد تراکنش {request.TransactionId}: {request.RefundReason}",
            PaymentStatus = PaymentStatus.Success,
            PaymentDate = DateTime.Now,
            RefId = $"REFUND-{originalTransaction.RefId}",
            Type = TransactionType.Buy // یا می‌تونیم یک نوع جدید برای Refund تعریف کنیم
        };
        
        await _context.Transactions.AddAsync(refundTransaction, cancellationToken);
        refundTransaction.AddDomainEvent(new RefundTransactionEvent(refundTransaction, originalTransaction));
        
        await _context.SaveChangesAsync(cancellationToken);
        
        return new RefundTransactionResponseDto
        {
            OriginalTransactionId = originalTransaction.Id,
            RefundTransactionId = refundTransaction.Id,
            RefundAmount = refundAmount,
            Message = "استرداد با موفقیت انجام شد"
        };
    }
}
