package com.zanxiang.game.back.serve.utils;

import com.github.sd4324530.jtuple.Tuple2;
import com.github.sd4324530.jtuple.Tuple3;
import com.github.sd4324530.jtuple.Tuple4;
import com.github.sd4324530.jtuple.Tuples;
import com.zanxiang.game.back.serve.pojo.BackPolicyOfSplitLevel;
import com.zanxiang.game.back.serve.pojo.BackPolicyOfSumRecharge;
import com.zanxiang.game.back.serve.pojo.entity.GameBackPolicy;
import com.zanxiang.game.back.serve.pojo.enums.BackUnitEnum;
import com.zanxiang.game.back.serve.pojo.vo.GameBackPolicyVO;
import com.zanxiang.module.util.DateUtil;
import com.zanxiang.module.util.JsonUtil;
import com.zanxiang.module.util.NumberUtil;
import com.zanxiang.module.util.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class BackPolicyUtil {

    /**
     * 订单回传
     *
     * @return <是否回传，回传金额，回传描述>
     */
    public static Tuple4<Boolean, Long, String, List<Tuple2<Long, LocalDateTime>>> backOrder(String orderId, GameBackPolicy gameBackPolicy,
                                                                                             long rechargeMoney, boolean isFirstOrder,
                                                                                             LocalDateTime payTime, LocalDateTime regTime,
                                                                                             String userId, IBackPolicyCheck backPolicyCheck) {
        if (null == gameBackPolicy) {
            log.error("订单 id[{}]找不到回传策略，默认回传", orderId);
            return Tuples.tuple(Boolean.TRUE, rechargeMoney, "没有回传策略", null);
        }
        if (gameBackPolicy.getPolicyType() == null || Objects.equals(gameBackPolicy.getPolicyType(), GameBackPolicy.TYPE_DEFAULT)) {
            Tuple3<Boolean, Long, String> backInfo = policyOfDefault(orderId, gameBackPolicy, rechargeMoney, isFirstOrder, payTime, regTime, userId, backPolicyCheck);
            if (backInfo.first) {
                Collection<GameBackPolicyVO.SplitStrategy> splitStrategyList = StringUtils.isBlank(gameBackPolicy.getSplitStrategy()) ? Collections.emptyList() : JsonUtil.toList(gameBackPolicy.getSplitStrategy(), List.class, GameBackPolicyVO.SplitStrategy.class);
                Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitInfo = splitOrder(splitStrategyList, backInfo.second);
                if (splitInfo.first) {
                    return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, splitInfo.third);
                } else {
                    return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, null);
                }
            } else {
                return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, null);
            }
        } else if (Objects.equals(gameBackPolicy.getPolicyType(), GameBackPolicy.TYPE_SPLIT_LEVEL)) {
            // 按策略判断
            BackPolicyOfSplitLevel policyOfSplitLevel = JsonUtil.toObj(gameBackPolicy.getTypeOfSplitLevelJson(), BackPolicyOfSplitLevel.class);
            Tuple3<Boolean, Long, String> backInfo = policyOfSplitLevel(orderId, gameBackPolicy.getId(), policyOfSplitLevel, rechargeMoney, isFirstOrder, payTime, regTime, userId, backPolicyCheck);

            if (backInfo.first) {
                Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitInfo = splitOrder(policyOfSplitLevel.getSplitStrategy(), backInfo.second);
                if (splitInfo.first) {
                    return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, splitInfo.third);
                } else {
                    return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, null);
                }
            } else {
                return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, null);
            }
        } else if (Objects.equals(gameBackPolicy.getPolicyType(), GameBackPolicy.TYPE_SUM_RECHARGE)) {
            // 按累充判断
            BackPolicyOfSumRecharge policyOfSumRecharge = JsonUtil.toObj(gameBackPolicy.getTypeOfSumRechargeJson(), BackPolicyOfSumRecharge.class);
            return policyOfSumRecharge(orderId, gameBackPolicy.getId(), policyOfSumRecharge, rechargeMoney, isFirstOrder, payTime, regTime, userId, backPolicyCheck);
        }
        throw new BaseException("未知的回传策略类型：" + gameBackPolicy.getPolicyType());

    }

    /**
     * 拆单逻辑
     */
    public static Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitOrder(Collection<GameBackPolicyVO.SplitStrategy> splitStrategyList, Long backMoney) {
        if (CollectionUtils.isEmpty(splitStrategyList)) {
            return Tuple3.with(false, backMoney, null);
        }
        GameBackPolicyVO.SplitStrategy backSplitStrategy = null;
        for (GameBackPolicyVO.SplitStrategy splitStrategy : splitStrategyList) {
            if (NumberUtil.multiply100(splitStrategy.getPayMoney()).longValue() == backMoney) {
                backSplitStrategy = splitStrategy;
                break;
            }
        }
        if (backSplitStrategy == null) {
            return Tuple3.with(false, backMoney, null);
        }
        List<Tuple2<Long, LocalDateTime>> result = new ArrayList<>();
        LocalDateTime beginTime = LocalDateTime.now();
        long sumMoney = 0L;
        for (BigDecimal splitMoney : backSplitStrategy.getSplitList()) {
            long money = NumberUtil.multiply100(splitMoney).longValue();
            sumMoney += money;
            result.add(Tuple2.with(money, beginTime));
            int randomMinute = RandomUtils.nextInt(backSplitStrategy.getBetweenMinuteMin(), backSplitStrategy.getBetweenMinuteMax());
            beginTime = beginTime.plusMinutes(randomMinute);
        }
        return Tuple3.with(true, sumMoney, result);
    }

    private static Tuple3<Boolean, Long, String> policyOfSplitLevel(String orderId, Long policyId, BackPolicyOfSplitLevel policyOfSplitLevel,
                                                                    long rechargeMoney, boolean isFirstOrder,
                                                                    LocalDateTime payTime, LocalDateTime regTime,
                                                                    String userId, IBackPolicyCheck backPolicyCheck) {
        BigDecimal rechargeAmount = NumberUtil.divide100(new BigDecimal(rechargeMoney));
        if (policyOfSplitLevel.getRegPayIntervalTime() != null
                && ((DateUtil.localDateTimeToSecond(payTime) - DateUtil.localDateTimeToSecond(regTime)) / 60) > policyOfSplitLevel.getRegPayIntervalTime()) {
            log.error("订单 id[{}]通过回传策略[{}]判断后，超过注册充值间隔时间({})，不回传", orderId, policyId, policyOfSplitLevel.getRegPayIntervalTime());
            return Tuples.tuple(Boolean.FALSE, rechargeMoney, "超过注册充值间隔时间(" + policyOfSplitLevel.getRegPayIntervalTime() + ")，不回传");
        }
        if (policyOfSplitLevel.getBackCountOfUser() != null) {
            long userBackCount = backPolicyCheck.backCountForUser(BackUnitEnum.LARGE_AMOUNT, userId, false);
            if (userBackCount > policyOfSplitLevel.getBackCountOfUser()) {
                return Tuples.tuple(Boolean.FALSE, rechargeMoney, "单用户最大回传 " + policyOfSplitLevel.getBackCountOfUser() + "笔，当前已回传 " + userBackCount + "笔");
            }
        }
        BackPolicyOfSplitLevel.RechargeLevel rechargeLevel = null;
        for (BackPolicyOfSplitLevel.RechargeLevel item : policyOfSplitLevel.getRechargeLevelList()) {
            if (rechargeAmount.compareTo(item.getMinAmount()) >= 0 && rechargeAmount.compareTo(item.getMaxAmount()) < 0) {
                rechargeLevel = item;
                break;
            }
        }
        if (rechargeLevel == null) {
            log.error("订单 id[{}]通过回传策略[{}]判断后，找不到对应的充值挡位，不回传", orderId, policyId);
            return Tuples.tuple(Boolean.FALSE, rechargeMoney, "充值金额(" + rechargeAmount + ")未找到对应的挡位，默认不回传");
        }
        if (Objects.equals(rechargeLevel.getBackType(), GameBackPolicy.POLICY_TYPE_FIXED_RATE)) {
            // 固定比例回传
            String[] temp = rechargeLevel.getBackRate().split(":");
            int backCount = Integer.parseInt(temp[0]);
            int ignoreCount = Integer.parseInt(temp[1]);
            if (backCount == 0) {
                String backMsg = "按比例回传，回传比例为 0，全部不回传";
                log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：{}", orderId, policyId, backMsg);
                return Tuples.tuple(Boolean.FALSE, rechargeMoney, backMsg);
            }
            if (ignoreCount == 0) {
                String backMsg = "按比例回传，忽略比例为 0，全部回传";
                log.error("订单 id[{}]通过回传策略[{}]判断后，回传，原因：{}", orderId, policyId, backMsg);
                return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
            }
            long isBackCount = backPolicyCheck.backCountForFixedRate(backCount + ignoreCount, BackUnitEnum.LARGE_AMOUNT, false);
            String backMsg = "按比例回传，每 " + (backCount + ignoreCount) + "笔回传 " + backCount + "笔，当前第 " + (isBackCount + 1) + "笔";
            if (isBackCount >= backCount) {
                log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：{}", orderId, policyId, backMsg);
                return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
            } else {
                log.error("订单 id[{}]通过回传策略[{}]判断后，回传，原因：{}", orderId, policyId, backMsg);
                return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
            }
        } else if (Objects.equals(rechargeLevel.getBackType(), GameBackPolicy.POLICY_TYPE_RANDOM_RATE)) {
            // 随机概率回传
            boolean isBack = RandomUtils.nextInt(0, 100) < NumberUtil.multiply100(new BigDecimal(rechargeLevel.getBackRate())).intValue();
            String backMsg = "随机概率回传(" + NumberUtil.multiply100(new BigDecimal(rechargeLevel.getBackRate())) + "%)";
            if (!isBack) {
                log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：{}", orderId, policyId, backMsg);
                return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
            } else {
                log.error("订单 id[{}]通过回传策略[{}]判断后，回传，原因：{}", orderId, policyId, backMsg);
                return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
            }
        } else {
            throw new RuntimeException("回传策略[" + policyId + "]配置错误，未知的回传类型：" + rechargeLevel.getBackType());
        }

    }

    private static Tuple4<Boolean, Long, String, List<Tuple2<Long, LocalDateTime>>> policyOfSumRecharge(String orderId, Long policyId, BackPolicyOfSumRecharge policyOfSumRecharge,
                                                                                                        long rechargeMoney, boolean isFirstOrder,
                                                                                                        LocalDateTime payTime, LocalDateTime regTime,
                                                                                                        String userId, IBackPolicyCheck backPolicyCheck) {
        Tuple2<Long, Long> backInfo = backPolicyCheck.backCountForUserWithSplitOrder(userId);
        BigDecimal rechargeAmount = NumberUtil.divide100(new BigDecimal(rechargeMoney));
        BigDecimal rechargeSumAmount = NumberUtil.divide100(new BigDecimal(backInfo.second)).add(rechargeAmount);
        if (policyOfSumRecharge.getRegPayIntervalTime() != null
                && ((DateUtil.localDateTimeToSecond(payTime) - DateUtil.localDateTimeToSecond(regTime)) / 60) > policyOfSumRecharge.getRegPayIntervalTime()) {
            log.error("订单 id[{}]通过回传策略[{}]判断后，超过注册充值间隔时间({})，不回传", orderId, policyId, policyOfSumRecharge.getRegPayIntervalTime());
            return Tuples.tuple(Boolean.FALSE, rechargeMoney, "超过注册充值间隔时间(" + policyOfSumRecharge.getRegPayIntervalTime() + ")，不回传", null);
        }
        BackPolicyOfSumRecharge.RechargeLevel rechargeLevel = null;
        for (BackPolicyOfSumRecharge.RechargeLevel item : policyOfSumRecharge.getRechargeLevelList()) {
            if (rechargeSumAmount.compareTo(item.getMinAmount()) >= 0 && rechargeSumAmount.compareTo(item.getMaxAmount()) < 0) {
                rechargeLevel = item;
                break;
            }
        }
        if (rechargeLevel == null) {
            log.error("订单 id[{}]通过回传策略[{}]判断后，找不到对应的累充挡位，不回传", orderId, policyId);
            return Tuples.tuple(Boolean.FALSE, rechargeMoney, "累充金额(" + rechargeSumAmount + ")未找到对应的挡位，默认不回传", null);
        }
        if (rechargeLevel.getBackCountOfUser() <= backInfo.first) {
            log.error("订单 id[{}]通过回传策略[{}]判断后，已达到回传的订单数，不回传", orderId, policyId);
            return Tuples.tuple(Boolean.FALSE, rechargeMoney, "累值金额(" + rechargeSumAmount + ")已达到回传的订单数(已回传：" + backInfo.first + "笔，当前挡位：" + rechargeLevel.getBackCountOfUser() + "笔），不回传", null);
        }

        long backCount = rechargeLevel.getBackCountOfUser() - backInfo.first;
        long backMoney = (NumberUtil.multiply100(rechargeSumAmount).longValue() - backInfo.second) / backCount;
        if (backMoney <= 0) {
            // 最低回传一分钱
            backMoney = 1;
        }
        List<Tuple2<Long, LocalDateTime>> splitOrder = new ArrayList<>();
        for (int i = 0; i < backCount; i++) {
            splitOrder.add(Tuple2.with(backMoney, LocalDateTime.now()));
        }
        String backMsg = "累充金额(" + rechargeSumAmount + ") 已回传：" + backInfo.first + "笔，当前挡位：" + rechargeLevel.getBackCountOfUser() + "笔，回传（" + backCount + "-" + backMoney + "）笔";
        log.error("订单 id[{}]通过回传策略[{}]判断后，回传。回传日志：{}", orderId, policyId, backMsg);
        return Tuples.tuple(Boolean.TRUE, backCount * backMoney, backMsg, splitOrder);
    }

    private static Tuple3<Boolean, Long, String> policyOfDefault(String orderId, GameBackPolicy gameBackPolicy,
                                                                 long rechargeMoney, boolean isFirstOrder,
                                                                 LocalDateTime payTime, LocalDateTime regTime,
                                                                 String userId, IBackPolicyCheck backPolicyCheck) {
        if (gameBackPolicy.getSupperSmallAmount() != null && gameBackPolicy.getSupperSmallAmount() >= rechargeMoney) {
            log.error("订单 id[{}]被判定为超小额订单({})，默认不回传", orderId, gameBackPolicy.getSupperSmallAmount());
            return Tuples.tuple(Boolean.FALSE, rechargeMoney, "超小额订单(<=" + gameBackPolicy.getSupperSmallAmount() + ")，不回传");
        }
        BackUnitEnum backUnit = gameBackPolicy.getBackUnit() == null ? BackUnitEnum.UNIT_ONCE : BackUnitEnum.getByValue(gameBackPolicy.getBackUnit());
        Long totalRechargeAmount = null;
        if (backUnit == BackUnitEnum.LARGE_AMOUNT) {
            Long totalAmount = backPolicyCheck.totalRechargeAmount();
            totalRechargeAmount = totalAmount == null ? rechargeMoney : totalAmount + rechargeMoney;
        }

        Boolean firstPolicy = null;
        Long markUpTime = null;
        Integer backType;
        String backRate;
        if (gameBackPolicy.getRegPayIntervalTime() != null
                && ((DateUtil.localDateTimeToSecond(payTime) - DateUtil.localDateTimeToSecond(regTime)) / 60) > gameBackPolicy.getRegPayIntervalTime()) {
            // 补单
            log.error("订单 id[{}]通过回传策略[{}]判断后，超过注册充值间隔时间，走补单逻辑 {}, money: {}.", orderId, gameBackPolicy.getId(), gameBackPolicy.getRegPayIntervalTime(), totalRechargeAmount);

            List<GameBackPolicyVO.PolicyDownLevel> downLevels = StringUtils.isEmpty(gameBackPolicy.getMarkUpDownLevel()) ? Collections.emptyList()
                    : Arrays.stream(gameBackPolicy.getMarkUpDownLevel().split(",")).map(BackPolicyUtil::transformDownLevel).collect(Collectors.toList());
            if (gameBackPolicy.getMarkUpOrder() != null && gameBackPolicy.getMarkUpOrder()) {
                long money = backUnit == BackUnitEnum.LARGE_AMOUNT ? totalRechargeAmount : rechargeMoney;
                markUpTime = gameBackPolicy.getRegPayIntervalTime();
                if (money <= gameBackPolicy.getMarkUpOrderMinMoney()) {
                    // 小额
                    backType = gameBackPolicy.getMarkUpOrderMinMoneyType();
                    backRate = gameBackPolicy.getMarkUpOrderMinMoneyRate();
                } else if (money >= gameBackPolicy.getMarkUpOrderMaxMoney()) {
                    // 大额
                    backType = gameBackPolicy.getMarkUpOrderMaxMoneyType();
                    backRate = gameBackPolicy.getMarkUpOrderMaxMoneyRate();
                } else {
                    backType = gameBackPolicy.getMarkUpOrderOtherMoneyType();
                    backRate = gameBackPolicy.getMarkUpOrderOtherMoneyRate();
                }
                String backMsg = "";
                if (Objects.equals(backType, GameBackPolicy.POLICY_TYPE_FIXED_RATE)) {
                    // 固定比例回传
                    String[] temp = backRate.split(":");
                    int backCount = Integer.parseInt(temp[0]);
                    int ignoreCount = Integer.parseInt(temp[1]);
                    if (backCount == 0) {
                        log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：回传比例 {}", orderId, gameBackPolicy.getId(), backRate);
                        return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), "补单-按比例回传，回传比例为 0，全部不回传");
                    }
                    if (ignoreCount == 0) {
                        log.error("订单 id[{}]通过回传策略[{}]判断后，回传，原因：回传比例 {}", orderId, gameBackPolicy.getId(), backRate);
                        return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevels), "补单-按比例回传，忽略比例为 0，全部回传");
                    }
                    long isBackCount = backPolicyCheck.markUpOfFixedRate(backCount + ignoreCount, markUpTime);
                    backMsg = "补单-按比例回传，每 " + (backCount + ignoreCount) + "笔回传 " + backCount + "笔，当前第 " + (isBackCount + 1) + "笔";
                    if (isBackCount >= backCount) {
                        log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：{}", orderId, gameBackPolicy.getId(), backMsg);
                        return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
                    }
                } else if (Objects.equals(backType, GameBackPolicy.POLICY_TYPE_RANDOM_RATE)) {
                    // 随机概率回传
                    boolean isBack = RandomUtils.nextInt(0, 100) < NumberUtil.multiply100(new BigDecimal(backRate)).intValue();
                    backMsg = "补单-随机概率回传(" + NumberUtil.multiply100(new BigDecimal(backRate)) + "%)";
                    if (!isBack) {
                        log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：{}", orderId, gameBackPolicy.getId(), backMsg);
                        return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
                    }
                } else {
                    throw new RuntimeException("回传策略[" + gameBackPolicy.getId() + "]配置错误，未知的回传类型：" + backType);
                }
                if (gameBackPolicy.getMarkUpBackCountOfUser() == null) {
                    log.error("订单 id[{}]通过回传策略[{}]判断后，回传，原因：回传概率 {}", orderId, gameBackPolicy.getId(), backMsg);
                    return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevels), backMsg);
                }
                long userBackCount = backPolicyCheck.markUpForUser(userId, markUpTime);
                backMsg = backMsg + "，单用户最大回传 " + gameBackPolicy.getMarkUpBackCountOfUser() + "笔，当前已回传 " + userBackCount + "笔";
                log.error("订单 id[{}]通过回传策略[{}]判断后，是否回传：{}，原因：{}", orderId, gameBackPolicy.getId(), userBackCount < gameBackPolicy.getMarkUpBackCountOfUser(), backMsg);
                return Tuples.tuple(userBackCount < gameBackPolicy.getMarkUpBackCountOfUser(), downLevel(rechargeMoney, downLevels), backMsg);
            } else {
                log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：超过注册充值间隔时间但是未开启补单", orderId, gameBackPolicy.getId());
                return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), "补单-未开启补单");
            }
        }

        // 正常判断
        if (backUnit == BackUnitEnum.UNIT_ONCE) {
            firstPolicy = isFirstOrder;
        } else if (backUnit == BackUnitEnum.UNIT_DAY) {
            long intervalDays = DateUtil.intervalOfDays(regTime.toLocalDate(), payTime.toLocalDate());
            firstPolicy = intervalDays == 0;
        } else if (backUnit == BackUnitEnum.UNIT_TIME_DAY) {
            long intervalHours = DateUtil.intervalOfHour(regTime, payTime);
            firstPolicy = intervalHours < 24;
        } else if (backUnit == BackUnitEnum.UNIT_TIME_2DAY) {
            long intervalHours = DateUtil.intervalOfHour(regTime, payTime);
            firstPolicy = intervalHours < 48;
        } else if (backUnit == BackUnitEnum.LARGE_AMOUNT) {
            // 是否是小额订单
            firstPolicy = rechargeMoney < gameBackPolicy.getLargeAmount();
        } else {
            throw new RuntimeException("未知的回传单位：" + backUnit);
        }
        if (firstPolicy) {
            long money = backUnit == BackUnitEnum.LARGE_AMOUNT ? totalRechargeAmount : rechargeMoney;
            if (money <= gameBackPolicy.getFirstMinMoney()) {
                // 小额
                backType = gameBackPolicy.getFirstMinMoneyType();
                backRate = gameBackPolicy.getFirstMinMoneyRate();
            } else if (money >= gameBackPolicy.getFirstMaxMoney()) {
                // 大额
                backType = gameBackPolicy.getFirstMaxMoneyType();
                backRate = gameBackPolicy.getFirstMaxMoneyRate();
            } else {
                backType = gameBackPolicy.getFirstOtherMoneyType();
                backRate = gameBackPolicy.getFirstOtherMoneyRate();
            }
            log.error("订单 id[{}]通过回传策略[{}]判断后走首日逻辑：backType: {}, backRate: {}, money: {}", orderId, gameBackPolicy.getId(), backType, backRate, money);
        } else {
            long money = backUnit == BackUnitEnum.LARGE_AMOUNT ? totalRechargeAmount : rechargeMoney;
            if (money <= gameBackPolicy.getRechargeMinMoney()) {
                // 小额
                backType = gameBackPolicy.getRechargeMinMoneyType();
                backRate = gameBackPolicy.getRechargeMinMoneyRate();
            } else if (money >= gameBackPolicy.getRechargeMaxMoney()) {
                // 大额
                backType = gameBackPolicy.getRechargeMaxMoneyType();
                backRate = gameBackPolicy.getRechargeMaxMoneyRate();
            } else {
                backType = gameBackPolicy.getRechargeOtherMoneyType();
                backRate = gameBackPolicy.getRechargeOtherMoneyRate();
            }
            log.error("订单 id[{}]通过回传策略[{}]判断后走次日逻辑, backType: {}, backRate: {}, money: {}", orderId, gameBackPolicy.getId(), backType, backRate, money);
        }
        Integer maxBackCountOfUser = firstPolicy ? gameBackPolicy.getFirstBackCountOfUser() : gameBackPolicy.getRechargeBackCountOfUser();
        String backMsg = firstPolicy ? "首-" : "次-";
        String downLevelString = firstPolicy ? gameBackPolicy.getFirstDownLevel() : gameBackPolicy.getRechargeDownLevel();
        List<GameBackPolicyVO.PolicyDownLevel> downLevels = StringUtils.isEmpty(downLevelString) ? Collections.emptyList()
                : Arrays.stream(downLevelString.split(",")).map(BackPolicyUtil::transformDownLevel).collect(Collectors.toList());
        if (Objects.equals(backType, GameBackPolicy.POLICY_TYPE_FIXED_RATE)) {
            // 固定比例回传
            String[] temp = backRate.split(":");
            int backCount = Integer.parseInt(temp[0]);
            int ignoreCount = Integer.parseInt(temp[1]);
            if (backCount == 0) {
                backMsg = backMsg + "按比例回传，回传比例为 0，全部不回传";
                log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：{}", orderId, gameBackPolicy.getId(), backMsg);
                return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
            }
            if (ignoreCount == 0) {
                backMsg = backMsg + "按比例回传，忽略比例为 0，全部回传";
                log.error("订单 id[{}]通过回传策略[{}]判断后，回传，原因：{}", orderId, gameBackPolicy.getId(), backMsg);
                return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevels), backMsg);
            }
            long isBackCount = backPolicyCheck.backCountForFixedRate(backCount + ignoreCount, backUnit, firstPolicy);
            backMsg = backMsg + "按比例回传，每 " + (backCount + ignoreCount) + "笔回传 " + backCount + "笔，当前第 " + (isBackCount + 1) + "笔";
            if (isBackCount >= backCount) {
                log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：{}", orderId, gameBackPolicy.getId(), backMsg);
                return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
            }
        } else if (Objects.equals(backType, GameBackPolicy.POLICY_TYPE_RANDOM_RATE)) {
            // 随机概率回传
            boolean isBack = RandomUtils.nextInt(0, 100) < NumberUtil.multiply100(new BigDecimal(backRate)).intValue();
            backMsg = backMsg + "随机概率回传(" + NumberUtil.multiply100(new BigDecimal(backRate)) + "%)";
            if (!isBack) {
                log.error("订单 id[{}]通过回传策略[{}]判断后，不回传，原因：{}", orderId, gameBackPolicy.getId(), backMsg);
                return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
            }
        } else {
            throw new RuntimeException("回传策略[" + gameBackPolicy.getId() + "]配置错误，未知的回传类型：" + backType);
        }

        if (maxBackCountOfUser == null) {
            log.error("订单 id[{}]通过回传策略[{}]判断后，回传，原因：回传概率 {}", orderId, gameBackPolicy.getId(), backMsg);
            return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevels), backMsg);
        }
        long userBackCount = backPolicyCheck.backCountForUser(backUnit, userId, firstPolicy);
        backMsg = backMsg + "，单用户最大回传 " + maxBackCountOfUser + "笔，当前已回传 " + userBackCount + "笔";
        log.error("订单 id[{}]通过回传策略[{}]判断后，是否回传：{}，原因：{}", orderId, gameBackPolicy.getId(), userBackCount < maxBackCountOfUser, backMsg);
        return Tuples.tuple(userBackCount < maxBackCountOfUser, downLevel(rechargeMoney, downLevels), backMsg);
    }

    private static Long downLevel(Long rechargeMoney, List<GameBackPolicyVO.PolicyDownLevel> downLevels) {
        if (CollectionUtils.isEmpty(downLevels)) {
            return rechargeMoney;
        }
        BigDecimal rechargeAmount = NumberUtil.divide100(new BigDecimal(rechargeMoney));
        for (GameBackPolicyVO.PolicyDownLevel downLevel : downLevels) {
            if (rechargeAmount.compareTo(downLevel.getMinMoney()) >= 0 && rechargeAmount.compareTo(downLevel.getMaxMoney()) <= 0) {
                return NumberUtil.multiply100(downLevel.getBackMoney()).longValue();
            }
        }
        return rechargeMoney;
    }

    private static GameBackPolicyVO.PolicyDownLevel transformDownLevel(String downLevel) {
        String[] tmp = downLevel.split("_");
        return GameBackPolicyVO.PolicyDownLevel.builder()
                .minMoney(NumberUtil.divide100(new BigDecimal(Long.parseLong(tmp[0]))))
                .maxMoney(NumberUtil.divide100(new BigDecimal(Long.parseLong(tmp[1]))))
                .backMoney(NumberUtil.divide100(new BigDecimal(Long.parseLong(tmp[2]))))
                .build();
    }

    public interface IBackPolicyCheck {
        /**
         * 按比例回传时单次循环已经回传的人数
         */
        long backCountForFixedRate(int numberOfRound, BackUnitEnum backUnit, Boolean firstPolicy);

        /**
         * 单个用户已回传订单数
         */
        long backCountForUser(BackUnitEnum backUnit, String userId, Boolean firstPolicy);

        /**
         * 补单，按比例回传时单次循环已经回传的人数
         */
        long markUpOfFixedRate(int numberOfRound, Long markUpTime);

        /**
         * 补单，单个用户已回传订单数
         */
        long markUpForUser(String userId, Long markUpTime);

        /**
         * 获取用户的累充金额
         */
        Long totalRechargeAmount();

        /**
         * 单个用户已回传订单数（包含拆单的订单数）
         * Tuple2<回传订单数、回传金额>
         */
        default Tuple2<Long, Long> backCountForUserWithSplitOrder(String userId) {
            throw new RuntimeException("暂不支持！！");
        }
    }
}
