package com.red.circle.other.app.command.game.vote;

import com.google.common.collect.Lists;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.other.app.dto.clientobject.game.GameRoomVoteCO;
import com.red.circle.other.app.dto.cmd.game.vote.GameRoomVoteCmd;
import com.red.circle.other.infra.database.cache.service.other.GameRoomVoteCacheService;
import com.red.circle.other.infra.database.rds.service.game.GameRoomVoteRecordService;
import com.red.circle.other.inner.asserts.GameErrorCode;
import com.red.circle.tool.core.json.JacksonUtils;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 用户投票.
 *
 * @author pengshigang
 * @since 2022-01-05
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GameRoomVoteCmdExe {

  private final GameRoomVoteCacheService gameRoomVoteCacheService;
  private final GameRoomVoteRecordService gameRoomVoteRecordService;

  public void execute(GameRoomVoteCmd cmd) {

    ResponseAssert.isFalse(GameErrorCode.GAME_OVER, isGameOver(cmd));
    ResponseAssert.isFalse(GameErrorCode.NOT_REPEATEDLY_VOTE_ERROR, isVoted(cmd));
    ResponseAssert.notEmpty(CommonErrorCode.REQUIRED_FIELDS_CANNOT_BE_IGNORED, cmd.getOptionIds());

    GameRoomVoteCO roomVote = getCacheRoomVote(cmd);
    ResponseAssert.notNull(GameErrorCode.NO_GAME_RECORD_FOUND, roomVote);
    ResponseAssert.notEmpty(GameErrorCode.NO_GAME_RECORD_FOUND, roomVote.getOptions());
    if (roomVote.getSingleChoice()) {
      ResponseAssert.isFalse(CommonErrorCode.NOT_ACCEPT_REQUEST, cmd.getOptionIds().size() > 1);
    }

    List<Long> optionIds = Lists.newArrayList();
    roomVote.getOptions().forEach(option -> {
      if (cmd.getOptionIds().contains(option.getId())) {
        option.setVotes(gameRoomVoteCacheService.getOptionVotes(roomVote.getId(), option.getId()));
        optionIds.add(option.getId());
      }
    });

    gameRoomVoteCacheService.cacheUserVoteOptionIds(roomVote.getId(), cmd.requiredReqUserId(),
        JacksonUtils.toJson(optionIds));
    gameRoomVoteCacheService.cacheRoomVote(roomVote.getId(), JacksonUtils.toJson(roomVote));
    gameRoomVoteCacheService.cacheSignUserVote(roomVote.getId(), cmd.requiredReqUserId());

  }

  private GameRoomVoteCO getCacheRoomVote(GameRoomVoteCmd cmd) {
    return gameRoomVoteCacheService.getRoomVote(cmd.getGameId(), GameRoomVoteCO.class);
  }

  private Boolean isVoted(GameRoomVoteCmd cmd) {
    return gameRoomVoteCacheService.getSignUserVote(cmd.getGameId(), cmd.requiredReqUserId());
  }

  private Boolean isGameOver(GameRoomVoteCmd cmd) {
    return gameRoomVoteRecordService.isOver(cmd.getRoomId(), cmd.getGameId());
  }

}
