package com.red.circle.console.app.service.app.game;

import com.red.circle.common.business.dto.cmd.PageUserIdCmd;
import com.red.circle.console.app.dto.clienobject.game.GameDataStatisticalCO;
import com.red.circle.console.app.dto.clienobject.game.GameUserBetRecordCO;
import com.red.circle.console.app.dto.clienobject.game.PageGameUserDaysCO;
import com.red.circle.console.inner.error.ConsoleErrorCode;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.game.fruit.inner.endpoint.GameFruitHistoryClient;
import com.red.circle.game.fruit.inner.model.cmd.GameDataStatisticalCmd;
import com.red.circle.game.fruit.inner.model.cmd.PageDaysRecordQryCmd;
import com.red.circle.game.fruit.inner.model.dto.DaysRecordDTO;
import com.red.circle.game.fruit.inner.model.dto.GameDataStatisticalDTO;
import com.red.circle.game.fruit.inner.model.dto.GameUserBetRecordDTO;
import com.red.circle.game.fruit.inner.model.dto.PageGameUserDaysDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.DateUtils;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 摩天轮游戏配置配置服务
 *
 * @author lisizhe on 2023/12/13
 */
@Service
@RequiredArgsConstructor
public class GameFruitHistoryServiceImpl implements GameFruitHistoryService {

  private final UserProfileClient userProfileClient;
  private final GameFruitHistoryClient gameFruitHistoryClient;

  @Override
  public DaysRecordDTO pageGameFruitDaysRecord(PageDaysRecordQryCmd cmd) {
    if(Objects.isNull(cmd.getDate()) && Objects.isNull(cmd.getNewNum()) && Objects.isNull(cmd.getPlayerNum())
    && Objects.isNull(cmd.getProfit()) && Objects.isNull(cmd.getUserExpend()) && Objects.isNull(cmd.getEarningsRate())
    &&  Objects.isNull(cmd.getPlatformExpend())){
      cmd.setDate(Boolean.FALSE);
    }
    return gameFruitHistoryClient.pageGameFruitDaysRecord(cmd).getBody();
  }

  @Override
  public GameDataStatisticalCO pageUserBetRecord(GameDataStatisticalCmd cmd) {
    if (Objects.isNull(cmd.getStartTime()) || Objects.isNull(cmd.getEndTime())) {
      ResponseAssert.failure(ConsoleErrorCode.PLEASE_SELECT_TIME);
    }
    long days = DateUtils.toDurationDays(DateUtils.convert(cmd.getStartTime()),
        DateUtils.convert(cmd.getEndTime()));

    ResponseAssert.isFalse(ConsoleErrorCode.TIME_OUT, days > 7L);

    GameDataStatisticalDTO gameDataStatisticalDTO = gameFruitHistoryClient.pageUserBetRecord(cmd)
        .getBody();
    PageResult<GameUserBetRecordDTO> gameUserBetRecordResult = gameDataStatisticalDTO.getGameUserBetRecords();

    Map<Long, UserProfileDTO> userProfileMap = userProfileClient.mapByUserIds(
        gameUserBetRecordResult.getRecords().stream().map(GameUserBetRecordDTO::getUserId).collect(
            Collectors.toSet())).getBody();

    return new GameDataStatisticalCO().setGameUserBetRecords(
            gameUserBetRecordResult.convert(item -> new GameUserBetRecordCO()
                .setAwards(item.getAwards())
                .setUserProfile(userProfileMap.get(item.getUserId()))
                .setBetAmount(item.getBetAmount())
                .setBetPrize(item.getBetPrize())
                .setRound(item.getRound())
                .setLastBetTime(item.getLastBetTime())
                .setLotteryPrize(item.getLotteryPrize())))
        .setBetAmount(gameDataStatisticalDTO.getBetAmount())
        .setPlayerNum(gameDataStatisticalDTO.getPlayerNum())
        .setAwards(gameDataStatisticalDTO.getAwards());
  }

  @Override
  public PageResult<PageGameUserDaysCO> pageDaysUserData(PageUserIdCmd cmd) {
    PageResult<PageGameUserDaysDTO> pageResult = gameFruitHistoryClient.pageDaysUserData(cmd)
        .getBody();

    if (Objects.isNull(pageResult) || CollectionUtils.isEmpty(pageResult.getRecords())) {
      return PageResult.newPageResult(cmd.getPageQuery().getLimit());
    }

    Map<Long, UserProfileDTO> userProfileMap = userProfileClient.mapByUserIds(
        pageResult.getRecords().stream().map(PageGameUserDaysDTO::getUserId).collect(
            Collectors.toSet())).getBody();

    return pageResult.convert(result -> {

      BigDecimal earnings = result.getEarning().subtract(result.getBetAmount());
      return new PageGameUserDaysCO()
          .setUserProfile(userProfileMap.get(result.getUserId()))
          .setDate(result.getDate())
          .setBetSize(result.getBetSize())
          .setEarnings(earnings)
          .setEarningsRate(ArithmeticUtils.eqZero(result.getBetAmount()) ? BigDecimal.ZERO
              : earnings.divide(result.getBetAmount(), 4, RoundingMode.HALF_UP)
                  .multiply(BigDecimal.valueOf(100)))
          .setWinnersAmount(result.getEarning())
          .setBetAmount(result.getBetAmount())
          .setEarningsSum(result.getEarningsSum())
          .setCreateTime(result.getCreateTime());

    });
  }
}
