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

import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.mq.business.model.event.game.GameTurntableEvent;
import com.red.circle.mq.rocket.business.producer.GameMqMessage;
import com.red.circle.other.app.convertor.game.GameTurntableConvertor;
import com.red.circle.other.app.dto.clientobject.game.RoomTurntableGameCO;
import com.red.circle.other.app.dto.cmd.game.GameTurntableCreateCmd;
import com.red.circle.other.infra.database.cache.key.GameListKeys;
import com.red.circle.other.infra.database.cache.service.other.MarkCacheService;
import com.red.circle.other.infra.database.mongo.entity.game.turntable.RoomTurntableGame;
import com.red.circle.other.infra.database.mongo.service.game.RoomTurntableGameMongoService;
import com.red.circle.other.infra.database.rds.entity.game.GameTurntableRecord;
import com.red.circle.other.infra.database.rds.service.game.GameTurntableRecordService;
import com.red.circle.other.infra.enums.game.TurntableGameStatus;
import com.red.circle.other.inner.asserts.RoomErrorCode;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 发起转盘游戏.
 *
 * @author houyong on 2021/2/1
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class GameTurntableCreateCmdExe {

  private final GameMqMessage gameMqMessage;
  private final MarkCacheService markCacheService;
  private final GameTurntableConvertor gameTurntableConvertor;
  private final GameTurntableRecordService gameTurntableRecordService;
  private final RoomTurntableGameMongoService roomTurntableGameMongoService;

  /**
   * 创建游戏.
   *
   * @param cmd cmd
   * @return ignore
   */
  public RoomTurntableGameCO execute(GameTurntableCreateCmd cmd) {
    // 游戏已被创建
    ResponseAssert.isTrue(RoomErrorCode.GAME_IS_CREATE, markCacheService
        .setIfAbsent(GameListKeys.getKey("GAME_TURNTABLE", String.valueOf(cmd.getRoomId())), 15,
            TimeUnit.SECONDS));

    // 9101 游戏已被创建
    checkGameExists(cmd);

    RoomTurntableGame roomTurntableGame = createTurntableGame(cmd);
    roomTurntableGameMongoService.create(roomTurntableGame);

    gameMqMessage.turntableDelayed(IdWorkerUtils.getIdStr()
        , new GameTurntableEvent()
            .setType(1)
            .setGameId(roomTurntableGame.getGameId())
            .setStartDeliverTime(TimestampUtils.nowPlusMinutes(2).getTime())
            .setSysOrigin(cmd.requireReqSysOriginEnum())
    );

    saveLogRecord(roomTurntableGame);
    return gameTurntableConvertor.toRoomTurntableGameCO(roomTurntableGame);
  }

  private void checkGameExists(GameTurntableCreateCmd cmd) {
    RoomTurntableGame game = roomTurntableGameMongoService
        .getRoomTurntableGameByRoomId(cmd.getRoomId());
    ResponseAssert.isFalse(RoomErrorCode.GAME_IS_CREATE, Objects.nonNull(game)
        && !TurntableGameStatus.checkGameClose(game.getStatus()));
  }

  private void saveLogRecord(RoomTurntableGame roomTurntableGame) {
    gameTurntableRecordService.save(new GameTurntableRecord()
        .setGameId(roomTurntableGame.getGameId())
        .setInitiatorRole(roomTurntableGame.getRoles())
        .setRoomId(roomTurntableGame.getRoomId())
        .setInitiatorUser(roomTurntableGame.getUserId())
        .setHomeownerUser(roomTurntableGame.getHomeownerUserId())
        .setGameGolds(roomTurntableGame.getGameGolds())
        .setStatus(TurntableGameStatus.WAIT.name())
    );
  }

  private RoomTurntableGame createTurntableGame(GameTurntableCreateCmd cmd) {
    return new RoomTurntableGame()
        .setRoomId(cmd.getRoomId())
        .setGameId(IdWorkerUtils.getId())
        .setUserId(cmd.getReqUserId())
        .setHomeownerUserId(cmd.getHomeownerUserId())
        .setGameGolds(cmd.getGameGolds())
        .setRoles(cmd.getRolesName())
        .setStatus(TurntableGameStatus.WAIT.name())
        .setExpiredTime(TimestampUtils.nowPlusMinutes(15))
        .setCreateTime(TimestampUtils.now());
  }

}
