package com.red.circle.other.app.inner.service.game.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.red.circle.other.app.inner.convertor.game.GameLudoConvertor;
import com.red.circle.other.app.inner.service.game.GameLudoClientService;
import com.red.circle.other.infra.database.cache.service.other.GameCacheService;
import com.red.circle.other.infra.database.mongo.entity.game.ludo.GameLudoRun;
import com.red.circle.other.infra.database.mongo.entity.game.ludo.GameStatus;
import com.red.circle.other.infra.database.mongo.entity.game.ludo.GameStatusEvent;
import com.red.circle.other.infra.database.mongo.service.game.GameLudoRunService;
import com.red.circle.other.infra.database.rds.entity.game.GameLudoHistory;
import com.red.circle.other.infra.database.rds.entity.game.GameLudoPlayers;
import com.red.circle.other.infra.database.rds.service.game.GameLudoHistoryService;
import com.red.circle.other.infra.database.rds.service.game.GameLudoPlayersService;
import com.red.circle.other.inner.model.cmd.game.GameLudoQryCmd;
import com.red.circle.other.inner.model.dto.game.GameLudoHistoryDTO;
import com.red.circle.other.inner.model.dto.game.GameLudoHistoryInfoDTO;
import com.red.circle.other.inner.model.dto.game.GameLudoPlayerInfoDTO;
import com.red.circle.other.inner.model.dto.game.GameLudoPlayersDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 飞行棋
 *
 * @author zongpubin on 2024/1/26
 */
@Service
@RequiredArgsConstructor
public class GameLudoClientServiceImpl implements GameLudoClientService {

  private final WalletGoldClient walletGoldClient;
  private final GameCacheService gameCacheService;
  private final GameLudoConvertor gameLudoConvertor;
  private final GameLudoRunService gameLudoRunService;
  private final GameLudoPlayersService gameLudoPlayersService;
  private final GameLudoHistoryService gameLudoHistoryService;

  @Override
  public List<GameLudoHistoryInfoDTO> listGameLudoRun(GameLudoQryCmd query) {

    List<GameLudoRun> gameLudoRuns = gameLudoRunService.flowSelective(query.getSysOrigin(),
        query.getRoomId(), query.getLastId());

    if (CollectionUtils.isEmpty(gameLudoRuns)) {
      return Lists.newArrayList();
    }

    return gameLudoRuns.stream().map(gameLudoRun -> {
      GameLudoHistoryInfoDTO gameLudo = new GameLudoHistoryInfoDTO();
      gameLudo.setId(gameLudoRun.getId());
      gameLudo.setGameStatus(gameLudoRun.getGameStatus().name());
      gameLudo.setGameStatusEvent(gameLudoRun.getGameStatusEvent().name());
      gameLudo.setBonus(gameLudoRun.bonusRatio());
      gameLudo.setJoinAmount(gameLudoRun.getJoinAmount());
      gameLudo.setCreateTime(gameLudoRun.getCreateTime());
      gameLudo.setLockSeat(gameLudoRun.getLockSeat());
      gameLudo.setPlayerSize(gameLudoRun.playersSize());
      gameLudo.setRoomId(gameLudoRun.getRoomId());
      gameLudo.setSysOrigin(gameLudoRun.getSysOrigin());
      gameLudo.setUpdateTime(gameLudoRun.getCreateTime());
      gameLudo.setPlayers(gameLudoRun.getPlayers().stream().map(gameLudoPlayer -> {
        GameLudoPlayerInfoDTO gameLudoPlayerInfo = new GameLudoPlayerInfoDTO();
        gameLudoPlayerInfo.setPlayerProfile(
            gameLudoConvertor.toGamePlayerProfileDTO(gameLudoPlayer.getPlayerProfile()));
        gameLudoPlayerInfo.setInitiator(gameLudoPlayer.getInitiator());
        gameLudoPlayerInfo.setCreateTime(gameLudoPlayer.getCreateTime());
        gameLudoPlayerInfo.setRankingIndex(gameLudoPlayer.getRankingIndex());
        gameLudoPlayerInfo.setCheckerboardColor(gameLudoPlayer.getCheckerboardColor().name());
        gameLudoPlayerInfo.setConsumeJoinAmount(gameLudoPlayer.getConsumeJoinAmount());
        return gameLudoPlayerInfo;
      }).collect(Collectors.toList()));
      return gameLudo;
    }).collect(Collectors.toList());
  }

  @Override
  public void dismiss(Long roomId) {
    GameLudoRun gameLudoRun = gameLudoRunService.get(roomId);
    if (Objects.isNull(gameLudoRun)) {
      return;
    }
    // 清理缓存
    gameCacheService.removeLudo(roomId,
        gameLudoRun.getPlayers().stream().map(player -> player.getPlayerProfile().getId()).collect(
            Collectors.toList()));

    // 清理游戏运行数据
    gameLudoRunService.remove(gameLudoRun.getId());

    // 保存游戏档案
    GameLudoHistory gameLudoHistory = new GameLudoHistory();
    gameLudoHistory.setId(IdWorkerUtils.getId());
    gameLudoHistory.setVictoryColor("");
    gameLudoHistory.setBonus(gameLudoRun.bonusRatio());
    gameLudoHistory.setPlayerSize(gameLudoRun.playersSize());
    gameLudoHistory.setGameStatus(GameStatus.END.name());
    gameLudoHistory.setGameStatusEvent(GameStatusEvent.BACK_DISBAND.name());
    gameLudoHistory.setCreateTime(gameLudoRun.getCreateTime());
    gameLudoHistory.setLockSeat(gameLudoRun.getLockSeat());
    gameLudoHistory.setJoinAmount(gameLudoRun.getJoinAmount());
    gameLudoHistory.setRoomId(gameLudoRun.getRoomId());
    gameLudoHistory.setSysOrigin(gameLudoRun.getSysOrigin());
    gameLudoHistoryService.save(gameLudoHistory);

    if (gameLudoHistory.getPlayerSize() <= 0) {
      return;
    }

    gameLudoPlayersService.saveBatch(
        gameLudoRun.getPlayers().stream().map(player -> new GameLudoPlayers()
                .setGameId(gameLudoHistory.getId())
                .setUserId(player.getPlayerProfile().getId())
                .setConsumeJoinAmount(player.getConsumeJoinAmount())
                .setCheckerboardColor(Objects.toString(player.getCheckerboardColor()))
                .setInitiator(player.getInitiator())
                .setRankingIndex(
                    Objects.isNull(player.getRankingIndex()) ? 0 : player.getRankingIndex()))
            .collect(Collectors.toList()));

    // 退钱
    refund(gameLudoRun);

  }

  @Override
  public List<GameLudoHistoryDTO> flowSelective(GameLudoQryCmd query) {

    List<GameLudoHistory> gameLudoHistories = gameLudoHistoryService.flowSelective(
        query.getSysOrigin(),
        query.getRoomId(), query.getLastId());

    return gameLudoConvertor.toListGameLudoHistoryDTO(gameLudoHistories);
  }

  @Override
  public Map<Long, List<GameLudoPlayersDTO>> mapLudoPlayersByGameId(Set<Long> gameIds) {
    return Optional.ofNullable(gameLudoPlayersService.listByGameIds(gameIds))
        .map(gameLudoPlayers ->
            gameLudoConvertor.toGameLudoPlayersDTO(gameLudoPlayers).stream()
                .collect(Collectors.groupingBy(GameLudoPlayersDTO::getGameId)))
        .orElseGet(Maps::newHashMap);
  }

  /**
   * 退款
   */
  private void refund(GameLudoRun gameLudoRun) {
    if (CollectionUtils.isNotEmpty(gameLudoRun.getPlayers())) {
      if (ArithmeticUtils.gtZero(gameLudoRun.getJoinAmount())) {
        gameLudoRun.getPlayers()
            .forEach(player -> {
              Long userId = player.getPlayerProfile().getId();
              walletGoldClient.changeBalance(GoldReceiptCmd.builder()
                  .userId(userId)
                  .sysOrigin(gameLudoRun.getSysOrigin())
                  .opsIncome()
                  .origin(GoldOrigin.GAME_LUDO_REFUND)
                  .remark(GoldOrigin.GAME_LUDO_REFUND.getDesc())
                  .eventId("-")
                  .amount(gameLudoRun.getJoinAmount())
                  .closeDelayAsset()
                  .build());
            });
      }
    }
  }
}
