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

namespace Baya.Application.Features.Bookings.Commands.UpsertCancellationPolicy;

// Admin-only access is enforced by the controller policy.
internal sealed class UpsertCancellationPolicyCommandHandler(IUnitOfWork unitOfWork)
    : IRequestHandler<UpsertCancellationPolicyCommand, OperationResult<CancellationPolicyDto>>
{
    public async ValueTask<OperationResult<CancellationPolicyDto>> Handle(UpsertCancellationPolicyCommand request, CancellationToken cancellationToken)
    {
        var policy = await unitOfWork.CancellationPolicyRepository.GetTrackedByCodeAsync(request.Code, cancellationToken);
        if (policy is null)
        {
            policy = new CancellationPolicy { Code = request.Code };
            await unitOfWork.CancellationPolicyRepository.AddAsync(policy, cancellationToken);
        }

        policy.AppliesTo = request.AppliesTo;
        policy.HoursBeforeStartMin = request.HoursBeforeStartMin;
        policy.HoursBeforeStartMax = request.HoursBeforeStartMax;
        policy.RefundPercentage = request.RefundPercentage;
        policy.FeeAmountIrr = request.FeeAmountIrr;
        policy.FeeRate = request.FeeRate;
        policy.IsActive = request.IsActive;

        await unitOfWork.CommitAsync();

        return OperationResult<CancellationPolicyDto>.SuccessResult(new CancellationPolicyDto(
            policy.Id, policy.Code, policy.AppliesTo, policy.HoursBeforeStartMin, policy.HoursBeforeStartMax,
            policy.RefundPercentage, policy.FeeAmountIrr.ToString(), policy.FeeRate, policy.IsActive));
    }
}
