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

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zanxiang.erp.security.annotation.PreAuthorize;
import com.zanxiang.game.back.serve.pojo.BackPolicyOfSplitLevel;
import com.zanxiang.game.back.serve.pojo.BackPolicyOfSumRecharge;
import com.zanxiang.game.back.serve.pojo.dto.GameBackPolicyDTO;
import com.zanxiang.game.back.serve.pojo.dto.GameBackPolicyListDTO;
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.game.back.serve.service.IGameBackPolicyService;
import com.zanxiang.module.util.exception.BaseException;
import com.zanxiang.module.util.pojo.ResultVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping("/policy")
public class BackPolicyController {
    @Autowired
    private IGameBackPolicyService gameBackPolicyService;

    @PreAuthorize(permissionKey = "gameBack:policy:allOfUser")
    @GetMapping("/allOfUser")
    public ResultVO<List<GameBackPolicyVO>> allOfUser() {
        return ResultVO.ok(gameBackPolicyService.allOfUser());
    }

    @PreAuthorize(permissionKey = "gameBack:policy:list")
    @PostMapping("/list")
    public ResultVO<IPage<GameBackPolicyVO>> policyList(@Validated @RequestBody GameBackPolicyListDTO dto) {
        return ResultVO.ok(gameBackPolicyService.policyList(dto));
    }

    @PreAuthorize(permissionKey = "gameBack:policy:create")
    @PostMapping("/add")
    public ResultVO<Boolean> createPolicy(@Validated @RequestBody GameBackPolicyDTO dto) {
        checkDTO(dto);
        return ResultVO.ok(gameBackPolicyService.createPolicy(dto));
    }

    @PreAuthorize(permissionKey = "gameBack:policy:update")
    @PostMapping("/modify/{policyId}")
    public ResultVO<Boolean> updatePolicy(@PathVariable("policyId") Long policyId, @Validated @RequestBody GameBackPolicyDTO dto) {
        checkDTO(dto);
        return ResultVO.ok(gameBackPolicyService.updatePolicy(policyId, dto));
    }

    @PreAuthorize(permissionKey = "gameBack:policy:delete")
    @DeleteMapping("/del/{ids}")
    public ResultVO<Boolean> deletePolicy(@PathVariable("ids") List<Long> ids) {
        throw new BaseException("暂不支持删除回传策略！");
        // return ResultVO.ok(gameBackPolicyService.deletePolicy(ids));
    }

    private void checkDTO(GameBackPolicyDTO dto) {
        if (dto.getPolicyType() == null) {
            dto.setPolicyType(GameBackPolicy.TYPE_DEFAULT);
        }
        if (Objects.equals(dto.getPolicyType(), GameBackPolicy.TYPE_DEFAULT)) {
            checkDefaultDTO(dto);
            return;
        }
        if (Objects.equals(dto.getPolicyType(), GameBackPolicy.TYPE_SUM_RECHARGE)) {
            checkSumRecharge(dto.getTypeOfSumRecharge());
            return;
        }
        if (Objects.equals(dto.getPolicyType(), GameBackPolicy.TYPE_SPLIT_LEVEL)) {
            checkSplitLevel(dto.getTypeOfSplitLevel());
            return;
        }
        throw new BaseException("参数错误！");
    }

    private void checkSplitLevel(BackPolicyOfSplitLevel policyOfSplitLevel) {
        if (policyOfSplitLevel.getRegPayIntervalTime() != null && policyOfSplitLevel.getRegPayIntervalTime() <= 0) {
            throw new BaseException("注册充值回传的最大间隔时间不能小于 1");
        }
        if (CollectionUtils.isEmpty(policyOfSplitLevel.getRechargeLevelList())) {
            throw new BaseException("充值挡位划分不能为空！");
        }
        if (policyOfSplitLevel.getBackCountOfUser() != null && policyOfSplitLevel.getBackCountOfUser() <= 0) {
            throw new BaseException("单用户最大回传订单数配置错误！");
        }

        policyOfSplitLevel.getRechargeLevelList().forEach(obj -> {
            if (obj.getMinAmount() == null || obj.getMinAmount().compareTo(BigDecimal.ZERO) <= 0
                    || obj.getMaxAmount() == null || obj.getMaxAmount().compareTo(BigDecimal.ZERO) <= 0
                    || obj.getBackType() == null || StringUtils.isBlank(obj.getBackRate())) {
                throw new BaseException("挡位划分配置错误！（不能为空，且不能 <= 0）");
            }
        });
        policyOfSplitLevel.getRechargeLevelList().sort((obj1, obj2) -> obj1.getMinAmount().compareTo(obj2.getMaxAmount()));
        BigDecimal maxAmount = BigDecimal.ZERO;
        for (BackPolicyOfSplitLevel.RechargeLevel rechargeLevel : policyOfSplitLevel.getRechargeLevelList()) {
            if (rechargeLevel.getMinAmount().compareTo(maxAmount) < 0) {
                throw new BaseException("挡位划分配置错误！挡位区间不能重合！");
            }
            maxAmount = rechargeLevel.getMinAmount();
            if (rechargeLevel.getMaxAmount().compareTo(maxAmount) < 0) {
                throw new BaseException("挡位划分配置错误！挡位区间不能重合！");
            }
            maxAmount = rechargeLevel.getMaxAmount();
        }
        checkDownLevel(policyOfSplitLevel.getDownLevel());
        checkSplitStrategy(policyOfSplitLevel.getSplitStrategy());
    }

    private void checkSumRecharge(BackPolicyOfSumRecharge policyOfSumRecharge) {
        if (policyOfSumRecharge.getRegPayIntervalTime() != null && policyOfSumRecharge.getRegPayIntervalTime() <= 0) {
            throw new BaseException("注册充值回传的最大间隔时间不能小于 1");
        }
        if (CollectionUtils.isEmpty(policyOfSumRecharge.getRechargeLevelList())) {
            throw new BaseException("挡位划分不能为空");
        }
        policyOfSumRecharge.getRechargeLevelList().forEach(obj -> {
            if (obj.getMinAmount() == null || obj.getMinAmount().compareTo(BigDecimal.ZERO) <= 0
                    || obj.getMaxAmount() == null || obj.getMaxAmount().compareTo(BigDecimal.ZERO) <= 0
                    || obj.getBackCountOfUser() == null || obj.getBackCountOfUser() <= 0) {
                throw new BaseException("挡位划分配置错误！（不能为空，且不能 <= 0）");
            }
        });
        policyOfSumRecharge.getRechargeLevelList().sort((obj1, obj2) -> obj1.getMinAmount().compareTo(obj2.getMaxAmount()));
        BigDecimal maxAmount = BigDecimal.ZERO;
        for (BackPolicyOfSumRecharge.RechargeLevel rechargeLevel : policyOfSumRecharge.getRechargeLevelList()) {
            if (rechargeLevel.getMinAmount().compareTo(maxAmount) < 0) {
                throw new BaseException("挡位划分配置错误！挡位区间不能重合！");
            }
            maxAmount = rechargeLevel.getMinAmount();
            if (rechargeLevel.getMaxAmount().compareTo(maxAmount) < 0) {
                throw new BaseException("挡位划分配置错误！挡位区间不能重合！");
            }
            maxAmount = rechargeLevel.getMaxAmount();
        }
    }

    private void checkDefaultDTO(GameBackPolicyDTO dto) {
        if (dto.getFirstMinMoney() == null) {
            throw new BaseException("参数错误(首充-小额判定金额（小于等于）)！");
        }
        if (dto.getFirstMinMoneyType() == null) {
            throw new BaseException("参数错误(首充-小额回传方式（概率/比例）)！");
        }
        if (StringUtils.isBlank(dto.getFirstMinMoneyRate())) {
            throw new BaseException("参数错误(首充-小额回传概率/比例)！");
        }
        if (dto.getFirstMaxMoney() == null) {
            throw new BaseException("参数错误(首充-大额判定金额（大于等于）)！");
        }
        if (dto.getFirstMaxMoneyType() == null) {
            throw new BaseException("参数错误(首充-大额回传方式（概率/比例）)！");
        }
        if (StringUtils.isBlank(dto.getFirstMaxMoneyRate())) {
            throw new BaseException("参数错误(首充-大额回传概率/比例)！");
        }
        if (dto.getFirstOtherMoneyType() == null) {
            throw new BaseException("参数错误(首充-其它金额回传方式（概率/比例）)！");
        }
        if (StringUtils.isBlank(dto.getFirstOtherMoneyRate())) {
            throw new BaseException("参数错误(首充-其它金额回传概率/比例)！");
        }
        if (dto.getRechargeMinMoney() == null) {
            throw new BaseException("参数错误(次单-小额判定金额（小于等于）)！");
        }
        if (dto.getRechargeMinMoneyType() == null) {
            throw new BaseException("参数错误(次单-小额回传方式（概率/比例）)！");
        }
        if (StringUtils.isBlank(dto.getRechargeMinMoneyRate())) {
            throw new BaseException("参数错误(次单-小额回传概率/比例)！");
        }
        if (dto.getRechargeMaxMoney() == null) {
            throw new BaseException("参数错误(次单-大额判定金额（大于等于）)！");
        }
        if (dto.getRechargeMaxMoneyType() == null) {
            throw new BaseException("参数错误(次单-大额回传方式（概率/比例）)！");
        }
        if (StringUtils.isBlank(dto.getRechargeMaxMoneyRate())) {
            throw new BaseException("参数错误(次单-大额回传概率/比例)！");
        }
        if (dto.getRechargeOtherMoneyType() == null) {
            throw new BaseException("参数错误(次单-其它金额回传方式（概率/比例）)！");
        }
        if (StringUtils.isBlank(dto.getRechargeOtherMoneyRate())) {
            throw new BaseException("参数错误(次单-其它金额回传概率/比例)！");
        }

        BackUnitEnum backUnit = BackUnitEnum.getByValue(dto.getBackUnit());
        if (backUnit == null) {
            throw new BaseException("错误的回传单位：" + dto.getBackUnit());
        }
        if (dto.getFirstMinMoney().compareTo(dto.getFirstMaxMoney()) >= 0) {
            throw new BaseException("首充的大额金额必须大于小额金额");
        }
        if (dto.getRechargeMinMoney().compareTo(dto.getRechargeMaxMoney()) >= 0) {
            throw new BaseException("此单的大额金额必须大于小额金额");
        }
        if (dto.getRegPayIntervalTime() != null && dto.getRegPayIntervalTime() <= 0) {
            throw new BaseException("注册充值回传的最大间隔时间不能小于 1");
        }
        if (dto.getMarkUpOrder() == null) {
            dto.setMarkUpOrder(false);
        }
        if (dto.getMarkUpOrder()) {
            if (dto.getRegPayIntervalTime() == null) {
                throw new BaseException("开启补单后必需填充值注册回传最大间隔时间");
            }
            if (dto.getMarkUpOrderMinMoney().compareTo(dto.getMarkUpOrderMaxMoney()) >= 0) {
                throw new BaseException("首充的大额金额必须大于小额金额");
            }
        }
        if (backUnit == BackUnitEnum.LARGE_AMOUNT) {
            if (dto.getLargeAmount() == null || dto.getLargeAmount().compareTo(BigDecimal.ZERO) <= 0) {
                throw new BaseException("大额判定金额错误！！！");
            }
        }
        checkDownLevel(dto.getFirstDownLevel());
        checkDownLevel(dto.getRechargeDownLevel());
        checkDownLevel(dto.getMarkUpDownLevel());
        checkSplitStrategy(dto.getSplitStrategy());
        if (dto.getFirstBackCountOfUser() != null && dto.getFirstBackCountOfUser() < 1) {
            throw new BaseException("单用户最大回传次数不能小于 1");
        }
        if (dto.getRechargeBackCountOfUser() != null && dto.getRechargeBackCountOfUser() < 1) {
            throw new BaseException("单用户最大回传次数不能小于 1");
        }
        if (dto.getMarkUpBackCountOfUser() != null && dto.getMarkUpBackCountOfUser() < 1) {
            throw new BaseException("单用户最大回传次数不能小于 1");
        }
    }

    private void checkDownLevel(List<GameBackPolicyVO.PolicyDownLevel> downLevelList) {
        if (CollectionUtils.isEmpty(downLevelList)) {
            return;
        }
        downLevelList.sort((val1, val2) -> val1.getMinMoney().compareTo(val2.getMinMoney()));
        BigDecimal compareMoney = null;
        for (GameBackPolicyVO.PolicyDownLevel downLevel : downLevelList) {
            if (downLevel.getMinMoney() == null
                    || downLevel.getMaxMoney() == null
                    || downLevel.getBackMoney() == null) {
                throw new BaseException("降档策略校验失败：金额不能为空");
            }
            if (downLevel.getMinMoney().compareTo(BigDecimal.ZERO) <= 0
                    || downLevel.getMaxMoney().compareTo(BigDecimal.ZERO) <= 0
                    || downLevel.getBackMoney().compareTo(BigDecimal.ZERO) <= 0) {
                throw new BaseException("降档策略校验失败：金额必须大于 0");
            }
            if (downLevel.getMinMoney().compareTo(downLevel.getMaxMoney()) > 0) {
                throw new BaseException("降档策略校验失败：最小金额（" + downLevel.getMinMoney() + "）> 最大金额（" + downLevel.getMaxMoney() + "）");
            }
            if (compareMoney == null) {
                compareMoney = downLevel.getMaxMoney();
            } else {
                if (compareMoney.compareTo(downLevel.getMinMoney()) >= 0) {
                    throw new BaseException("降档策略校验失败：金额区间内不能有交集！！！");
                }
            }
        }
    }

    private void checkSplitStrategy(List<GameBackPolicyVO.SplitStrategy> splitStrategyList) {
        if (CollectionUtils.isEmpty(splitStrategyList)) {
            return;
        }
        splitStrategyList.sort((val1, val2) -> val1.getPayMoney().compareTo(val2.getPayMoney()));
        BigDecimal compareMoney = null;
        for (GameBackPolicyVO.SplitStrategy splitStrategy : splitStrategyList) {
            if (splitStrategy.getPayMoney() == null
                    || CollectionUtils.isEmpty(splitStrategy.getSplitList())
                    || splitStrategy.getBetweenMinuteMin() == null
                    || splitStrategy.getBetweenMinuteMax() == null) {
                throw new BaseException("拆单策略参数错误");
            }
            if (splitStrategy.getPayMoney().compareTo(BigDecimal.ZERO) <= 0) {
                throw new BaseException("拆单策略支付金额错误！[" + splitStrategy.getPayMoney() + "]");
            }
            splitStrategy.getSplitList().forEach(splitMoney -> {
                if (splitMoney == null || splitMoney.compareTo(BigDecimal.ZERO) <= 0) {
                    throw new BaseException("拆单策略拆分金额错误！[" + splitMoney + "]");
                }
            });
            if (splitStrategy.getBetweenMinuteMin() < 1 || splitStrategy.getBetweenMinuteMin() >= 60) {
                throw new BaseException("拆单策略间隔时间错误！[" + splitStrategy.getBetweenMinuteMin() + "]");
            }
            if (splitStrategy.getBetweenMinuteMax() < 1 || splitStrategy.getBetweenMinuteMax() >= 60) {
                throw new BaseException("拆单策略间隔时间错误！[" + splitStrategy.getBetweenMinuteMax() + "]");
            }
            if (splitStrategy.getBetweenMinuteMin().compareTo(splitStrategy.getBetweenMinuteMax()) >= 0) {
                throw new BaseException("拆单策略间隔时间错误！[" + splitStrategy.getBetweenMinuteMin() + ">=" + splitStrategy.getBetweenMinuteMax() + "]");
            }
        }
    }
}
