package com.red.circle.game.fruit.application.command;

import cn.hutool.core.date.DateUtil;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.game.fruit.application.dto.enums.GameSysOriginEnum;
import com.red.circle.game.fruit.application.dto.enums.RankingOriginEnum;
import com.red.circle.game.fruit.application.dto.enums.RankingTypeEnum;
import com.red.circle.game.fruit.infrastructure.database.entity.GameFruitDaysRecord;
import com.red.circle.game.fruit.infrastructure.database.entity.GameFruitPriorityWinners;
import com.red.circle.game.fruit.infrastructure.database.entity.GameFruitRule;
import com.red.circle.game.fruit.infrastructure.database.entity.GameFruitUserDaysRanking;
import com.red.circle.game.fruit.infrastructure.database.repository.GameFruitDaysRecordService;
import com.red.circle.game.fruit.infrastructure.database.repository.GameFruitPriorityWinnersService;
import com.red.circle.game.fruit.infrastructure.database.repository.GameFruitRuleService;
import com.red.circle.game.fruit.infrastructure.database.repository.GameFruitUserDaysRankingService;
import com.red.circle.order.inner.endpoint.OrderPurchaseHistoryClient;
import com.red.circle.order.inner.endpoint.UserRechargeCountClient;
import com.red.circle.order.inner.model.cmd.UserRechargeDaysQryCmd;
import com.red.circle.order.inner.model.cmd.UserRechargeMonthQryCmd;
import com.red.circle.order.inner.model.dto.MonthlyRechargeUserDTO;
import com.red.circle.order.inner.model.dto.OrderPurchaseHistoryDTO;
import com.red.circle.order.inner.model.dto.TotalRechargeUserDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.DateUtils;
import com.red.circle.tool.core.date.LocalDateUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 充值榜单优先获奖名单
 *
 * @author lisizhe 2023/12/8  15:13
 */
@Component
@RequiredArgsConstructor
public class InitGameDataExe {

  private final GameFruitRuleService gameFruitRuleService;
  private final UserRechargeCountClient userRechargeCountClient;
  private final GameFruitDaysRecordService gameFruitDaysRecordService;
  private final OrderPurchaseHistoryClient orderPurchaseHistoryClient;
  private final GameFruitPriorityWinnersService gameFruitPriorityWinnersService;
  private final GameFruitUserDaysRankingService gameFruitUserDaysRankingService;

  public void execute() {
    List<GameFruitPriorityWinners> gameFruitPriorityWinners = new ArrayList<>();

    for (GameSysOriginEnum sysOriginEnum : GameSysOriginEnum.values()) {

      String sysOrigin = sysOriginEnum.getSysOrigin();

      GameFruitRule gameFruitRule = gameFruitRuleService.getRule(sysOrigin);
      // 新增今日游戏数据
      addTodayGameData(sysOrigin);

      // 获取总榜优先获奖数据
      List<GameFruitPriorityWinners> totalPriorityWinners = addTotalPriorityWinners(sysOrigin);
      // 获取月榜优先获奖数据
      List<GameFruitPriorityWinners> monthPriorityWinners = addMonthPriorityWinners(
          totalPriorityWinners.stream().map(GameFruitPriorityWinners::getUserId)
              .collect(Collectors.toSet()), sysOrigin);

      // 总榜亏损用户补偿
      List<GameFruitPriorityWinners> totalLossPriorityWinners = addLossTotalPriorityWinners(
          totalPriorityWinners, gameFruitRule);

      // 月榜亏损用户补偿
      List<GameFruitPriorityWinners> monthLossPriorityWinners = addLossMonthPriorityWinners(
          totalLossPriorityWinners.stream().map(GameFruitPriorityWinners::getUserId).collect(
              Collectors.toSet()), gameFruitRule);

      // 获取日榜优先获奖数据
      gameFruitPriorityWinners.addAll(addDaysPriorityWinners(sysOrigin));
      gameFruitPriorityWinners.addAll(monthPriorityWinners);
      gameFruitPriorityWinners.addAll(totalPriorityWinners);

      gameFruitPriorityWinners.addAll(totalLossPriorityWinners);
      gameFruitPriorityWinners.addAll(monthLossPriorityWinners);
    }
    gameFruitPriorityWinnersService.batchAdd(gameFruitPriorityWinners);
  }

  private void addTodayGameData(String sysOrigin) {
    // 新增今日游戏记录
    gameFruitDaysRecordService.add(
        new GameFruitDaysRecord()
            .setSysOrigin(sysOrigin).setDate(
                DateUtils.formatUtc(DateUtils.nowPlusDays(1), "yyyyMMdd")));
  }


  /**
   * 日榜充值优先名单
   */
  public List<GameFruitPriorityWinners> addDaysPriorityWinners(String sysOrigin) {
    // 查询日榜充值
    List<OrderPurchaseHistoryDTO> orderPurchaseHistory = orderPurchaseHistoryClient.purchaseTodayBySysOrigin(
        new UserRechargeDaysQryCmd().setSysOrigin(sysOrigin)).getBody();
    AtomicInteger rank = new AtomicInteger();

    if (CollectionUtils.isEmpty(orderPurchaseHistory)) {
      return CollectionUtils.newArrayList();
    }
    return orderPurchaseHistory.stream()
        .map(item -> new GameFruitPriorityWinners().setIsUse(0)
            .setSysOrigin(sysOrigin)
            .setExpiredTime(DateUtil.offsetDay(DateUtil.date(), 1))
            .setType(RankingTypeEnum.PRIORITY_LOTTERY.name())
            .setRanking(rank.incrementAndGet())
            .setOrigin(RankingOriginEnum.TODAY.name())
            .setUserId(item.getUserId())).toList();
  }

  /**
   * 月榜充值优先名单
   */
  public List<GameFruitPriorityWinners> addMonthPriorityWinners(Set<Long> userIds,
      String sysOrigin) {
    List<MonthlyRechargeUserDTO> monthlyRechargeUser = userRechargeCountClient.listMonthlyRecharge(
        new UserRechargeMonthQryCmd().setRechargeDate(LocalDateUtils.nowThisMonthToInteger())
            .setUserIds(userIds).setSysOrigin(sysOrigin)
    ).getBody();

    if (CollectionUtils.isEmpty(monthlyRechargeUser)) {
      return CollectionUtils.newArrayList();
    }
    AtomicInteger rank = new AtomicInteger();

    return monthlyRechargeUser.stream()
        .map(item -> new GameFruitPriorityWinners().setIsUse(0)
            .setExpiredTime(DateUtil.offsetDay(DateUtil.date(), 1))
            .setType(RankingTypeEnum.PRIORITY_LOTTERY.name())
            .setRanking(rank.incrementAndGet())
            .setOrigin(RankingOriginEnum.MONTH.name())
            .setUserId(item.getUserId())).toList();

  }

  /**
   * 总榜充值优先名单
   */
  private List<GameFruitPriorityWinners> addTotalPriorityWinners(String sysOrigin) {
    List<TotalRechargeUserDTO> totalRechargeUsers = userRechargeCountClient.listUserRechargeTotal(
        sysOrigin).getBody();

    if (CollectionUtils.isEmpty(totalRechargeUsers)) {
      return CollectionUtils.newArrayList();
    }
    AtomicInteger rank = new AtomicInteger();

    return totalRechargeUsers.stream()
        .map(item -> new GameFruitPriorityWinners().setIsUse(0)
            .setExpiredTime(DateUtil.offsetDay(DateUtil.date(), 1))
            .setType(RankingTypeEnum.PRIORITY_LOTTERY.name())
            .setRanking(rank.incrementAndGet())
            .setOrigin(RankingOriginEnum.OVERALL.name())
            .setUserId(item.getUserId())).toList();
  }

  /**
   * 总榜补偿名单
   */
  private List<GameFruitPriorityWinners> addLossTotalPriorityWinners(
      List<GameFruitPriorityWinners> totalLossPriorityWinners,
      GameFruitRule gameFruitRule) {

    BigDecimal lossRatioLottery = gameFruitRule.getLossRatioLottery();
    BigDecimal toDayLossLottery = gameFruitRule.getTodayLossLottery();

    if (CollectionUtils.isEmpty(totalLossPriorityWinners)) {
      return CollectionUtils.newArrayList();
    }

    // 查询满足条件的用户
    List<GameFruitUserDaysRanking> gameFruitUserDaysRankings = gameFruitUserDaysRankingService.listByUserIds(
        totalLossPriorityWinners.stream().map(GameFruitPriorityWinners::getUserId)
            .collect(Collectors.toSet()), lossRatioLottery, toDayLossLottery);

    // 过滤今日未充值的用户
    List<GameFruitUserDaysRanking> addGameFruitUserDaysRanking = filterToDayNoRecharge(
        gameFruitUserDaysRankings, gameFruitRule.getSysOrigin());

    if (CollectionUtils.isEmpty(addGameFruitUserDaysRanking)) {
      return CollectionUtils.newArrayList();
    }
    AtomicInteger rank = new AtomicInteger();

    return addGameFruitUserDaysRanking.stream()
        .map(item -> new GameFruitPriorityWinners().setIsUse(0)
            .setExpiredTime(DateUtil.offsetDay(DateUtil.date(), 2))
            .setType(RankingTypeEnum.COMPENSATORY_REWARD.name())
            .setRanking(rank.incrementAndGet())
            .setOrigin(RankingOriginEnum.OVERALL.name())
            .setUserId(item.getUserId())).toList();
  }

  /**
   * 月榜补偿名单
   */
  private List<GameFruitPriorityWinners> addLossMonthPriorityWinners(Set<Long> userIds, GameFruitRule gameFruitRule) {

    // 查询月榜top50
    List<MonthlyRechargeUserDTO> monthPriorityWinners = userRechargeCountClient.listMonthlyRecharge(
        new UserRechargeMonthQryCmd().setRechargeDate(LocalDateUtils.nowThisMonthToInteger())
            .setSysOrigin(gameFruitRule.getSysOrigin())
    ).getBody();

    if (CollectionUtils.isEmpty(monthPriorityWinners)) {
      return CollectionUtils.newArrayList();
    }

    BigDecimal lossRatioLottery = gameFruitRule.getLossRatioLottery();
    BigDecimal toDayLossLottery = gameFruitRule.getTodayLossLottery();

    // 过滤掉总榜已存在的
    List<MonthlyRechargeUserDTO> priorityWinners = monthPriorityWinners.stream()
        .filter(item -> !userIds.contains(item.getUserId())).toList();

    if (CollectionUtils.isEmpty(priorityWinners)) {
      return CollectionUtils.newArrayList();
    }

    // 查询是否满足条件
    List<GameFruitUserDaysRanking> gameFruitUserDaysRankings = gameFruitUserDaysRankingService.listByUserIds(
        priorityWinners.stream().map(MonthlyRechargeUserDTO::getUserId)
            .collect(Collectors.toSet())
        , lossRatioLottery, toDayLossLottery);

    // 过滤今日未充值的用户
    List<GameFruitUserDaysRanking> addGameFruitUserDaysRanking = filterToDayNoRecharge(
        gameFruitUserDaysRankings, gameFruitRule.getSysOrigin());

    if (CollectionUtils.isEmpty(addGameFruitUserDaysRanking)) {
      return CollectionUtils.newArrayList();
    }
    AtomicInteger rank = new AtomicInteger();

    return addGameFruitUserDaysRanking.stream()
        .map(item -> new GameFruitPriorityWinners().setIsUse(0)
            .setExpiredTime(DateUtil.offsetDay(DateUtil.date(), 2))
            .setType(RankingTypeEnum.COMPENSATORY_REWARD.name())
            .setRanking(rank.incrementAndGet())
            .setOrigin(RankingOriginEnum.MONTH.name())
            .setUserId(item.getUserId())).toList();

  }

  /**
   * 过滤今日未充值的用户
   */
  public List<GameFruitUserDaysRanking> filterToDayNoRecharge(
      List<GameFruitUserDaysRanking> gameFruitUserDaysRankings, String sysOrigin) {
    if (CollectionUtils.isEmpty(gameFruitUserDaysRankings)) {
      return CollectionUtils.newArrayList();
    }
    Set<Long> userIds = gameFruitUserDaysRankings.stream().map(GameFruitUserDaysRanking::getUserId)
        .collect(Collectors.toSet());

    // 查询日榜充值
    List<OrderPurchaseHistoryDTO> orderPurchaseHistory = orderPurchaseHistoryClient.purchaseTodayBySysOrigin(
        new UserRechargeDaysQryCmd().setSysOrigin(sysOrigin)
            .setUserIds(userIds)).getBody();

    return gameFruitUserDaysRankings.stream().filter(
        item -> orderPurchaseHistory.stream().map(OrderPurchaseHistoryDTO::getUserId).toList()
            .contains(item.getUserId())).toList();
  }
}
