package com.red.circle.other.app.common.game;

import com.red.circle.common.business.core.enums.GameStateEnum;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.external.inner.endpoint.message.ImGroupClient;
import com.red.circle.external.inner.model.cmd.message.BroadcastGroupMsgBodyCmd;
import com.red.circle.external.inner.model.enums.message.GroupMessageTypeEnum;
import com.red.circle.mq.business.model.event.game.GameIndoorTeamPkEvent;
import com.red.circle.other.app.dto.clientobject.game.GameIndoorTeamPkBaseInfoCO;
import com.red.circle.other.app.dto.clientobject.game.GameIndoorTeamPkMsgCO;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.model.user.UserProfile;
import com.red.circle.other.infra.database.cache.service.other.GameRoomPkCacheService;
import com.red.circle.other.infra.database.mongo.entity.game.pk.GameTeamPkCount;
import com.red.circle.other.infra.database.mongo.entity.gift.GiftAcceptUser;
import com.red.circle.other.infra.database.mongo.service.game.GamePkCountService;
import com.red.circle.other.infra.database.rds.entity.game.GameIndoorTeamPkRecord;
import com.red.circle.other.infra.database.rds.service.game.GameIndoorTeamPkRecordService;
import com.red.circle.other.infra.enums.game.GamePkBelongTeamEnum;
import com.red.circle.other.infra.enums.game.GameRoomPkTypeEnum;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 处理房间内团队PK业务.
 *
 * @author pengshigang
 * @since 2022-3-4
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class GameIndoorTeamPkCommon {

  private final ImGroupClient imGroupClient;
  private final UserProfileGateway userProfileGateway;
  private final GamePkCountService gamePkCountService;
  private final GameRoomPkCacheService gameRoomPkCacheService;
  private final GameIndoorTeamPkRecordService gameIndoorTeamPkRecordService;

  public void processRoomPk(GameIndoorTeamPkEvent event) {


    log.warn("当前订阅消息:{}" , event);
    Long pkId = event.getGameId();
    GameIndoorTeamPkRecord pkRecord = gameIndoorTeamPkRecordService.getById(pkId);
    log.warn("当前pkRecord:{}" , pkRecord);
    if (isEnd(pkRecord, event.getState())) {
      return;
    }

    if (Objects.equals(pkRecord.getGameStatus(), GameStateEnum.WAITING.name())) {
      updateGameState(pkRecord, GameRoomPkTypeEnum.GAME_ROOM_PK_EXPIRED_OVER);
      return;
    }
    //团队分数
    pkRecord.setBlueTeamScore(gameRoomPkCacheService.getBelongTeamIntegral(
        pkRecord.getId(), GamePkBelongTeamEnum.BLUE_TEAM.name()));
    pkRecord.setRedTeamScore(gameRoomPkCacheService
        .getBelongTeamIntegral(pkRecord.getId(), GamePkBelongTeamEnum.RED_TEAM.name()));
    //mvp用户
    pkRecord.setMvpUserId(getMvpUserId(pkRecord));

    //保存记录
    gamePkCountService.addTeamPk(new GameTeamPkCount()
        .setId(IdWorkerUtils.getId())
        .setSysOrigin(pkRecord.getSysOrigin())
        .setRoomId(pkRecord.getRoomId())
        .setMvpUserId(pkRecord.getMvpUserId())
        .setBlueTeamScore(pkRecord.getBlueTeamScore())
        .setRedTeamScore(pkRecord.getRedTeamScore())
        .setCreateTime(pkRecord.getCreateTime())
        .setExpiredTime(TimestampUtils.nowPlusDays(30))
    );

    if (Objects.isNull(pkRecord.getMvpUserId())) {
      updateGameState(pkRecord, GameRoomPkTypeEnum.GAME_ROOM_PK_NO_WINNER_OVER);
      return;
    }

    updateGameState(pkRecord, GameRoomPkTypeEnum.GAME_ROOM_PK_RESULT);

  }

  private Long getMvpUserId(GameIndoorTeamPkRecord record) {

    Long blueMvpUserId = gameRoomPkCacheService.getBelongTeamMvpUserId(record.getId(),
        GamePkBelongTeamEnum.BLUE_TEAM.name());

    Long redMvpUserId = gameRoomPkCacheService.getBelongTeamMvpUserId(record.getId(),
        GamePkBelongTeamEnum.RED_TEAM.name());

    if (Objects.isNull(blueMvpUserId) && Objects.isNull(redMvpUserId)) {
      return null;
    }

    if (Objects.isNull(blueMvpUserId)) {
      return redMvpUserId;
    }

    if (Objects.isNull(redMvpUserId)) {
      return blueMvpUserId;
    }

    Long blueIntegral = gameRoomPkCacheService
        .getBelongTeamRecipientIntegral(record.getId(), GamePkBelongTeamEnum.BLUE_TEAM.name(),
            String.valueOf(blueMvpUserId));

    Long redIntegral = gameRoomPkCacheService
        .getBelongTeamRecipientIntegral(record.getId(), GamePkBelongTeamEnum.RED_TEAM.name(),
            String.valueOf(redMvpUserId));

    if (Objects.equals(blueIntegral, 0L) && Objects.equals(redIntegral, 0L)) {
      return null;
    }

    return blueIntegral > redIntegral ? blueMvpUserId : redMvpUserId;


  }


  /**
   * 修改状态为【时间过期结束】，并删除redis pk数据.
   */
  private void updateGameState(GameIndoorTeamPkRecord pkRecord,
      GameRoomPkTypeEnum roomPkType) {

    pkRecord.setGameStatus(getGameState(pkRecord));
    pkRecord.setUpdateTime(TimestampUtils.now());
    gameIndoorTeamPkRecordService.updateSelectiveById(pkRecord);
    sendMsg(pkRecord, roomPkType);
  }


  /**
   * 发送消息.
   *
   * @param record             记录
   * @param gameRoomPkTypeEnum 结束类型
   */
  private void sendMsg(GameIndoorTeamPkRecord record, GameRoomPkTypeEnum gameRoomPkTypeEnum) {

    UserProfile userProfile = userProfileGateway.getByUserId(record.getMvpUserId());
    log.warn("下发PK消息:{}" , gameRoomPkTypeEnum.name());
    imGroupClient.sendMessageBroadcast(BroadcastGroupMsgBodyCmd.builder()
        .allPlatform()
        .type(GroupMessageTypeEnum.GAME_INDOOR_TEAM_PK)
        .data(new GameIndoorTeamPkMsgCO()
            .setRoomId(record.getRoomId())
            .setMvpUserId(record.getMvpUserId())
            .setMvpName(Objects.isNull(userProfile) ? null : userProfile.getUserNickname())
            .setMvpCover(Objects.isNull(userProfile) ? null : userProfile.getUserAvatar())
            .setRedTeamScore(record.getRedTeamScore())
            .setBlueTeamScore(record.getBlueTeamScore())
            .setMsgType(gameRoomPkTypeEnum.name())
        )
        .build());
  }

  /**
   * 该局游戏是否已结束.
   */
  private boolean isEnd(GameIndoorTeamPkRecord gameRoomPkRecord, GameStateEnum msgStateEnum) {

    if (Objects.isNull(gameRoomPkRecord)) {
      return true;
    }

    if (Objects.equals(GameStateEnum.STARTED.name(), gameRoomPkRecord.getGameStatus()) &&
        Objects.equals(msgStateEnum, GameStateEnum.WAITING)) {
      //数据库状态为 pk中，但订阅消息传过来的是 等待中 则不处理任何业务
      return true;
    }

    return Objects.equals(gameRoomPkRecord.getGameStatus(), GameStateEnum.END.name()) ||
        Objects.equals(gameRoomPkRecord.getGameStatus(), GameStateEnum.EXPIRED_END.name()) ||
        Objects.equals(gameRoomPkRecord.getGameStatus(), GameStateEnum.VOLUNTARILY_END.name());
  }

  private String getGameState(GameIndoorTeamPkRecord gameRoomPkRecord) {
    return Objects.equals(GameStateEnum.WAITING.name(), gameRoomPkRecord.getGameStatus()) ?
        GameStateEnum.EXPIRED_END.name() : GameStateEnum.END.name();

  }

  /**
   * 计算团队房间内PK积分
   *
   * @param accepts      收礼人
   * @param roomId       房间id
   * @param sendUserId   送礼人id
   * @param acceptAmount 收礼金额
   */
  public void calculatePoints(List<GiftAcceptUser> accepts, Long roomId, Long sendUserId,
      BigDecimal acceptAmount) {

    if (CollectionUtils.isNotEmpty(accepts) && Objects.nonNull(acceptAmount)) {
      accepts.stream().filter(this::checkData).forEach(accept -> {
        // 给有座位号的用户id 判断区域 然后增加对应积分
        GameIndoorTeamPkBaseInfoCO pkBaseInfo = getCacheServiceIndoorTeamPkBaseInfo(roomId);
        if (Objects.isNull(pkBaseInfo) || !Objects
            .equals(pkBaseInfo.getGameStatus(), GameStateEnum.STARTED.name())) {
          return;
        }
        String belongTeam = getBelongTeam(accept, pkBaseInfo);
        if (StringUtils.isBlank(belongTeam)) {
          return;
        }

        // 累计房间内PK各队总额
        gameRoomPkCacheService.indoorAccumulateTeamScore(pkBaseInfo.getId(), belongTeam,
            acceptAmount.longValue());

        // 累计房间内PK小队具体支持者分值
        gameRoomPkCacheService
            .indoorAccumulateTeamRecipientScore(pkBaseInfo.getId(), belongTeam,
                accept.getAcceptUserId(), acceptAmount.longValue());

        // 累计房间内PK小队具体收礼人分值
        gameRoomPkCacheService
            .indoorAccumulateTeamFansScore(pkBaseInfo.getId(), belongTeam,
                sendUserId, acceptAmount.longValue());

      });
    }

  }

  private GameIndoorTeamPkBaseInfoCO getCacheServiceIndoorTeamPkBaseInfo(Long roomId) {

    if (Objects.isNull(roomId)) {
      return null;
    }

    GameIndoorTeamPkRecord record = gameIndoorTeamPkRecordService
        .getByRoomIdByStatus(roomId, GameStateEnum.STARTED);

    if (Objects.isNull(record)) {
      return null;
    }

    return gameRoomPkCacheService
        .getIndoorTeamPkBaseInfo(record.getId(), GameIndoorTeamPkBaseInfoCO.class);
  }

  /**
   * 校验是否为有效座位号
   */
  private Boolean checkData(GiftAcceptUser accept) {
    if (Objects.isNull(accept) || Objects.isNull(accept.getSeatIndex())) {
      return Boolean.FALSE;
    }
    return (accept.getSeatIndex() <= 7 && accept.getSeatIndex() >= 0) || accept.getSeatIndex() == 9;
  }

  /**
   * 获得归属团队
   */
  private String getBelongTeam(GiftAcceptUser accept,
      GameIndoorTeamPkBaseInfoCO pkBaseInfo) {

    if (Objects.isNull(accept.getSeatIndex())) {
      return null;
    }
    if (SysOriginPlatformEnum.YOLO.name().equals(pkBaseInfo.getSysOrigin())||SysOriginPlatformEnum.TARAB.name().equals(pkBaseInfo.getSysOrigin())){
      if (accept.getSeatIndex() <= 3) {
        return GamePkBelongTeamEnum.BLUE_TEAM.name();
      }
      if (accept.getSeatIndex() <= 7) {
        return GamePkBelongTeamEnum.RED_TEAM.name();
      }
    }else {
      if (accept.getSeatIndex() <= 3) {
        return GamePkBelongTeamEnum.RED_TEAM.name();
      }
      if (accept.getSeatIndex() <= 7) {
        return GamePkBelongTeamEnum.BLUE_TEAM.name();
      }
    }

    if (StringUtils.isBlank(pkBaseInfo.getBelongTeam())) {
      return null;
    }
    if (accept.getSeatIndex() == 9 && Objects
        .equals(accept.getAcceptUserId(), pkBaseInfo.getUserId())) {
      return pkBaseInfo.getBelongTeam();
    }
    return null;
  }


}
