#nullable enable
using Baya.Application.Contracts.Common;
using Baya.Application.Contracts.Persistence;
using Baya.Application.Models.Common;
using Baya.Domain.Entities.Payments;
using Mediator;

namespace Baya.Application.Features.Refunds.Commands.WriteOffClawback;

internal sealed class WriteOffClawbackCommandHandler(
    IUnitOfWork unitOfWork,
    IDateTimeProvider dateTimeProvider)
    : IRequestHandler<WriteOffClawbackCommand, OperationResult<bool>>
{
    public async ValueTask<OperationResult<bool>> Handle(WriteOffClawbackCommand request, CancellationToken cancellationToken)
    {
        var clawback = await unitOfWork.RefundRepository.GetTrackedClawbackByIdAsync(request.ClawbackId, cancellationToken);
        if (clawback is null)
            return OperationResult<bool>.NotFoundResult("Clawback not found.");
        if (!clawback.IsPending)
            return OperationResult<bool>.ConflictResult("Only a pending clawback can be written off.");

        var now = dateTimeProvider.UtcNow.UtcDateTime;
        clawback.WriteOff(request.Reason, now);

        var correction = LedgerPosting.ClawbackWriteOff(
            clawback.BookingId, clawback.NurseId, clawback.AmountIrr, clawback.Id, now);
        await unitOfWork.PaymentRepository.AddLedgerEntriesAsync(correction, cancellationToken);

        await unitOfWork.CommitAsync();
        return OperationResult<bool>.SuccessResult(true);
    }
}
