using Netina.Domain.Entities.Accounting;

namespace Netina.Repository.Handlers.Accounting;

public class CreateOrUpdatePaymentCommandHandler(IRepositoryWrapper repositoryWrapper)
    : IRequestHandler<CreateOrUpdatePaymentCommand, bool>
{
    public async Task<bool> Handle(CreateOrUpdatePaymentCommand request, CancellationToken cancellationToken)
    {
        if (request.Id != null)
        {
            var ent = await repositoryWrapper.SetRepository<Payment>()
                .TableNoTracking
                .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);
            if (ent == null)
                throw new AppException("Payment not found", ApiResultStatusCode.NotFound);

            var newEnt = Payment.Create(request.FactorNumber, request.Amount, request.Description, request.TransactionCode,
                request.CardPan, request.Authority, request.Type, request.Status, request.OrderId, request.UserId);
            newEnt.Id = ent.Id;
            newEnt.CreatedAt = ent.CreatedAt == DateTime.MinValue ? DateTime.Now : ent.CreatedAt;
            newEnt.CreatedBy = ent.CreatedBy;

            repositoryWrapper.SetRepository<Payment>()
                .Update(newEnt);

            await repositoryWrapper.SaveChangesAsync(cancellationToken);
        }
        else
        {
            var orderPayment = await repositoryWrapper.SetRepository<Payment>()
                .TableNoTracking
                .FirstOrDefaultAsync(p => p.OrderId == request.OrderId && p.Type == request.Type,cancellationToken);
            if (orderPayment != null)
            {
                var newEnt = Payment.Create(request.FactorNumber, request.Amount, request.Description, request.TransactionCode,
                    request.CardPan, request.Authority, request.Type, request.Status, request.OrderId, request.UserId);
                newEnt.Id = orderPayment.Id;
                newEnt.CreatedAt = orderPayment.CreatedAt == DateTime.MinValue ? DateTime.Now : orderPayment.CreatedAt;
                newEnt.CreatedBy = orderPayment.CreatedBy;
                
                repositoryWrapper.SetRepository<Payment>()
                    .Update(newEnt);

                await repositoryWrapper.SaveChangesAsync(cancellationToken);
            }
            else
            {
                var payment = Payment.Create(request.FactorNumber, request.Amount, request.Description, request.TransactionCode,
                    request.CardPan, request.Authority, request.Type, request.Status, request.OrderId, request.UserId);

                repositoryWrapper.SetRepository<Payment>()
                    .Add(payment);

                await repositoryWrapper.SaveChangesAsync(cancellationToken);
            }
        }
        return true;
    }
}