using CMSMicroservice.Application.Common.Exceptions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Entities.Payment;
using CMSMicroservice.Domain.Enums;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace CMSMicroservice.Application.ManualPaymentCQ.Commands.RejectManualPayment;

public class RejectManualPaymentCommandHandler : IRequestHandler<RejectManualPaymentCommand, bool>
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUser;
    private readonly ILogger<RejectManualPaymentCommandHandler> _logger;

    public RejectManualPaymentCommandHandler(
        IApplicationDbContext context,
        ICurrentUserService currentUser,
        ILogger<RejectManualPaymentCommandHandler> logger)
    {
        _context = context;
        _currentUser = currentUser;
        _logger = logger;
    }

    public async Task<bool> Handle(
        RejectManualPaymentCommand request,
        CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogInformation(
                "Rejecting manual payment: {ManualPaymentId}",
                request.ManualPaymentId
            );

            // 1. پیدا کردن ManualPayment
            var manualPayment = await _context.ManualPayments
                .FirstOrDefaultAsync(m => m.Id == request.ManualPaymentId, cancellationToken);

            if (manualPayment == null)
            {
                _logger.LogWarning("ManualPayment not found: {Id}", request.ManualPaymentId);
                throw new NotFoundException(nameof(ManualPayment), request.ManualPaymentId);
            }

            // 2. بررسی وضعیت
            if (manualPayment.Status != ManualPaymentStatus.Pending)
            {
                _logger.LogWarning(
                    "ManualPayment {Id} is not in Pending status: {Status}",
                    request.ManualPaymentId,
                    manualPayment.Status
                );
                throw new BadRequestException($"فقط درخواست‌های در وضعیت Pending قابل رد هستند. وضعیت فعلی: {manualPayment.Status}");
            }

            // 3. بررسی SuperAdmin
            var currentUserId = _currentUser.UserId;
            if (string.IsNullOrEmpty(currentUserId))
            {
                throw new UnauthorizedAccessException("کاربر احراز هویت نشده است");
            }

            if (!long.TryParse(currentUserId, out var rejectedById))
            {
                throw new UnauthorizedAccessException("شناسه کاربر نامعتبر است");
            }

            // 4. رد درخواست
            manualPayment.Status = ManualPaymentStatus.Rejected;
            manualPayment.ApprovedBy = rejectedById;
            manualPayment.ApprovedAt = DateTime.Now;
            manualPayment.RejectionReason = request.RejectionReason;

            await _context.SaveChangesAsync(cancellationToken);

            _logger.LogInformation(
                "Manual payment rejected successfully. Id: {Id}, RejectedBy: {RejectedBy}, Reason: {Reason}",
                manualPayment.Id,
                rejectedById,
                request.RejectionReason
            );

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(
                ex,
                "Error rejecting manual payment: {ManualPaymentId}",
                request.ManualPaymentId
            );
            throw;
        }
    }
}
