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

import com.google.common.collect.Lists;
import com.red.circle.common.business.dto.cmd.RoomIdCmd;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.game.GameIndoorTeamPkBaseInfoCO;
import com.red.circle.other.app.dto.clientobject.game.GameIndoorTeamPkCO;
import com.red.circle.other.app.dto.clientobject.game.GameIndoorTeamPkTopThreeFansCO;
import com.red.circle.other.app.dto.clientobject.game.GameUserCO;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.cache.service.other.GameRoomPkCacheService;
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.inner.asserts.GameErrorCode;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.date.LocalDateTimeUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 房间内团队PK - 基本信息.
 *
 * @author pengshigang on 2022/3/4
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GameTeamPkBaseInfoCmdExe {

  private final UserProfileGateway userProfileGateway;
  private final GameRoomPkCacheService gameRoomPkCacheService;
  private final UserProfileAppConvertor userProfileAppConvertor;
  private final GameIndoorTeamPkRecordService gameIndoorTeamPkRecordService;

  public GameIndoorTeamPkCO execute(RoomIdCmd cmd) {

    GameIndoorTeamPkRecord pkRecord = gameIndoorTeamPkRecordService
        .getEfficientPkByRoomId(cmd.getRoomId());
    ResponseAssert.notNull(GameErrorCode.GAME_NOT_EXIST, pkRecord);

    GameIndoorTeamPkBaseInfoCO baseInfoCO = gameRoomPkCacheService.getIndoorTeamPkBaseInfo(
        pkRecord.getId(),
        GameIndoorTeamPkBaseInfoCO.class);
    ResponseAssert.notNull(GameErrorCode.GAME_NOT_EXIST, baseInfoCO);

    String redTeam = GamePkBelongTeamEnum.RED_TEAM.name();
    String blueTeam = GamePkBelongTeamEnum.BLUE_TEAM.name();

    long countDown = LocalDateTimeUtils
        .betweenTwoTime(TimestampUtils.now().toLocalDateTime(),
            baseInfoCO.getEndTime().toLocalDateTime(), ChronoUnit.SECONDS);

    baseInfoCO.setOverTime(countDown > 0 ? countDown : 0);

    GameIndoorTeamPkTopThreeFansCO topThreeFans = new GameIndoorTeamPkTopThreeFansCO()
        .setRedTeamFans(buildFans(pkRecord, redTeam))
        .setBlueTeamFans(buildFans(pkRecord, blueTeam))
        .setRedTeamScore(gameRoomPkCacheService.getBelongTeamIntegral(pkRecord.getId(),
            redTeam))
        .setBlueTeamScore(gameRoomPkCacheService.getBelongTeamIntegral(pkRecord.getId(),
            blueTeam));

    return new GameIndoorTeamPkCO()
        .setTeamPkBaseInfo(baseInfoCO)
        .setTeamPkScoreDetails(topThreeFans);
  }

  /**
   * 获得粉丝列表
   *
   * @param pkRecord pk记录
   * @param team     归属团队
   */
  private List<GameUserCO> buildFans(GameIndoorTeamPkRecord pkRecord, String team) {
    return Optional.ofNullable(
            gameRoomPkCacheService.getBelongTeamFanTopThreeUserIds(pkRecord.getId(), team))
        .map(userIds -> userIds.stream().map(userId -> {
          Long score = gameRoomPkCacheService
              .getBelongTeamFansIntegral(pkRecord.getId(), team,
                  userId);
          UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
              userProfileGateway.getByUserId(Long.valueOf(userId)));
          if (Objects.isNull(userProfile)) {
            return null;
          }
          return new GameUserCO()
              .setUserId(userProfile.getId())
              .setUserNickname(userProfile.getUserNickname())
              .setUserSex(userProfile.getUserSex())
              .setUserAvatar(userProfile.getUserAvatar())
              .setAccount(userProfile.getAccount())
              .setTotal(String.valueOf(score));
        }).filter(Objects::nonNull).toList())
        .orElse(Lists.newArrayList());
  }
}
