public async Task <IActionResult> PlayCard(Guid gameId, [FromBody] DtoPlayCardMove move)
        {
            var result = await this.gamesService.PlayCard(gameId, move).ConfigureAwait(false);

            return(this.utility.GetActionResult(result));
        }
        public async Task <VoidAppResult> PlayCard(Guid gameId, DtoPlayCardMove move, CancellationToken cancellationToken = default(CancellationToken))
        {
            var game = await this.dbContext.Games.IncludeUserParticipations().IncludeEntities().SingleOrDefaultAsync(_ => _.Id == gameId, cancellationToken);

            if (game == null)
            {
                return(VoidAppResult.Error(ErrorPreset.OnLoadingData));
            }
            var currentTurnPlayerResult = await this.GetCurrentTurnPlayer(game, cancellationToken);

            if (currentTurnPlayerResult.IsErrorResult)
            {
                return(currentTurnPlayerResult.GetVoidAppResult());
            }
            var currentTurnPlayer = currentTurnPlayerResult.SuccessReturnValue;

            var playedGameCard = await this.dbContext.GameCards.IncludeCards().SingleOrDefaultAsync(_ => _.Id == move.CardId);

            if (playedGameCard == null || playedGameCard.CardLocation != CardLocation.Hand)
            {
                return(VoidAppResult.Error(AppActionResultType.RuleError, "Selected card cannot be played."));
            }

            if (currentTurnPlayer.Mail != this.loginManager.LoggedInUser.Mail)
            {
                return(VoidAppResult.Error(ErrorPreset.NotYourTurn));
            }

            if (game.UserParticipations.All(_ => _.Mail != this.loginManager.LoggedInUser.Mail))
            {
                return(VoidAppResult.Error(ErrorPreset.NotAParticipant));
            }

            playedGameCard.CardLocation = CardLocation.Board;

            // Discard cards
            if (playedGameCard.Card.Cost != move.DiscardedCardIds.Count)
            {
                return(VoidAppResult.Error(AppActionResultType.RuleError, $"You must discard exactly {playedGameCard.Card.Cost} cards."));
            }
            foreach (var entityId in move.DiscardedCardIds)
            {
                var gameCard = game.Entities.SingleOrDefault(_ => _.Id == entityId) as GameCard;
                if (gameCard == null || gameCard.CardLocation != CardLocation.Hand)
                {
                    return(VoidAppResult.Error(AppActionResultType.RuleError, "The selected card cannot be discarded."));
                }
                gameCard.CardLocation = CardLocation.OutOfPlay;
            }

            // Execute effects
            foreach (var effect in move.EffectTargets)
            {
                var executeEffectResult = await this.effectsService.ExecuteEffect(effect, game, currentTurnPlayer, cancellationToken);

                if (executeEffectResult.IsErrorResult)
                {
                    return(executeEffectResult);
                }
            }

            await dbContext.SaveChangesAsync(cancellationToken);

            return(VoidAppResult.Success());
        }