public Mono<HandleHandleGroupInvitationResult> authAndHandleInvitation(
            @NotNull Long requesterId,
            @NotNull Long invitationId,
            @NotNull @ValidResponseAction ResponseAction action,
            @Nullable String reason) {
        try {
            Validator.notNull(requesterId, "requesterId");
            Validator.notNull(invitationId, "invitationId");
            Validator.notNull(action, "action");
            DataValidator.validResponseAction(action);
            Validator.maxLength(reason, "reason", maxResponseReasonLength);
        } catch (ResponseException e) {
            return Mono.error(e);
        }
        return queryInviteeIdAndGroupIdAndCreationDateAndStatusByInvitationId(invitationId)
                // If the requester is not authorized to the invitation,
                // they should not know the status of the invitation from the error code.
                // So we should not tell if the invitation exists or not.
                .switchIfEmpty(Mono.error(ResponseException
                        .get(ResponseStatusCode.NOT_INVITEE_TO_UPDATE_GROUP_INVITATION)))
                .flatMap(invitation -> {
                    // If the requester is not authorized to the invitation,
                    // they should not know the status of the invitation from the error code.
                    // So we check whether the requester is authorized first.
                    if (!invitation.getInviteeId()
                            .equals(requesterId)) {
                        return Mono.error(ResponseException
                                .get(ResponseStatusCode.NOT_INVITEE_TO_UPDATE_GROUP_INVITATION));
                    }
                    RequestStatus status = invitation.getStatus();
                    if (status == RequestStatus.PENDING) {
                        if (groupInvitationRepository.isExpired(invitation.getCreationDate()
                                .getTime())) {
                            return Mono.error(ResponseException.get(
                                    ResponseStatusCode.UPDATE_NON_PENDING_GROUP_INVITATION,
                                    "The invitation is under the status "
                                            + RequestStatus.EXPIRED));
                        }
                    } else {
                        return Mono.error(ResponseException.get(
                                ResponseStatusCode.UPDATE_NON_PENDING_GROUP_INVITATION,
                                "The invitation is under the status "
                                        + status));
                    }
                    return switch (action) {
                        case ACCEPT -> groupInvitationRepository
                                .inTransaction(session -> updatePendingInvitationStatus(
                                        invitation.getGroupId(),
                                        invitationId,
                                        RequestStatus.ACCEPTED,
                                        reason,
                                        session)
                                        .then(groupMemberService
                                                .addGroupMember(invitation.getGroupId(),
                                                        requesterId,
                                                        GroupMemberRole.MEMBER,
                                                        null,
                                                        null,
                                                        null,
                                                        session)
                                                .thenReturn(new HandleHandleGroupInvitationResult(
                                                        invitation,
                                                        true))
                                                .onErrorResume(DuplicateKeyException.class,
                                                        e -> Mono.just(
                                                                new HandleHandleGroupInvitationResult(
                                                                        invitation,
                                                                        false)))))
                                .retryWhen(TRANSACTION_RETRY);
                        case IGNORE -> updatePendingInvitationStatus(invitation
                                .getGroupId(), invitationId, RequestStatus.IGNORED, reason, null)
                                .thenReturn(
                                        new HandleHandleGroupInvitationResult(invitation, false));
                        case DECLINE -> updatePendingInvitationStatus(invitation
                                .getGroupId(), invitationId, RequestStatus.DECLINED, reason, null)
                                .thenReturn(
                                        new HandleHandleGroupInvitationResult(invitation, false));
                        default ->
                            Mono.error(ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
                                    "The response action must not be UNRECOGNIZED"));
                    };
                });
    }
@return group ID, invitee ID, and status
turms-service/src/main/java/im/turms/service/domain/group/service/GroupInvitationService.java