package com.hzs.member.account.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.constant.MemberFieldConstants;
import com.hzs.common.core.constant.msg.FinanceMsgConstants;
import com.hzs.common.core.constant.msg.SystemMsgConstants;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.CommonUtil;
import com.hzs.common.core.utils.ThreadUtils;
import com.hzs.common.core.utils.TransactionUtils;
import com.hzs.common.core.utils.reflect.ReflectUtils;
import com.hzs.common.domain.member.account.*;
import com.hzs.common.domain.member.base.CuMember;
import com.hzs.common.domain.member.ext.CuMemberAccountExt;
import com.hzs.common.domain.system.config.*;
import com.hzs.common.domain.system.config.ext.BdWithdrawalTaxExt;
import com.hzs.member.account.dto.CuMemberAccountParam;
import com.hzs.member.account.mapper.CuMemberWithdrawMapper;
import com.hzs.member.account.dto.MemberAccountAudit;
import com.hzs.member.account.service.*;
import com.hzs.member.account.vo.CuMemberBankVO;
import com.hzs.member.account.vo.CuMemberPetitionVO;
import com.hzs.member.account.vo.CuMemberTradeVO;
import com.hzs.member.account.vo.CuMemberWithdrawVO;
import com.hzs.member.base.service.ICuMemberService;
import com.hzs.system.base.dto.CurrencyDTO;
import com.hzs.system.config.IWithdrawalAutoServiceApi;
import com.hzs.system.config.IWithdrawalProcessServiceApi;
import com.hzs.system.config.IWithdrawalServiceApi;
import com.hzs.system.config.IWithdrawalTaxServiceApi;
import com.hzs.system.sys.IApprovalServiceApi;
import com.hzs.system.sys.dto.ApprovalSubmitDTO;
import com.hzs.system.sys.dto.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 会员提现表 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2022-09-06
 */
@Service
@Slf4j
public class CuMemberWithdrawServiceImpl extends ServiceImpl<CuMemberWithdrawMapper, CuMemberWithdraw> implements ICuMemberWithdrawService {


    @DubboReference
    IWithdrawalTaxServiceApi withdrawalTaxServiceApi;

    @Autowired
    ICuMemberTradeService cuMemberTradeService;

    @Autowired
    ICuMemberAccountService cuMemberAccountService;

    @Autowired
    ICuMemberBaseService cuMemberBaseService;

    @Autowired
    ICuMemberBankService cuMemberBankService;

    @Autowired
    ICuMemberService cuMemberService;

    @DubboReference
    IWithdrawalAutoServiceApi withdrawalAutoServiceApi;

    @DubboReference
    IWithdrawalProcessServiceApi withdrawalProcessServiceApi;


    @DubboReference
    IApprovalServiceApi approvalServiceApi;


    @Override
    public List<CuMemberWithdraw> getWithdrawTimes(Long pkMember) {
        return baseMapper.getWithdrawTimes(pkMember);
    }

    @Override
    public CuMemberWithdraw selectWithdrawByCode(String code) {
        //根据单号查询充值信息
        QueryWrapper<CuMemberWithdraw> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("WITHDRAW_CODE", code);
        queryWrapper.eq("DEL_FLAG", EDelFlag.UN_DELETE.getValue());
        return getOne(queryWrapper);
    }


    @Override
    public List<CuMemberWithdraw> selectWithdrawByBatch(String batchNO) {
        //根据单号查询充值信息
        QueryWrapper<CuMemberWithdraw> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("BATCH", batchNO);
        return baseMapper.selectList(queryWrapper);
    }


    private BigDecimal[] getIncomeTax(BdWithdrawalTaxExt withdrawalTax, Integer pkCountry, BigDecimal curCashAmount) {
        //个税比例
        BigDecimal incomeTax = BigDecimal.ZERO;
        BigDecimal lowerBound = BigDecimal.ZERO;
        //计算类型
        Integer serviceType = withdrawalTax.getServiceType();
        //获取个税列表配置
        List<BdWithdrawalTaxDetails> withdrawalTaxDetails = withdrawalTax.getWithdrawalTaxDetailsList();
        if (CollUtil.isNotEmpty(withdrawalTaxDetails)) {
            for (BdWithdrawalTaxDetails bdWithdrawalTaxDeatail : withdrawalTaxDetails) {
                lowerBound = bdWithdrawalTaxDeatail.getLowerBound();
                BigDecimal upperBound = bdWithdrawalTaxDeatail.getUpperBound();
                BigDecimal ratio = bdWithdrawalTaxDeatail.getRatio();
                if (curCashAmount.compareTo(upperBound) <= 0 && curCashAmount.compareTo(lowerBound) >= 0) {
                    incomeTax = ratio;
                    break;
                }
            }
        }
        incomeTax = serviceType.equals(ECalType.RATIO.getValue()) ? incomeTax.divide(new BigDecimal("100"), 4, BigDecimal.ROUND_HALF_UP) : incomeTax;
        return new BigDecimal[]{lowerBound, incomeTax};
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer saveMemberWithdrawInfo(CuMemberWithdraw cuMemberWithdraw) {
        Integer row = baseMapper.insert(cuMemberWithdraw);
        this.updateTradeAndBalancd(cuMemberWithdraw, EOperationMethod.INSERT);
        return row;

    }

    /**
     * 更新交易流水和余额
     *
     * @param cuMemberWithdraw 提现信息
     * @param eMethodType      提现方式
     */
    public Integer updateTradeAndBalancd(CuMemberWithdraw cuMemberWithdraw, EOperationMethod eMethodType) {
        CuMemberTrade cuMemberTrade = this.getCuMemberTrade(cuMemberWithdraw, eMethodType);
        cuMemberTradeService.save(cuMemberTrade);
        //更新余额表
        Integer pkAccount = cuMemberWithdraw.getPkAccount();
        int accountType = cuMemberBaseService.getAccount(pkAccount).getFieldValue();
        //提现金额
        BigDecimal cashAmount = cuMemberWithdraw.getCashAmount();
        BigDecimal amount = eMethodType.equals(EOperationMethod.INSERT) ? cashAmount.negate() : cashAmount;
        CuMemberAccountParam param = CuMemberAccountParam.builder().pkMember(cuMemberWithdraw.getPkMember())
                .accountType(accountType).amount(amount).pkModified(cuMemberWithdraw.getPkCreator())
                .accountClassify(ETradeClassify.WITHDRAWAL.getValue()).pkCountry(cuMemberWithdraw.getPkCountry())
                .transferType(ETransferType.TRANSFER_IN.getValue()).build();
        return cuMemberAccountService.updateMemberAccountByMemberCode(param);
    }

    /**
     * 构造交易明细
     *
     * @param cuMemberWithdraw 提现信息
     * @return CuMemberTrade
     */
    private CuMemberTrade getCuMemberTrade(CuMemberWithdraw cuMemberWithdraw, EOperationMethod eMethodType) {
        Long pkMember = cuMemberWithdraw.getPkMember();
        //提现金额
        BigDecimal tradeAmount = cuMemberWithdraw.getCashAmount();
        BigDecimal amount = eMethodType.equals(EOperationMethod.INSERT) ? tradeAmount.negate() : tradeAmount;
        String remarks = eMethodType.equals(EOperationMethod.INSERT) ? FinanceMsgConstants.WITHDRAWAL : cuMemberWithdraw.getPayerRemarks();
        //交易编号
        String tradeCode = eMethodType.equals(EOperationMethod.INSERT) ? cuMemberWithdraw.getWithdrawCode() : CommonUtil.createSerialNumber(EOrderPrefix.WITHDRAWAL_CODE.getValue());
        //来源编号
        String sourceCode = eMethodType.equals(EOperationMethod.INSERT) ? cuMemberWithdraw.getWithdrawCode() : cuMemberWithdraw.getBatch();
        Integer tradeType = eMethodType.equals(EOperationMethod.INSERT) ? ETradeType.WITHDRAW.getValue() : ETradeType.WITHDRAWAL_REFUSED.getValue();
        Integer pkAccount = cuMemberWithdraw.getPkAccount();
        //账户值
        Integer accountValue = cuMemberBaseService.getAccountValueById(pkAccount);
        //查询余额
        BigDecimal balance = cuMemberAccountService.selectBalanceByMemberCode(pkMember, accountValue);
        CuMemberTrade memberTrade = CuMemberTrade.builder().pkMember(pkMember)
                .tradeCode(tradeCode)
                .pkAccount(pkAccount)
                .tradeType(tradeType)
                .tradeClassify(ETradeClassify.WITHDRAWAL.getValue())
                .pkRate(cuMemberWithdraw.getPkRate())
                .tradeAmount(amount)
                .tradeBeforeBalance(balance)
                .tradeBalance(balance.add(amount))
                .sourceCode(sourceCode)
                .tradeStatue(ETradeStatus.TAKE_EFFECT.getValue())
                .remarks(remarks)
                .build();
        memberTrade.setPkCountry(cuMemberWithdraw.getPkCountry());
        memberTrade.setPkCreator(cuMemberWithdraw.getPkCreator());
        return memberTrade;
    }

    @Override
    public Integer updateWithdrawByCode(MemberAccountAudit memberAccountAudit) {
        CuMemberWithdraw cuMemberWithdraw = new CuMemberWithdraw();
        BeanUtils.copyProperties(memberAccountAudit, cuMemberWithdraw);
        cuMemberWithdraw.setWithdrawCode(memberAccountAudit.getBusinessCode());
        return baseMapper.updateWithdrawByCode(cuMemberWithdraw);
    }


    @Override
    public Object[] selectMemberWithdrawList(CuMemberWithdrawVO memberWithdrawVO) {
        CuMemberWithdrawVO cuMemberWithdrawVO;
        List<CuMemberWithdrawVO> cuMemberWithdrawVoS = new ArrayList<>();
        List<CuMemberWithdrawExt> cuMemberWithdrawExts = baseMapper.selectMemberWithdrawList(memberWithdrawVO);
        if (CollUtil.isNotEmpty(cuMemberWithdrawExts)) {
            for (CuMemberWithdrawExt cuMemberWithdrawExt : cuMemberWithdrawExts) {
                cuMemberWithdrawVO = new CuMemberWithdrawVO();
                BeanUtils.copyProperties(cuMemberWithdrawExt, cuMemberWithdrawVO);
                this.setPublicParam(cuMemberWithdrawVO, cuMemberWithdrawExt);
                cuMemberWithdrawVoS.add(cuMemberWithdrawVO);
            }
            //总计
            CuMemberWithdrawExt cuMemberWithdrawExt = baseMapper.selectMemberWithdrawListTotal(memberWithdrawVO);
            cuMemberWithdrawVoS.add(BeanUtil.copyProperties(cuMemberWithdrawExt, CuMemberWithdrawVO.class));
        }
        Object[] objects = new Object[]{cuMemberWithdrawExts, cuMemberWithdrawVoS};
        return objects;

    }


    /**
     * 页面显示公用参数
     *
     * @param cuMemberWithdrawVO 提现VO
     * @param memberWithdraw     提现信息
     */
    private void setPublicParam(CuMemberWithdrawVO cuMemberWithdrawVO, CuMemberWithdrawExt memberWithdraw) {
        BigDecimal exchangeRate;
        Integer pkRate = memberWithdraw.getPkRate();
        if (null != pkRate) {
            //汇率
            exchangeRate = cuMemberBaseService.getCurrencyById(memberWithdraw.getPkRate()).getInExchangeRate();
        } else {
            //取最新的汇率
            CurrencyDTO currencyDTO = cuMemberBaseService.getCurrency(cuMemberWithdrawVO.getPkCountry());
            exchangeRate = currencyDTO.getInExchangeRate();
        }

        //查询提现账户
        Integer pkAccount = memberWithdraw.getPkAccount();
        Integer accountsType = cuMemberBaseService.getAccountValueById(pkAccount);
        //查询账户余额
        CuMemberAccount cuMemberAccount = cuMemberAccountService.queryCuMemberAccountByPkMember(memberWithdraw.getPkMember());
        BigDecimal availableBalance;
        if (accountsType.equals(EAccount.BONUS.getValue())) {
            BigDecimal balance = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.WITHDRAW_ACCOUNT + accountsType);
            BigDecimal lockAccount = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + accountsType);
            availableBalance = null != lockAccount ? balance.subtract(lockAccount) : balance;
        } else {
            availableBalance = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.ACCOUNT + accountsType);
            BigDecimal lockAccount = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.LOCK_ACCOUNT + accountsType);
            BigDecimal lockTransferAccount = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.LOCK_TRANSFER_ACCOUNT + accountsType);
            if (null != lockAccount && null != lockTransferAccount) {
                availableBalance = availableBalance.subtract(lockAccount).subtract(lockTransferAccount);
            }
        }
        availableBalance = null == availableBalance ? BigDecimal.ZERO : availableBalance;
        cuMemberWithdrawVO.setAvailableAmount(availableBalance.add(memberWithdraw.getCashAmount()));
        cuMemberWithdrawVO.setAvailableBalance(availableBalance);

        //提现金额
        BigDecimal settleCashAmount = memberWithdraw.getCashAmount().divide(exchangeRate, 4, BigDecimal.ROUND_HALF_UP);
        //个税
        BigDecimal settleIncomeTax = memberWithdraw.getIncomeTax().divide(exchangeRate, 4, BigDecimal.ROUND_HALF_UP);
        //手续费
        BigDecimal settleServiceCharge = memberWithdraw.getServiceCharge().divide(exchangeRate, 4, BigDecimal.ROUND_HALF_UP);
        //实发金额
        BigDecimal settleIssuedAmount = memberWithdraw.getIssuedAmount().divide(exchangeRate, 4, BigDecimal.ROUND_HALF_UP);

        cuMemberWithdrawVO.setExchangeRate(exchangeRate);
        cuMemberWithdrawVO.setSettleIncomeTax(settleIncomeTax);
        cuMemberWithdrawVO.setSettleServiceCharge(settleServiceCharge);
        cuMemberWithdrawVO.setSettleCashAmount(settleCashAmount);
        cuMemberWithdrawVO.setSettleIssuedAmount(settleIssuedAmount);
        cuMemberWithdrawVO.setPkAccount(cuMemberBaseService.translateAccountValue(pkAccount));
    }


    @Override
    public CuMemberWithdrawVO queryCuMemberWithdrawDetail(Long pkId) {
        CuMemberWithdrawVO memberRechargeDetailVo = new CuMemberWithdrawVO();
        CuMemberWithdrawExt memberWithdrawExt = baseMapper.queryCuMemberWithdrawDetail(pkId);
        BeanUtils.copyProperties(memberWithdrawExt, memberRechargeDetailVo);
        setPublicParam(memberRechargeDetailVo, memberWithdrawExt);
        return memberRechargeDetailVo;
    }

    @Override
    public Integer withdrawPaymentByPkId(CuMemberWithdrawVO memberWithdrawVO) {
        CuMemberWithdrawExt cuMemberWithdraw = new CuMemberWithdrawExt();
        BeanUtils.copyProperties(memberWithdrawVO, cuMemberWithdraw);
        return baseMapper.withdrawPaymentByPkId(cuMemberWithdraw);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer withdrawPaymentPositiveByPkId(CuMemberWithdrawVO memberWithdrawVO) {
        //更新提现的打款充正的状态
        CuMemberWithdrawExt cuMemberWithdraw = new CuMemberWithdrawExt();
        BeanUtils.copyProperties(memberWithdrawVO, cuMemberWithdraw);
        Integer row = baseMapper.withdrawPaymentByPkId(cuMemberWithdraw);

        List<CuMemberWithdraw> cuMemberWithdraws = baseMapper.selectBatchIds(memberWithdrawVO.getPkIds());
        for (CuMemberWithdraw memberWithdraw : cuMemberWithdraws) {
            memberWithdraw.setPayerRemarks(memberWithdrawVO.getPayerRemarks());
            this.updateTradeAndBalancd(memberWithdraw, EOperationMethod.UPDATE);
        }
        return row;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void autoWithdraw(BdWithdrawal withdrawal) {
        Integer pkCountry = withdrawal.getPkCountry();
        if (Boolean.TRUE.equals(isWithdrawalCycle(pkCountry))) {
            //查询提现到的币种
            List<BdAccount> bdAccounts = cuMemberBaseService.getAccountByCountry(EAccountProperty.IS_WITHDRAWAL.getValue(), pkCountry);
            Integer accountsType = bdAccounts.get(0).getFieldValue();
            //查询会员币种余额、锁定金额
            List<CuMemberAccountExt> cuMemberAccountExts = cuMemberAccountService.queryMemberAccountByPkcountry(pkCountry);
            memberWithDrawal(withdrawal, cuMemberAccountExts, bdAccounts, accountsType, pkCountry);
        }
    }

    /**
     * 会员提现
     *
     * @param withdrawal          提现配置信息
     * @param cuMemberAccountExts 会员币种表
     * @param bdAccounts          币种信息
     * @param accountsType        配置的提现币种
     * @param pkCountry           国家ID
     */
    public void memberWithDrawal(BdWithdrawal withdrawal, List<CuMemberAccountExt> cuMemberAccountExts, List<BdAccount> bdAccounts, Integer accountsType, Integer pkCountry) {
        //会员ID 银行卡ID
        Long pkMember;
        Long pkBank;
        //余额 锁定金额
        BigDecimal balance, lockAccount;
        //最高自动提现金额
        BigDecimal upperBound = withdrawal.getUpperBound();
        //最低自动提现金额
        BigDecimal lowerBound = withdrawal.getLowerBound();
        //配置文件中的提现次数
        Integer withdrawalNumber = withdrawal.getWithdrawalNumber();
        if (CollUtil.isNotEmpty(cuMemberAccountExts)) {
            //查询每个会员正在参与审核的次数
            List<CuMemberWithdrawExt> withdrawTimesByPkCountry = baseMapper.getWithdrawTimesByPkCountry(pkCountry);
            Map<Long, Integer> withdrawTimes = withdrawTimesByPkCountry.stream().collect(Collectors.toMap(CuMemberWithdrawExt::getPkMember, CuMemberWithdrawExt::getTimes));
            //汇率
            CurrencyDTO currencyDTO = cuMemberBaseService.getCurrency(pkCountry);
            for (CuMemberAccountExt cuMemberAccountExt : cuMemberAccountExts) {
                pkBank = cuMemberAccountExt.getPkBank();
                //是否绑定银行卡
                CuMemberBankVO memberBank = cuMemberBankService.selectCuMemberBankById(pkBank);
                log.info("----------是否绑定银行卡");
                if (null != memberBank) {
                    log.info("----------绑定银行卡");
                    pkMember = cuMemberAccountExt.getPkMember();
                    balance = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.WITHDRAW_ACCOUNT + accountsType);
                    lockAccount = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + accountsType);
                    if (lockAccount.compareTo(BigDecimal.ZERO) > 0) {
                        balance = balance.subtract(lockAccount);
                    }
                    //是否取整
                    balance = computeRounding(withdrawal, balance);
                    // 提现金额在配置金额之间
                    if (balance.compareTo(lowerBound) >= 0 && balance.compareTo(upperBound) <= 0) {
                        log.info("----------提现开始");
                        Integer times = withdrawTimes.get(pkMember) == null ? 0 : withdrawTimes.get(pkMember);
                        //比较正在提现次数与配置的最大提现次数
                        if (times <= withdrawalNumber) {
                            //本次应缴个税
                            BigDecimal payIncomeTax = computeIncomeTaxValue(pkMember, balance, pkCountry, lowerBound);
                            //手续费金额
                            BigDecimal serviceChargeAmount = computeServiceCharge(pkCountry, balance);
                            BigDecimal issuedAmount = balance.subtract(payIncomeTax).subtract(serviceChargeAmount);
                            String code = CommonUtil.createSerialNumber(EOrderPrefix.WITHDRAWAL_CODE.getValue());
                            CuMember member = cuMemberService.getMember(pkMember);
                            String remarks = TransactionUtils.getContent(FinanceMsgConstants.AUTOMATIC_WITHDRAWAL_APPLICATION, member.getMemberCode(), balance.toString());
                            CuMemberWithdraw cuMemberWithdraw = CuMemberWithdraw.builder().pkMember(pkMember)
                                    .pkAccount(bdAccounts.get(0).getPkId()).pkBank(pkBank)
                                    .pkRate(currencyDTO.getPkId()).cashAmount(balance)
                                    .serviceCharge(serviceChargeAmount).incomeTax(payIncomeTax)
                                    .issuedAmount(issuedAmount).withdrawCode(code).remarks(remarks).build();
                            cuMemberWithdraw.setApproveState(EApproveStatus.WAIT_SUBMIT.getValue());
                            cuMemberWithdraw.setDelFlag(EDelFlag.UN_DELETE.getValue());
                            cuMemberWithdraw.setPkCountry(pkCountry);
                            cuMemberWithdraw.setPkCreator(pkMember);
                            //保存提现、交易流水、余额信息
                            baseMapper.insert(cuMemberWithdraw);
                            this.updateTradeAndBalancd(cuMemberWithdraw, EOperationMethod.INSERT);
                            log.info("----------提现国家{}完成" , pkCountry);

                        }
                    }
                }
            }
        }
    }

    /**
     * 查询自动提现的时间
     *
     * @param pkCountry 国家
     * @return Boolean
     */
    public Boolean isWithdrawalCycle(Integer pkCountry) {
        //当前时间位于星期的第几天
        LocalDate localDate = LocalDate.now();
        DayOfWeek dayOfWeek = localDate.getDayOfWeek();
        Integer dayOfWeekNum = dayOfWeek.getValue();
        //自动提现配置的提现周期
        List<BdWithdrawalAuto> listR = withdrawalAutoServiceApi.queryWithdrawalAuto(pkCountry).getData();
        for (BdWithdrawalAuto withdrawalAuto : listR) {
            Integer withdrawalCycle = withdrawalAuto.getWithdrawalCycle();
            if (dayOfWeekNum.equals(withdrawalCycle)) {
                return true;
            }

        }
        return false;
    }

    @Override
    public BigDecimal getBalance(Long pkMember, Integer pkCountry, Integer accountsType) {
        //提现账户
        if (null == accountsType) {
            List<BdAccount> bdAccounts = cuMemberBaseService.getAccountByCountry(EAccountProperty.IS_WITHDRAWAL.getValue(), pkCountry);
            accountsType = bdAccounts.get(0).getFieldValue();
        }
        //查询账户余额
        return cuMemberAccountService.selectBalanceByMemberCode(pkMember, accountsType);
    }

    @Override
    public BigDecimal computeIncomeTaxValue(Long pkMember, BigDecimal cashAmount, Integer pkCountry, BigDecimal minAmount) {
        //获取个税配置
        R<BdWithdrawalTaxExt> bdWithdrawalTaxExtR = withdrawalTaxServiceApi.queryWithdrawalTax(pkCountry);
        BdWithdrawalTaxExt withdrawalTax = bdWithdrawalTaxExtR.getData();
        if (null == withdrawalTax) {
            return BigDecimal.ZERO;
        }
        Integer cycle = withdrawalTax.getTaxCycle();

        BigDecimal monthCashAmount = BigDecimal.ZERO;
        BigDecimal monthTax = BigDecimal.ZERO;
        //查询周期内提现金额、总个税
        CuMemberWithdraw cuMemberWithdraw = baseMapper.getIncomeTaxByCycle(pkMember, cycle);
        if (null != cuMemberWithdraw) {
            monthCashAmount = cuMemberWithdraw.getCashAmount();
            monthTax = cuMemberWithdraw.getIncomeTax();
        }
        // 当月提现额度 + 本次提现额度 = 当前提现金额
        BigDecimal curCashAmount = monthCashAmount.add(cashAmount);
        //个税配置信息
        BigDecimal[] taxConfig = getIncomeTax(withdrawalTax, pkCountry, curCashAmount);
        //参加提税的金额(总提税金额-最低个税金额)
        curCashAmount = curCashAmount.subtract(taxConfig[0]);
        //当月总个税 = 当前提现金额*个税比例
        BigDecimal totalTax = curCashAmount.multiply(taxConfig[1]).setScale(4, BigDecimal.ROUND_HALF_UP);
        //当总所得税小于当月已缴所得税时，本交不交所得税
        if (totalTax.compareTo(monthTax) < 0) {
            return BigDecimal.ZERO;
        }
        // 本次应缴所得税 = 总所得税 - 当月已缴费所得税
        return totalTax.subtract(monthTax);
    }

    @Override
    public BigDecimal computeServiceCharge(Integer pkCountry, BigDecimal cashAmount) {
        BdWithdrawalProcess withdrawalProcess = withdrawalProcessServiceApi.queryBdWithdrawalProcess(pkCountry).getData();
        //手续费类型
        Integer serviceType = withdrawalProcess.getServiceType();
        BigDecimal serviceRatio = withdrawalProcess.getServiceRatio();
        //按金额
        if (serviceType.equals(ECalType.VALUE.getValue())) {
            return serviceRatio;
        } else {//按比例
            //转化为百分比比率
            BigDecimal serviceChargeeRatio = serviceRatio.divide(new BigDecimal("100"), 4, BigDecimal.ROUND_HALF_UP);
            //手续费金额 = 本次提现金额 * 手续费比例
            return cashAmount.multiply(serviceChargeeRatio).setScale(4, BigDecimal.ROUND_HALF_UP);
        }

    }

    @Override
    public BigDecimal computeRounding(BdWithdrawal bdWithdrawal, BigDecimal cashAmount) {
        BigDecimal roundIngAmount = cashAmount;
        Integer isRounding = bdWithdrawal.getIsRounding();
        if (isRounding.equals(EYesNo.YES.getIntValue())) {
            //向下取整
            roundIngAmount = cashAmount.setScale(0, BigDecimal.ROUND_DOWN);
        }
        return roundIngAmount;
    }


    @Override
    public List<CuMemberWithdraw> getWithdrawApproveStateByIds(List<Long> pkIds, Integer approveState) {
        return baseMapper.getWithdrawApproveStateByIds(pkIds, approveState);
    }


    @Override
    public CuMemberPetitionVO showMemberWithdrawPetition(List<Long> pkIds, Integer approveState) {
        CuMemberPetitionVO memberPetitionVo = new CuMemberPetitionVO();
        memberPetitionVo.setPkIds(pkIds);
        memberPetitionVo.setBusinessNo(CommonUtil.createSerialNumber(EOrderPrefix.WITHDRAWAL_CODE.getValue()));
        memberPetitionVo.setBusinessType(EApprovalBusiness.WITHDRAWAL.getValue());
        //查询业务数据
        List<CuMemberWithdrawVO> memberWithdrawList = BeanUtil.copyToList(baseMapper.showMemberWithdrawPetition(pkIds, approveState), CuMemberWithdrawVO.class);
        memberPetitionVo.setMemberWithdrawList(memberWithdrawList);
        return memberPetitionVo;
    }


    @Override
    public List<CuMemberWithdrawVO> checkWithdrawPetitionByState(List<Long> pkIds, Integer approveState) {
        return BeanUtil.copyToList(baseMapper.showMemberWithdrawPetition(pkIds, approveState), CuMemberWithdrawVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer confirmWithdrawPetition(CuMemberPetitionVO memberPetitionVo) {
        List<Long> pkIds = memberPetitionVo.getPkIds();
        String businessNo = memberPetitionVo.getBusinessNo();
        LoginUser loginUser = memberPetitionVo.getLoginUser();
        CuMemberWithdrawExt cuMemberWithdrawExt = new CuMemberWithdrawExt();
        cuMemberWithdrawExt.setBatch(businessNo);
        cuMemberWithdrawExt.setPkIds(pkIds);
        cuMemberWithdrawExt.setApproveState(EApproveStatus.ALREADY_SUBMIT.getValue());
        cuMemberWithdrawExt.setPkModified(loginUser.getUserId());
        //修改审批状态 批次
        Integer rows = baseMapper.withdrawPaymentByPkId(cuMemberWithdrawExt);
        //修改交易流水表中sourceCode 为批次号
        List<CuMemberWithdrawExt> cuMemberWithdrawExts = baseMapper.showMemberWithdrawPetition(pkIds, null);
        List<String> withdrawCodeList = cuMemberWithdrawExts.stream().map(CuMemberWithdrawExt::getWithdrawCode).collect(Collectors.toList());
        CuMemberTradeVO memberTradeVO = CuMemberTradeVO.builder().sourceCode(businessNo)
                .tradeCodes(withdrawCodeList).pkModified(loginUser.getUserId()).build();
        cuMemberTradeService.updateSourceCodeByTradeCode(memberTradeVO);

        List<CuMemberWithdrawVO> memberWithdrawList = memberPetitionVo.getMemberWithdrawList();
        //提交提现用户
        List<Long> pkMemberList = cuMemberWithdrawExts.stream().map(CuMemberWithdrawExt::getPkMember).collect(Collectors.toList());
        Set<Long> pkMembers = CollUtil.newHashSet(pkMemberList);
        ApprovalSubmitDTO approvalSubmitDTO = ApprovalSubmitDTO.builder().eApprovalBusiness(EApprovalBusiness.WITHDRAWAL)
                .businessCode(businessNo).businessData(JSONUtil.toJsonStr(memberWithdrawList))
                .signType(ESignType.getEnumByValue(memberPetitionVo.getSignType())).sendIdList(memberPetitionVo.getSendIdList())
                .userIdList(memberPetitionVo.getUserIdList())
                .remark(memberPetitionVo.getDescription())
                .pkMemberList(pkMembers).build();
        //调用审批接口
        R<String> submit = approvalServiceApi.submit(approvalSubmitDTO, loginUser);
        if (!submit.isSuccess()) {
            throw new RuntimeException(submit.getMsg());
        }
        return rows;
    }

    @Override
    public Object[] selectMemberWithdrawListByPkMember(Long pkMember, Integer pkCountry) {
        CuMemberWithdrawVO cuMemberWithdrawVO;
        List<CuMemberWithdrawVO> cuMemberWithdrawVOList = new ArrayList<>();
        List<CuMemberWithdrawExt> cuMemberWithdrawList = baseMapper.selectMemberWithdrawListByPkMember(pkMember, pkCountry);
        if (CollUtil.isNotEmpty(cuMemberWithdrawList)) {
            //查询币种值
            List<BdAccount> allAccounts = cuMemberBaseService.getAccountByCountryId(pkCountry);
            Map<Integer, BdAccount> map = allAccounts.stream().collect(Collectors.toMap(BdAccount::getPkId, o -> o));
            for (CuMemberWithdrawExt ext : cuMemberWithdrawList) {
                cuMemberWithdrawVO = BeanUtil.copyProperties(ext, CuMemberWithdrawVO.class);
                BdAccount bdAccount = map.get(ext.getPkAccount());
                if (null != bdAccount) {
                    cuMemberWithdrawVO.setPkAccount(bdAccount.getPkTransactionKey());
                }
                cuMemberWithdrawVOList.add(cuMemberWithdrawVO);
            }
        }
        return new Object[]{cuMemberWithdrawList, cuMemberWithdrawVOList};
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateWithdrawStatusByPkId(Long pkId, Long pkModified) {
        CuMemberWithdraw cuMemberWithdraw = baseMapper.selectById(pkId);
        //回退金额
        BigDecimal backAmount = cuMemberWithdraw.getCashAmount();
        if (backAmount.compareTo(BigDecimal.ZERO) > 0) {
            //插入交易明细表
            cuMemberTradeService.save(getCuMemberTradeInfo(cuMemberWithdraw));
            //更新余额表
            CuMemberAccount cuMemberAccount = CuMemberAccount.builder()
                    .account4(backAmount)
                    .withdrawAccount4(backAmount)
                    .pkMember(cuMemberWithdraw.getPkMember())
                    .build();
            cuMemberAccount.setPkCountry(cuMemberWithdraw.getPkCountry());
            cuMemberAccountService.updateMemberAccount(cuMemberAccount, pkModified);
        }
        return baseMapper.updateWithdrawStatusByPkId(pkId, pkModified);
    }

    /**
     * 获取交易流水信息
     *
     * @param cuMemberWithdraw 提现信息
     * @return CuMemberTrade
     */
    private CuMemberTrade getCuMemberTradeInfo(CuMemberWithdraw cuMemberWithdraw) {
        Long pkMember = cuMemberWithdraw.getPkMember();
        Integer pkAccount = cuMemberWithdraw.getPkAccount();
        BdAccount account = cuMemberBaseService.getAccount(pkAccount);
        //交易金额
        BigDecimal tradeAmount = cuMemberWithdraw.getCashAmount();
        //查询余额
        BigDecimal balance = cuMemberAccountService.selectBalanceByMemberCode(pkMember, account.getFieldValue());
        CuMemberTrade memberTrade = CuMemberTrade.builder().pkMember(pkMember)
                .tradeCode(CommonUtil.createSerialNumber(EOrderPrefix.WITHDRAWAL_CODE.getValue()))
                .pkAccount(pkAccount)
                .tradeType(ETradeType.WITHDRAW.getValue())
                .tradeClassify(ETradeClassify.WITHDRAWAL.getValue())
                .pkRate(cuMemberWithdraw.getPkRate())
                .tradeAmount(tradeAmount)
                .tradeBeforeBalance(balance)
                .tradeBalance(balance.add(tradeAmount))
                .sourceCode(cuMemberWithdraw.getWithdrawCode())
                .tradeStatue(ETradeStatus.TAKE_EFFECT.getValue())
                .pkMember(pkMember)
                .remarks(FinanceMsgConstants.WITHDRAWAL_CANCELLATION)
                .build();
        memberTrade.setPkCountry(cuMemberWithdraw.getPkCountry());
        return memberTrade;
    }

}
