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

namespace Baya.Application.Features.Messaging.Commands.RemoveParticipant;

/// <summary>Soft-removes a participant (staff on any ticket, or the ticket owner). The unique row survives so a
/// later re-add resurrects it.</summary>
internal sealed class RemoveParticipantCommandHandler(
    ICurrentUser currentUser,
    IUnitOfWork unitOfWork,
    IDateTimeProvider dateTimeProvider)
    : IRequestHandler<RemoveParticipantCommand, OperationResult<bool>>
{
    public async ValueTask<OperationResult<bool>> Handle(RemoveParticipantCommand request, CancellationToken cancellationToken)
    {
        if (currentUser.UserId is not { } callerId)
            return OperationResult<bool>.UnauthorizedResult("Not authenticated.");

        var header = await unitOfWork.TicketRepository.GetHeaderAsync(request.TicketId, cancellationToken);
        if (header is null)
            return OperationResult<bool>.NotFoundResult("Ticket not found.");

        if (!StaffRoles.IsStaff(currentUser.Roles) && header.OpenedById != callerId)
            return OperationResult<bool>.ForbiddenResult("Only staff or the ticket owner can manage participants.");

        var participant = await unitOfWork.TicketRepository.GetParticipantAsync(request.TicketId, request.UserId, cancellationToken);
        if (participant is null || !participant.IsActive)
            return OperationResult<bool>.NotFoundResult("That user is not an active participant on this ticket.");

        participant.Remove(dateTimeProvider.UtcNow);
        await unitOfWork.CommitAsync();

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