private async Task <CurrentProjectState> ClearGuestSessionState(Guid principalId)
        {
            var guestContext = await _projectGuestContextService.GetProjectGuestContextAsync();

            if (guestContext == null || guestContext.GuestSessionId == Guid.Empty)
            {
                return(new CurrentProjectState
                {
                    Message = "No guest session from which to clear the current project."
                });
            }

            var guestSessionRequest = new UpdateGuestSessionStateRequest
            {
                GuestSessionId    = guestContext.GuestSessionId,
                GuestSessionState = InternalApi.Enums.GuestState.Ended
            };

            var guestSessionStateResponse = await _guestSessionController.UpdateGuestSessionStateAsync(guestSessionRequest, principalId);

            if (guestSessionStateResponse.ResultCode == UpdateGuestSessionStateResultCodes.Success)
            {
                return(new CurrentProjectState()
                {
                    Message = "Cleared current project and ended guest session."
                });
            }

            throw new InvalidOperationException($"Could not clear the current project or end the guest session. {guestSessionStateResponse.Message}");
        }
        public async Task <UpdateGuestSessionStateResponse> UpdateGuestSessionStateAsync(UpdateGuestSessionStateRequest request, Guid principalId)
        {
            var result = new UpdateGuestSessionStateResponse
            {
                ResultCode = UpdateGuestSessionStateResultCodes.Failed
            };

            const string failedToUpdateGuestSession = "Failed to update guest session.";
            GuestSession currentGuestSession;

            try
            {
                currentGuestSession = await _guestSessionRepository.GetItemAsync(request.GuestSessionId);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"{failedToUpdateGuestSession} Failed to get guest session.", ex);
            }

            if (currentGuestSession.GuestSessionState == GuestState.Ended && request.GuestSessionState != GuestState.Ended)
            {
                result.ResultCode = UpdateGuestSessionStateResultCodes.SessionEnded;
                result.Message    = $"{failedToUpdateGuestSession} Can\'t update a guest session that is already ended.";
                return(result);
            }

            if (currentGuestSession.GuestSessionState == request.GuestSessionState)
            {
                result.ResultCode   = UpdateGuestSessionStateResultCodes.SameAsCurrent;
                result.Message      = $"{failedToUpdateGuestSession} The guest session is already in that state.";
                result.GuestSession = currentGuestSession;
                return(result);
            }

            var projectResponse = await _serviceToServiceProjectApi.GetProjectByIdAsync(currentGuestSession.ProjectId);

            if (projectResponse.ResponseCode == HttpStatusCode.NotFound)
            {
                _logger.Error($"Failed to obtain GuestSession {request.GuestSessionId}. Could not find the project associated with this guest session.");
                result.Message = $"{failedToUpdateGuestSession}  Could not find the project associated with this guest session.";
                return(result);
            }

            if (!projectResponse.IsSuccess() || projectResponse.Payload == null)
            {
                _logger.Error($"Failed to obtain GuestSession {request.GuestSessionId}. Could not retrieve the project associated with this guest session. {projectResponse.ResponseCode} - {projectResponse.ReasonPhrase}");
                result.Message = $"{failedToUpdateGuestSession}  Could not find the project associated with this guest session.";
                return(result);
            }

            var project = projectResponse.Payload;

            if (project.GuestAccessCode != currentGuestSession.ProjectAccessCode && request.GuestSessionState != GuestState.Ended)
            {
                result.ResultCode = UpdateGuestSessionStateResultCodes.SessionEnded;
                result.Message    = $"{failedToUpdateGuestSession}  Guest access code has changed.";
                return(result);
            }

            var availableGuestCount = await GetAvailableGuestCountAsync(currentGuestSession.ProjectId, project.GuestAccessCode);

            if (request.GuestSessionState == GuestState.InProject && availableGuestCount < 1)
            {
                result.ResultCode = UpdateGuestSessionStateResultCodes.ProjectFull;
                result.Message    = $"{failedToUpdateGuestSession}  Can\'t admit a guest into a full project.";
                await UpdateProjectLobbyStateAsync(project.Id, LobbyState.GuestLimitReached);

                return(result);
            }

            var previousSessionState = currentGuestSession.GuestSessionState;

            currentGuestSession.GuestSessionState = request.GuestSessionState;

            var guestSession = await UpdateGuestSessionAsync(currentGuestSession, principalId);

            if (guestSession.GuestSessionState == GuestState.InProject && availableGuestCount == 1)
            {
                await UpdateProjectLobbyStateAsync(project.Id, LobbyState.GuestLimitReached);
            }
            else if (previousSessionState == GuestState.InProject && request.GuestSessionState != GuestState.InProject && availableGuestCount == 0)
            {
                await UpdateProjectLobbyStateAsync(project.Id, LobbyState.Normal);
            }

            result.GuestSession = guestSession;
            result.Message      = "Guest session state updated.";
            result.ResultCode   = UpdateGuestSessionStateResultCodes.Success;

            return(result);
        }