#nullable enable
using Baya.Application.Contracts.Common;
using Baya.Application.Contracts.Configuration;
using Baya.Application.Contracts.Holidays;
using Baya.Application.Contracts.Persistence;
using Baya.Application.Models.Common;
using Baya.Application.Models.Payouts;
using Mediator;

namespace Baya.Application.Features.Payouts.Queries.ComputeEligibleEarnings;

internal sealed class ComputeEligibleEarningsQueryHandler(
    IUnitOfWork unitOfWork,
    IHolidayCalendar holidays,
    IPlatformConfig platformConfig,
    IDateTimeProvider dateTimeProvider)
    : IRequestHandler<ComputeEligibleEarningsQuery, OperationResult<PagedResult<EligibleNurseEarningsDto>>>
{
    public async ValueTask<OperationResult<PagedResult<EligibleNurseEarningsDto>>> Handle(
        ComputeEligibleEarningsQuery request, CancellationToken cancellationToken)
    {
        var page = request.Page < 1 ? 1 : request.Page;
        var pageSize = request.PageSize is < 1 or > 100 ? 20 : request.PageSize;
        var now = dateTimeProvider.UtcNow.UtcDateTime;

        // Preview the exact set a generate would take — the period end is holiday-shifted the same way.
        var periodEnd = await holidays.NextBusinessDay(request.PeriodEnd, cancellationToken);
        var requireBnplSettlement = await platformConfig.GetConfig<bool>("require_bnpl_settlement_for_payout", cancellationToken);

        var result = await unitOfWork.PayoutRepository.GetEligiblePreviewAsync(
            request.PeriodStart, periodEnd, now, requireBnplSettlement, page, pageSize, cancellationToken);

        return OperationResult<PagedResult<EligibleNurseEarningsDto>>.SuccessResult(result);
    }
}
