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

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

internal sealed class GetNurseEarningsQueryHandler(
    ICurrentUser currentUser,
    IUnitOfWork unitOfWork,
    IDateTimeProvider dateTimeProvider)
    : IRequestHandler<GetNurseEarningsQuery, OperationResult<PagedResult<NurseEarningsItemDto>>>
{
    public async ValueTask<OperationResult<PagedResult<NurseEarningsItemDto>>> Handle(GetNurseEarningsQuery request, CancellationToken cancellationToken)
    {
        if (currentUser.UserId is not { } userId)
            return OperationResult<PagedResult<NurseEarningsItemDto>>.UnauthorizedResult("Not authenticated.");

        if (currentUser.Roles?.Contains(RoleNames.Nurse) != true)
            return OperationResult<PagedResult<NurseEarningsItemDto>>.ForbiddenResult("Only a nurse can read their earnings.");

        var nurseId = await unitOfWork.NurseProfileRepository.GetProfileIdByUserIdAsync(userId, cancellationToken);
        if (nurseId is not { } nid)
            return OperationResult<PagedResult<NurseEarningsItemDto>>.NotFoundResult("No nurse profile exists yet.");

        var (page, pageSize) = Pagination.Normalize(request.Page, request.PageSize);
        var now = dateTimeProvider.UtcNow.UtcDateTime;

        var all = await unitOfWork.PayoutRepository.GetNurseEarningsAsync(nid, now, cancellationToken);
        var filtered = string.IsNullOrWhiteSpace(request.State)
            ? all
            : all.Where(e => e.State == request.State).ToList();

        var total = filtered.Count;
        var items = filtered
            .OrderByDescending(e => e.ScheduledDate).ThenByDescending(e => e.BookingId)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToList();

        return OperationResult<PagedResult<NurseEarningsItemDto>>.SuccessResult(
            new PagedResult<NurseEarningsItemDto>(items, total, page, pageSize));
    }
}
