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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.hzs.common.core.constant.CountryConstants;
import com.hzs.common.core.constant.EnumsPrefixConstants;
import com.hzs.common.core.constant.MemberFieldConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.CommonUtil;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.core.utils.reflect.ReflectUtils;
import com.hzs.common.domain.member.account.CuMemberAccount;
import com.hzs.common.domain.member.account.CuMemberRecharge;
import com.hzs.common.domain.member.account.CuMemberTrade;
import com.hzs.common.domain.member.account.CuMemberTradeExt;
import com.hzs.common.domain.member.ext.CuMemberAccountExt;
import com.hzs.common.domain.system.config.BdAccount;
import com.hzs.common.service.ITransactionCommonService;
import com.hzs.member.account.dto.*;
import com.hzs.member.account.mapper.CuMemberTradeMapper;
import com.hzs.member.account.service.ICuMemberAccountService;
import com.hzs.member.account.service.ICuMemberBaseService;
import com.hzs.member.account.service.ICuMemberRechargeService;
import com.hzs.member.account.service.ICuMemberTradeService;
import com.hzs.member.account.vo.CuMemberTradeDetailVO;
import com.hzs.member.account.vo.CuMemberTradeVO;
import com.hzs.member.achieve.service.impl.CuMemberBonusSettle;
import com.hzs.system.base.dto.CurrencyDTO;
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.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 会员交易明细 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2022-09-06
 */
@Service
public class CuMemberTradeServiceImpl extends ServiceImpl<CuMemberTradeMapper, CuMemberTrade> implements ICuMemberTradeService {

    @Autowired
    ICuMemberBaseService cuMemberBaseService;
    @Autowired
    ICuMemberAccountService cuMemberAccountService;

    @Autowired
    ICuMemberRechargeService cuMemberRechargeService;

    @Autowired
    ITransactionCommonService iTransactionCommonService;

    private CuMemberBonusSettle cuMemberBonusSettle;

    @Autowired
    public void setCuMemberBonusSettle(CuMemberBonusSettle cuMemberBonusSettle) {
        this.cuMemberBonusSettle = cuMemberBonusSettle;
    }

    @Override
    public List<CuMemberTrade> queryCuMemberTrade(Long pkMember, String sourceCode) {
        return baseMapper.queryCuMemberTrade(pkMember, sourceCode);
    }

    @Override
    public Object[] selectMemberTradeList(CuMemberTradeVO cuMemberTradeVO) {
        CuMemberTradeVO memberTradeVO;
        List<CuMemberTradeVO> cuMemberTradeVoS = new ArrayList<>();
        List<CuMemberTradeExt> cuMemberTradeExts = baseMapper.selectMemberTradeList(cuMemberTradeVO);
        if (CollUtil.isNotEmpty(cuMemberTradeExts)) {
            for (CuMemberTradeExt cuMemberTradeExt : cuMemberTradeExts) {
                memberTradeVO = new CuMemberTradeVO();
                BeanUtils.copyProperties(cuMemberTradeExt, memberTradeVO);
                this.setPublicParam(memberTradeVO, cuMemberTradeExt);
                cuMemberTradeVoS.add(memberTradeVO);
            }
        }
        return new Object[]{cuMemberTradeExts, cuMemberTradeVoS};
    }

    /**
     * 页面显示公用参数
     *
     * @param cuMemberTradeVO 交易明细VO
     * @param memberTradeExt  交易明细信息
     */
    private void setPublicParam(CuMemberTradeVO cuMemberTradeVO, CuMemberTradeExt memberTradeExt) {
        BigDecimal exchangeRate;
        Integer pkRate = memberTradeExt.getPkRate();
        if (null != pkRate) {
            //汇率
            exchangeRate = cuMemberBaseService.getCurrencyById(pkRate).getInExchangeRate();
        } else {
            //取最新的汇率
            CurrencyDTO currencyDTO = cuMemberBaseService.getCurrency(cuMemberTradeVO.getPkCountry());
            exchangeRate = currencyDTO.getInExchangeRate();
        }
        //交易金额
        BigDecimal settleTradeAmount = null != exchangeRate ? memberTradeExt.getTradeAmount().divide(exchangeRate, 4, RoundingMode.HALF_UP) : BigDecimal.ZERO;
        //交易余额
        BigDecimal settleTradeBalance = null != exchangeRate ? memberTradeExt.getTradeBalance().divide(exchangeRate, 4, RoundingMode.HALF_UP) : BigDecimal.ZERO;
        //历史余额
        BigDecimal settleTradeBeforeBalance = null != exchangeRate ? memberTradeExt.getTradeBeforeBalance().divide(exchangeRate, 4, RoundingMode.HALF_UP) : BigDecimal.ZERO;
        //翻译Key
        Integer pkAccount = cuMemberTradeVO.getPkAccount();
        cuMemberTradeVO.setPkAccount(cuMemberBaseService.translateAccountValue(pkAccount));
        cuMemberTradeVO.setExchangeRate(exchangeRate);
        cuMemberTradeVO.setSettleTradeAmount(settleTradeAmount);
        cuMemberTradeVO.setSettleTradeBeforeBalance(settleTradeBeforeBalance);
        cuMemberTradeVO.setSettleTradeBalance(settleTradeBalance);
    }

    @Override
    public Integer batchSaveTradeByMemberCode(List<CuMemberTrade> cuMemberTrades) {
        return baseMapper.batchSaveTradeByMemberCode(cuMemberTrades);
    }

    @Override
    public Object[] selectMemberTradeDetailList(CuMemberTradeDetailVO memberTradeDetailVO) {
        CuMemberTradeDetailVO cuMemberTradeDetailVO;
        List<CuMemberTradeDetailVO> cuMemberTradeDetailVoS = new ArrayList<>();
        CuMemberTradeVO memberTradeVO = new CuMemberTradeVO();
        BeanUtils.copyProperties(memberTradeDetailVO, memberTradeVO);
        List<CuMemberTradeExt> cuMemberTradeExtList = baseMapper.selectMemberTradeList(memberTradeVO);
        if (CollUtil.isNotEmpty(cuMemberTradeExtList)) {
            Integer pkCountry = memberTradeDetailVO.getPkCountry();
            //查询币种值
            List<BdAccount> allAccounts = cuMemberBaseService.getAccountByCountryId(pkCountry);
            Map<Integer, BdAccount> map = allAccounts.stream().collect(Collectors.toMap(BdAccount::getPkId, o -> o));
            Map<String, String> transactionMap = iTransactionCommonService.exportEnumTransaction(ETradeType.values());
            //根据国家查询汇率
            CurrencyDTO currency = cuMemberBaseService.getCurrency(pkCountry);
            //汇率
            BigDecimal exchangeRate = currency.getInExchangeRate();
            for (CuMemberTradeExt cuMemberTradeExt : cuMemberTradeExtList) {
                cuMemberTradeDetailVO = new CuMemberTradeDetailVO();
                BeanUtils.copyProperties(cuMemberTradeExt, cuMemberTradeDetailVO);
                //交易金额
                BigDecimal settleTradeAmount = cuMemberTradeExt.getTradeAmount().divide(exchangeRate, 4, RoundingMode.HALF_UP);
                //交易余额
                BigDecimal settleTradeBalance = cuMemberTradeExt.getTradeBalance().divide(exchangeRate, 4, RoundingMode.HALF_UP);
                cuMemberTradeDetailVO.setSettleTradeAmount(settleTradeAmount);
                cuMemberTradeDetailVO.setSettleTradeBalance(settleTradeBalance);

                //转化备注
                String remarks = cuMemberTradeExt.getRemarks();
                if (StringUtils.isNotEmpty(remarks) && remarks.startsWith(EnumsPrefixConstants.TRADE_TYPE)) {
                    cuMemberTradeDetailVO.setRemarks(transactionMap.get(remarks));
                }

                Integer pkAccount = cuMemberTradeExt.getPkAccount();
                if (null != pkAccount) {
                    cuMemberTradeDetailVO.setPkAccount(map.get(pkAccount).getPkTransactionKey());
                }
                cuMemberTradeDetailVoS.add(cuMemberTradeDetailVO);
            }
        }
        return new Object[]{cuMemberTradeExtList, cuMemberTradeDetailVoS};
    }

    @Override
    public Boolean businessCommissionSubmit(BusinessCommissionDTO businessCommissionDTO) {
        return businessCommissionSubmit(businessCommissionDTO, null);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean businessCommissionSubmit(BusinessCommissionDTO businessCommissionDTO, EApproveStatus eApproveStatus) {
        Integer isWithdraw = null;
        eApproveStatus = null == eApproveStatus ? EApproveStatus.FINISH : eApproveStatus;
        //过滤扣费金额等于、小于零的业务
        List<MemberAmountDTO> memberAmountDTOList = businessCommissionDTO.getMemberAmountDTOList();
        if (CollUtil.isNotEmpty(memberAmountDTOList)) {
            List<MemberAmountDTO> memberAmountList = memberAmountDTOList.stream().filter(memberAmountDTO -> memberAmountDTO.getTradeAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(memberAmountList)) {
                businessCommissionDTO.setMemberAmountDTOList(memberAmountList);
                Object[] objects = composeCuMemberTrade(businessCommissionDTO, eApproveStatus);
                List<CuMemberTrade> cuMemberTrades = (List<CuMemberTrade>) objects[0];
                this.saveBatch(cuMemberTrades);
                //更新余额
                Integer pkCountry = businessCommissionDTO.getPkCountry();
                if (null != pkCountry) {
                    Integer accountValue = cuMemberBaseService.getAccountValueById(businessCommissionDTO.getPkAccount());
                    if(accountValue.equals(EAccount.BONUS.getValue())){
                        isWithdraw = 0;
                    }
                    return cuMemberAccountService.batchUpdateMemberAccountByPkmember((List<MemberAmountDTO>) objects[1],accountValue, isWithdraw);
                } else {
                    return cuMemberAccountService.batchUpdateMemberAccountByPkMemberCountry((List<MemberAmountDTO>) objects[1], null);
                }


            }
        }
        return true;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean businessCommissionReject(BusinessCommissionDTO businessCommissionDTO) {
        CuMemberTrade rejectTrade;
        MemberAmountDTO memberAmount;
        int isWithdraw = EYesNo.NO.getIntValue();
        //审批驳回的数据
        List<CuMemberTrade> rejectList = new ArrayList<>();
        String sourceCode = businessCommissionDTO.getTradeCode();
        //业务类型
        Integer tradeType = businessCommissionDTO.getTradeType();
        // 根据交易编号与交易类型查询审批通过的信息
        List<CuMemberTrade> cuMemberTrades = baseMapper.selectMemberTradeByTradeCodeAndTradeType(sourceCode, ETradeType.getValueByApprovalValue(tradeType));
        if (CollUtil.isNotEmpty(cuMemberTrades)) {
            List<Long> pkMembers = cuMemberTrades.stream().map(CuMemberTrade::getPkMember).collect(Collectors.toList());
            //查询账户余额
            List<CuMemberAccount> cuMemberAccounts = cuMemberAccountService.selectMemberAccountByPkMember(pkMembers);
            Map<Long, CuMemberAccount> memberAccountMap = cuMemberAccounts.stream().collect(Collectors.toMap(CuMemberAccount::getPkMember, o -> o));
            Integer pkAccountValue = null;
            Map<Long, MemberAmountDTO> memberAmountMap = new HashMap<>();
            for (CuMemberTrade cuMemberTrade : cuMemberTrades) {
                Long pkMember = cuMemberTrade.getPkMember();
                Integer pkAccount = cuMemberTrade.getPkAccount();
                pkAccountValue = cuMemberBaseService.getAccountValueById(pkAccount);
                rejectTrade = new CuMemberTrade();
                BeanUtils.copyProperties(cuMemberTrade, rejectTrade);
                BigDecimal tradeAmount = cuMemberTrade.getTradeAmount().negate();
                rejectTrade.setTradeAmount(tradeAmount);
                BigDecimal balance = ReflectUtils.invokeGetter(memberAccountMap.get(pkMember), MemberFieldConstants.ACCOUNT + pkAccountValue);
                rejectTrade.setTradeBalance(tradeAmount.add(balance));
                rejectTrade.setSourceCode(sourceCode);
                rejectTrade.setTradeCode(CommonUtil.createSerialNumber(EOrderPrefix.TRADE_CODE.getValue()));
                rejectTrade.setTradeBeforeBalance(balance);
                rejectTrade.setPkCreator(businessCommissionDTO.getPkCreator());
                rejectTrade.setCreationTime(new Date());
                rejectList.add(rejectTrade);
                //同一会员同一账号更新余额
                CuMemberAccount memberAccount = memberAccountMap.get(pkMember);
                ReflectUtils.invokeSetter(memberAccount, MemberFieldConstants.ACCOUNT + pkAccountValue, tradeAmount.add(balance));
                memberAccountMap.put(pkMember, memberAccount);
                //封装更新余额入参
                memberAmount = new MemberAmountDTO();
                memberAmount.setPkMember(pkMember);
                memberAmount.setPkAccount(pkAccountValue);
                //同一会员同一账号多次扣款
                BigDecimal totalAmount = null == memberAmountMap.get(pkMember) ? tradeAmount : memberAmountMap.get(pkMember).getTradeAmount().add(tradeAmount);
                memberAmount.setTradeAmount(totalAmount);
                memberAmountMap.put(pkMember, memberAmount);
                //提现
                if (tradeType.equals(EApprovalBusiness.WITHDRAWAL.getValue()) && pkAccountValue.equals(EAccount.BONUS.getValue())) {
                    isWithdraw = EYesNo.YES.getIntValue();
                }

            }
            this.saveBatch(rejectList);
            //会员余额信息
            List<MemberAmountDTO> memberAmountDTOList = memberAmountMap.entrySet().stream().map(a -> a.getValue()).collect(Collectors.toList());
            //更新余额
            return cuMemberAccountService.batchUpdateMemberAccountByPkMemberCountry(memberAmountDTOList, isWithdraw);
        }
        return true;
    }


    @Override
    public List<MemberBalanceDTO> selectBalanceNotEnoughMember(BusinessCommissionDTO businessCommissionDTO) {
        MemberBalanceDTO memberBalanceDTO;
        List<MemberBalanceDTO> memberBalanceDTOList = new ArrayList<>();
        Integer pkAccount = businessCommissionDTO.getPkAccount();
        List<MemberAmountDTO> memberAmountDTOList = businessCommissionDTO.getMemberAmountDTOList();
        Map<Long, MemberAmountDTO> memberAccountExtMap = memberAmountDTOList.stream().collect(Collectors.toMap(MemberAmountDTO::getPkMember, o -> o));
        List<CuMemberAccountExt> cuMemberAccountExts = cuMemberAccountService.queryMemberAccountByPkMember(memberAmountDTOList);
        for (CuMemberAccountExt memberAccountExt : cuMemberAccountExts) {
            BigDecimal availableBalance = getAvailableBalance(memberAccountExt, pkAccount);
            if (availableBalance.compareTo(memberAccountExtMap.get(memberAccountExt.getPkMember()).getTradeAmount()) < 0) {
                memberBalanceDTO = new MemberBalanceDTO();
                memberBalanceDTO.setMemberCode(memberAccountExt.getMemberCode());
                memberBalanceDTO.setMemberName(memberAccountExt.getMemberName());
                memberBalanceDTO.setBanlance(availableBalance);
                memberBalanceDTOList.add(memberBalanceDTO);
            }
        }

        return memberBalanceDTOList;
    }

    /**
     * @description: 基础业务办理专用查询会员余额
     * @author: zhang jing
     * @date: 2023/11/10 15:17
     * @param: [mbbList]
     * @return: java.util.List<com.hzs.member.account.dto.MemberBalanceDTO>
     **/
    @Override
    public List<MemberBusinessBalanceDTO> selectBusinessBalanceNotEnoughMember(List<MemberBusinessBalanceDTO> mbbList, Integer pkCountry) {
        // 根据国家查询固定币种
        List<BdAccount> accList = cuMemberBaseService.getAccountByCountryId(pkCountry);
        Map<Integer, BdAccount> accountMap = accList.stream()
                .collect(Collectors.toMap(BdAccount::getFieldValue, Function.identity()));
        List<MemberAmountDTO> memberAmountDTOList = mbbList.stream()
                .map(item -> BeanUtil.copyProperties(item, MemberAmountDTO.class))
                .collect(Collectors.toList());
        List<CuMemberAccountExt> cuMemberAccountExts = cuMemberAccountService.queryMemberAccountByPkMember(memberAmountDTOList);
        Map<Long, CuMemberAccountExt> cuMemberAccountExtsMap = cuMemberAccountExts.stream()
                .collect(Collectors.toMap(CuMemberAccountExt::getPkMember, Function.identity()));
        Map<Long, List<MemberAmountDTO>> memberAmountMap = memberAmountDTOList.stream()
                .collect(Collectors.groupingBy(MemberAmountDTO::getPkMember));

        for (Map.Entry<Long, List<MemberAmountDTO>> maDto : memberAmountMap.entrySet()) {
            Integer flag = 0;
            BigDecimal availableBalance;
            Integer businessType = 0;
            //中国
            if (pkCountry == CountryConstants.CHINA_COUNTRY) {
                //会员下的业务
                ff3:
                for (int i = 0; i < maDto.getValue().size(); i++) {
                    businessType = maDto.getValue().get(i).getBusinessType();
                    for (Map.Entry<Integer, BdAccount> entry : accountMap.entrySet()) {
                        BdAccount account = entry.getValue();
                        //消费
                        if (account.getFieldValue().equals(EAccount.CONSUME.getValue())) {
                            availableBalance = getAvailableBalance(cuMemberAccountExtsMap.get(maDto.getKey()), account.getPkId());
                            if (availableBalance.compareTo(maDto.getValue().get(i).getTradeAmount()) >= 0) {
                                ReflectUtils.invokeSetter(cuMemberAccountExtsMap.get(maDto.getKey()),
                                        MemberFieldConstants.ACCOUNT + EAccount.CONSUME.getValue(),
                                        availableBalance.subtract(maDto.getValue().get(i).getTradeAmount()));

                                for (MemberBusinessBalanceDTO mbb : mbbList) {
                                    if (mbb.getPkMember().equals(cuMemberAccountExtsMap.get(maDto.getKey()).getPkMember())
                                            && mbb.getBusinessType().equals(maDto.getValue().get(i).getBusinessType())) {
                                        mbb.setPkAccount(account.getPkId());
                                        continue ff3;
                                    }
                                }
                            } else {
                                flag = 1;
                            }
                        }
                        //现金
                        if (account.getFieldValue().equals(EAccount.CASH.getValue())) {
                            availableBalance = getAvailableBalance(cuMemberAccountExtsMap.get(maDto.getKey()), account.getPkId());
                            if (availableBalance.compareTo(maDto.getValue().get(i).getTradeAmount()) >= 0) {
                                ReflectUtils.invokeSetter(cuMemberAccountExtsMap.get(maDto.getKey()),
                                        MemberFieldConstants.ACCOUNT + EAccount.CASH.getValue(),
                                        availableBalance.subtract(maDto.getValue().get(i).getTradeAmount()));

                                for (MemberBusinessBalanceDTO mbb : mbbList) {
                                    if (mbb.getPkMember().equals(cuMemberAccountExtsMap.get(maDto.getKey()).getPkMember())
                                            && mbb.getBusinessType().equals(maDto.getValue().get(i).getBusinessType())) {
                                        mbb.setPkAccount(account.getPkId());
                                        continue ff3;
                                    }
                                }
                            } else {
                                flag = 1;
                            }
                        }
                        //奖金
                        if (account.getFieldValue().equals(EAccount.BONUS.getValue())) {
                            availableBalance = getAvailableBalance(cuMemberAccountExtsMap.get(maDto.getKey()), account.getPkId());
                            if (availableBalance.compareTo(maDto.getValue().get(i).getTradeAmount()) >= 0) {
                                ReflectUtils.invokeSetter(cuMemberAccountExtsMap.get(maDto.getKey()),
                                        MemberFieldConstants.ACCOUNT + EAccount.BONUS.getValue(),
                                        availableBalance.subtract(maDto.getValue().get(i).getTradeAmount()));

                                for (MemberBusinessBalanceDTO mbb : mbbList) {
                                    if (mbb.getPkMember().equals(cuMemberAccountExtsMap.get(maDto.getKey()).getPkMember())
                                            && mbb.getBusinessType().equals(maDto.getValue().get(i).getBusinessType())) {
                                        mbb.setPkAccount(account.getPkId());
                                        continue ff3;
                                    }
                                }
                            } else {
                                flag = 1;
                            }
                        }
                    }
                    if (flag == 1) {
                        for (MemberBusinessBalanceDTO mbb : mbbList) {
                            if (mbb.getPkMember().equals(cuMemberAccountExtsMap.get(maDto.getKey()).getPkMember())
                                    && mbb.getBusinessType().equals(businessType)) {
                                mbb.setMemberCode(cuMemberAccountExtsMap.get(maDto.getKey()).getMemberCode());
                                mbb.setPkAccount(null);
                            }
                        }
                    }
                }
            } else {
                //国外
                for (int i = 0; i < maDto.getValue().size(); i++) {
                    businessType = maDto.getValue().get(i).getBusinessType();
                    if (maDto.getValue().get(i).getPkAccount() != null) {
                        availableBalance = getAvailableBalance(cuMemberAccountExtsMap.get(maDto.getKey()), maDto.getValue().get(i).getPkAccount());
                        if (availableBalance.compareTo(maDto.getValue().get(i).getTradeAmount()) >= 0) {
                            ReflectUtils.invokeSetter(cuMemberAccountExtsMap.get(maDto.getKey()),
                                    MemberFieldConstants.ACCOUNT + EAccount.CONSUME.getValue(),
                                    availableBalance.subtract(maDto.getValue().get(i).getTradeAmount()));

                            for (MemberBusinessBalanceDTO mbb : mbbList) {
                                if (mbb.getPkMember().equals(cuMemberAccountExtsMap.get(maDto.getKey()).getPkMember())
                                        && mbb.getBusinessType().equals(maDto.getValue().get(i).getBusinessType())) {
                                    mbb.setPkAccount(maDto.getValue().get(i).getPkAccount());
                                }
                            }
                        } else {
                            for (MemberBusinessBalanceDTO mbb : mbbList) {
                                if (mbb.getPkMember().equals(cuMemberAccountExtsMap.get(maDto.getKey()).getPkMember())
                                        && mbb.getBusinessType().equals(businessType)) {
                                    mbb.setMemberCode(cuMemberAccountExtsMap.get(maDto.getKey()).getMemberCode());
                                    mbb.setPkAccount(null);
                                }
                            }
                        }
                    }
                }

            }


        }
        return mbbList;
    }

    /**
     * @description: 特殊业务业务办理专用查询会员余额
     * @author: zhang jing
     * @date: 2023/11/10 15:17
     * @param: [mbbList]
     * @return: java.util.List<com.hzs.member.account.dto.MemberBalanceDTO>
     **/
    @Override
    public List<MemberBusinessBalanceDTO> selectSpecialBusinessBalanceNotEnoughMember(List<MemberBusinessBalanceDTO> mbbList, Integer pkCountry) {
        // 根据国家查询固定币种
        List<BdAccount> accList = cuMemberBaseService.getAccountByCountryId(pkCountry);
        Map<Integer, BdAccount> accountMap = accList.stream().collect(Collectors.toMap(BdAccount::getFieldValue, Function.identity()));

        List<MemberAmountDTO> memberAmountDTOList = mbbList.stream()
                .map(item -> BeanUtil.copyProperties(item, MemberAmountDTO.class))
                .collect(Collectors.toList());

        Map<Long, MemberAmountDTO> memberAccountExtMap = memberAmountDTOList.stream()
                .collect(Collectors.toMap(MemberAmountDTO::getPkMember, Function.identity()));

        List<CuMemberAccountExt> cuMemberAccountExts = cuMemberAccountService.queryMemberAccountByPkMember(memberAmountDTOList);

        for (CuMemberAccountExt memberAccountExt : cuMemberAccountExts) {
            processAccountBalance(accountMap, memberAccountExt, memberAccountExtMap, mbbList);
        }

        return mbbList;
    }

    private void processAccountBalance(Map<Integer, BdAccount> accountMap,
                                       CuMemberAccountExt memberAccountExt,
                                       Map<Long, MemberAmountDTO> memberAccountExtMap,
                                       List<MemberBusinessBalanceDTO> mbbList) {

        for (Map.Entry<Integer, BdAccount> entry : accountMap.entrySet()) {
            BdAccount account = entry.getValue();
            //消费
            if (account.getFieldValue().equals(EAccount.CONSUME.getValue())) {
                BigDecimal availableBalance = getAvailableBalance(memberAccountExt, account.getPkId());
                if (availableBalance.compareTo(memberAccountExtMap.get(memberAccountExt.getPkMember()).getTradeAmount()) > 0) {
                    for (MemberBusinessBalanceDTO mbb : mbbList) {
                        if (mbb.getPkMember().equals(memberAccountExt.getPkMember())) {
                            mbb.setPkAccount(account.getPkId());
                            return;
                        }
                    }
                }
            }
            //现金
            if (account.getFieldValue().equals(EAccount.CASH.getValue())) {
                BigDecimal availableBalance = getAvailableBalance(memberAccountExt, account.getPkId());
                if (availableBalance.compareTo(memberAccountExtMap.get(memberAccountExt.getPkMember()).getTradeAmount()) > 0) {
                    for (MemberBusinessBalanceDTO mbb : mbbList) {
                        if (mbb.getPkMember().equals(memberAccountExt.getPkMember())) {
                            mbb.setPkAccount(account.getPkId());
                            return;
                        }
                    }
                }
            }
            //奖金
            if (account.getFieldValue().equals(EAccount.BONUS.getValue())) {
                BigDecimal availableBalance = getAvailableBalance(memberAccountExt, account.getPkId());
                if (availableBalance.compareTo(memberAccountExtMap.get(memberAccountExt.getPkMember()).getTradeAmount()) > 0) {
                    for (MemberBusinessBalanceDTO mbb : mbbList) {
                        if (mbb.getPkMember().equals(memberAccountExt.getPkMember())) {
                            mbb.setPkAccount(account.getPkId());
                            return;
                        }
                    }
                }
            }

        }
        for (MemberBusinessBalanceDTO mbb : mbbList) {
            if (mbb.getPkMember().equals(memberAccountExt.getPkMember())) {
                mbb.setMemberCode(memberAccountExt.getMemberCode());
                mbb.setPkAccount(null);
            }
        }
    }


    /**
     * 获取账户的可用余额
     *
     * @param memberAccountExt 账户信息
     * @param pkAccount        币种ID
     * @return BigDecimal
     */
    private BigDecimal getAvailableBalance(CuMemberAccountExt memberAccountExt, Integer pkAccount) {
        BigDecimal balance;
        //币种值
        Integer accountValue = cuMemberBaseService.getAccountValueById(pkAccount);
        //奖金账号
        if (accountValue.equals(EAccount.BONUS.getValue())) {
            //账户余额
            BigDecimal accountBalance = ReflectUtils.invokeGetter(memberAccountExt, MemberFieldConstants.ACCOUNT + accountValue);
            //锁定消费
            BigDecimal lockConsumeBalance = ReflectUtils.invokeGetter(memberAccountExt, MemberFieldConstants.LOCK_ACCOUNT + accountValue);
            accountBalance = accountBalance.subtract(lockConsumeBalance);

            //可提现账户余额
            BigDecimal withdrawBalance = ReflectUtils.invokeGetter(memberAccountExt, MemberFieldConstants.WITHDRAW_ACCOUNT + accountValue);
            BigDecimal withdrawLockAccount = ReflectUtils.invokeGetter(memberAccountExt, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + accountValue);

            if (null != withdrawBalance && withdrawLockAccount.compareTo(BigDecimal.ZERO) > 0) {
                withdrawBalance = withdrawBalance.subtract(withdrawLockAccount);
            }
            //可消费余额
            BigDecimal consumeBalance = ReflectUtils.invokeGetter(memberAccountExt, MemberFieldConstants.CONSUME_ACCOUNT + accountValue);
            //真实余额
            BigDecimal realBalance = withdrawBalance.add(consumeBalance);
            balance = accountBalance.compareTo(realBalance) > 0 ? realBalance : accountBalance;

        } else {
            //余额
            balance = ReflectUtils.invokeGetter(memberAccountExt, MemberFieldConstants.ACCOUNT + accountValue);
            //锁定消费
            BigDecimal consumeBalance = ReflectUtils.invokeGetter(memberAccountExt, MemberFieldConstants.LOCK_ACCOUNT + accountValue);
            balance = balance.subtract(consumeBalance);
        }
        return balance;
    }

    /**
     * 拼装组合交易流水信息
     *
     * @param businessCommissionDTO 业务信息
     * @param eApproveStatus        审批状态
     * @return Object []
     */
    private Object[] composeCuMemberTrade(BusinessCommissionDTO businessCommissionDTO, EApproveStatus eApproveStatus) {
        CuMemberTrade cuMemberTrade;
        MemberAmountDTO memberAmount;
        CurrencyDTO currencyDTO = null;
        Map<Long, MemberAmountDTO> memberAmountMap = null;

        List<CuMemberTrade> cuMemberTradeLsit = new ArrayList<>();
        List<MemberAmountDTO> memberAmountList = new ArrayList<>();

        Integer pkCountry = businessCommissionDTO.getPkCountry();
        //账户
        Integer pkAccount = businessCommissionDTO.getPkAccount();
        //是多国不同账户
        Boolean isMany = isMultinational(pkCountry, pkAccount);
        if (!isMany) {
            currencyDTO = cuMemberBaseService.getCurrency(pkCountry);
        }
        List<MemberAmountDTO> memberAmountDTOList = businessCommissionDTO.getMemberAmountDTOList();
        if (CollUtil.isNotEmpty(memberAmountDTOList)) {
            //查询账户余额
            List<CuMemberAccountExt> cuMemberAccountExts = cuMemberAccountService.queryMemberAccountByPkMember(memberAmountDTOList);
            Map<Long, CuMemberAccountExt> memberAccountExtMap = cuMemberAccountExts.stream().collect(Collectors.toMap(CuMemberAccountExt::getPkMember, o -> o));
            Integer tradeType = ETradeType.getValueByApprovalValue(businessCommissionDTO.getTradeType());
            tradeType = tradeType == 0 ? businessCommissionDTO.getTradeType() : tradeType;
            String remarks = ETradeType.getTradeLabel(tradeType);
            //兼容多个国家账户余额
            if (isMany) {
                memberAmountMap = new HashMap<>();
            }

            for (MemberAmountDTO memberAmountDTO : memberAmountDTOList) {
                Long pkMember = memberAmountDTO.getPkMember();
                //兼容多个国家汇率
                if (isMany) {
                    pkCountry = memberAmountDTO.getPkCountry();
                    currencyDTO = cuMemberBaseService.getCurrency(pkCountry);
                    pkAccount = memberAmountDTO.getPkAccount();
                }
                //扣款金额
                BigDecimal tradeAmount = eApproveStatus.getValue() == EApproveStatus.FINISH.getValue() ? memberAmountDTO.getTradeAmount().negate() : memberAmountDTO.getTradeAmount();
                //账户余额
                CuMemberAccountExt cuMemberAccountExt = memberAccountExtMap.get(pkMember);
                Integer pkAccountValue = cuMemberBaseService.getAccountValueById(pkAccount);
                BigDecimal balance = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.ACCOUNT + pkAccountValue);
                if (balance == null) {
                    balance = BigDecimal.ZERO;
                }
                cuMemberTrade = CuMemberTrade.builder().pkMember(pkMember)
                        .tradeClassify(ETradeClassify.CONSUME.getValue())
                        .pkRate(currencyDTO.getPkId()).tradeBalance(tradeAmount.add(balance))
                        .tradeBeforeBalance(balance).sourceCode(businessCommissionDTO.getTradeCode())
                        .tradeStatue(ETradeStatus.TAKE_EFFECT.getValue())
                        .remarks(remarks).tradeAmount(tradeAmount)
                        .build();
                BeanUtils.copyProperties(businessCommissionDTO, cuMemberTrade);
                cuMemberTrade.setTradeCode(CommonUtil.createSerialNumber(EOrderPrefix.TRADE_CODE.getValue()));
                cuMemberTrade.setTradeType(tradeType);

                if (isMany) {
                    //更新同一用户的余额
                    ReflectUtils.invokeSetter(cuMemberAccountExt, MemberFieldConstants.ACCOUNT + pkAccountValue, tradeAmount.add(balance));
                    memberAccountExtMap.put(pkMember, cuMemberAccountExt);
                    cuMemberTrade.setPkCountry(pkCountry);
                    cuMemberTrade.setPkAccount(pkAccount);
                }
                cuMemberTradeLsit.add(cuMemberTrade);
                //余额取负
                //if (eApproveStatus.getValue() == EApproveStatus.FINISH.getValue()) {
                memberAmount = new MemberAmountDTO();
                memberAmount.setPkMember(pkMember);
                memberAmount.setTradeAmount(tradeAmount);
                //奖金币种扣除时，先扣可提现用户，再扣可消费用户
                if (eApproveStatus.getValue() == EApproveStatus.FINISH.getValue()) {
                    bonusAccountBalance(memberAmount, pkAccountValue, cuMemberAccountExt);
                }
                if (isMany) {
                    memberAmount.setPkAccount(cuMemberBaseService.getAccountValueById(pkAccount));
                    memberAmount.setPkCountry(pkCountry);
                    BigDecimal totalBalance = null == memberAmountMap.get(pkMember) ? tradeAmount : memberAmountMap.get(pkMember).getTradeAmount().add(tradeAmount);
                    memberAmount.setTradeAmount(totalBalance);
                    memberAmountMap.put(pkMember, memberAmount);
                } else {
                    memberAmountList.add(memberAmount);
                }
                // }
            }

            if (null != memberAmountMap) {
                memberAmountList = memberAmountMap.entrySet().stream().map(a -> a.getValue()).collect(Collectors.toList());
            }
        }
        return new Object[]{cuMemberTradeLsit, memberAmountList};
    }

    /**
     * @param memberAmount       用户扣款信息
     * @param pkAccountValue     币种值
     * @param cuMemberAccountExt 账户信息
     * @return MemberAmountDTO
     */
    private MemberAmountDTO bonusAccountBalance(MemberAmountDTO memberAmount, Integer pkAccountValue, CuMemberAccountExt cuMemberAccountExt) {
        if (pkAccountValue.equals(EAccount.BONUS.getValue())) {
            //可提现账户余额
            BigDecimal withdrawBalance = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.WITHDRAW_ACCOUNT + pkAccountValue);
            BigDecimal withdrawLockAccount = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + pkAccountValue);
            if (null != withdrawBalance && withdrawLockAccount.compareTo(BigDecimal.ZERO) > 0) {
                withdrawBalance = withdrawBalance.subtract(withdrawLockAccount);
            }
            BigDecimal tradeAmount = memberAmount.getTradeAmount().negate();
            //扣除可提现金额
            if (withdrawBalance.compareTo(BigDecimal.ZERO) > 0 && withdrawBalance.compareTo(tradeAmount) > 0) {
                memberAmount.setWithdrawBalance(tradeAmount.negate());
            } else if (withdrawBalance.compareTo(BigDecimal.ZERO) >= 0 && withdrawBalance.compareTo(tradeAmount) < 0) {
                //可提现金额小于扣除金额，则从可消费里扣除
                memberAmount.setWithdrawBalance(withdrawBalance.negate());
                //可消费余额
                BigDecimal consumeBalance = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.CONSUME_ACCOUNT + pkAccountValue);
                if (consumeBalance.compareTo(BigDecimal.ZERO) > 0) {
                    //可消费扣除金额
                    BigDecimal deductAmount = tradeAmount.subtract(withdrawBalance);
                    memberAmount.setConsumeBalance(deductAmount.negate());
                }
            }
        }
        return memberAmount;

    }

    /**
     * 是否扣款是不同国家不同账户
     *
     * @param pkCountry 国家ID
     * @param pkAccount 账户ID
     * @return Boolean
     */
    private Boolean isMultinational(Integer pkCountry, Integer pkAccount) {
        if (null == pkCountry && null == pkAccount) {
            return true;
        }
        return false;
    }

    @Override
    public List<CuMemberTradeVO> selectWattleDetail(CuMemberTradeVO cuMemberTradeVO) {
        CuMemberTradeVO memberTradeVO;
        Page<CuMemberTradeVO> cuMemberTradeVOList = new Page<>();
        Integer pkCountry = cuMemberTradeVO.getPkCountry();
        Page<CuMemberTradeExt> cuMemberTrades = (Page<CuMemberTradeExt>) baseMapper.selectWattleDetail(cuMemberTradeVO);
        if (CollUtil.isNotEmpty(cuMemberTrades)) {
            Map<String, String> transactionMap = iTransactionCommonService.exportEnumTransaction(ETradeType.values());
            Map<Integer, Integer> accountTranValue = this.getTranslateAccountValue(pkCountry);
            for (CuMemberTradeExt memberTrade : cuMemberTrades) {
                memberTradeVO = BeanUtil.copyProperties(memberTrade, CuMemberTradeVO.class);
                Integer pkAccount = memberTradeVO.getPkAccount();
                memberTradeVO.setPkAccount(accountTranValue.get(pkAccount));
                //转化备注
                String remarks = memberTradeVO.getRemarks();
                if (StringUtils.isNotEmpty(remarks) && remarks.startsWith(EnumsPrefixConstants.TRADE_TYPE)) {
                    memberTradeVO.setRemarks(transactionMap.get(remarks));
                    memberTradeVO.setMontage(EYesNo.YES.getIntValue());
                } else {
                    memberTradeVO.setMontage(EYesNo.NO.getIntValue());
                }
                //充值的前台备注
                String memberRemarks = memberTrade.getMemberRemarks();
                if (memberTrade.getTradeType().equals(ETradeType.OFF_LINE_RECHARGE.getValue())) {
                    memberTradeVO.setRemarks(memberRemarks);
                }
                cuMemberTradeVOList.add(memberTradeVO);
            }
        }
        cuMemberTradeVOList.setTotal(cuMemberTrades.getTotal());
        return cuMemberTradeVOList;
    }

    /**
     * 获取币种翻译值
     *
     * @param pkCountry 国家
     * @return Map<Integer, Integer>
     */
    private Map<Integer, Integer> getTranslateAccountValue(Integer pkCountry) {
        List<BdAccount> accountList = cuMemberBaseService.getAccountByCountry(null, pkCountry);
        return accountList.stream().collect(Collectors.toMap(BdAccount::getPkId, BdAccount::getPkTransactionKey));
    }


    @Override
    public Integer updateSourceCodeByTradeCode(CuMemberTradeVO cuMemberTradeVO) {
        return baseMapper.updateSourceCodeByTradeCode(cuMemberTradeVO);
    }

    @Override
    public List<CuMemberTrade> querySourceCodeLastTrade(Long pkMember, String sourceCode, Integer tradeClassify) {
        return baseMapper.querySourceCodeLastTrade(pkMember, sourceCode, tradeClassify);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer saveMemberTradeAndAccountByRechargeCode(String rechargeCode) {
        CuMemberRecharge cuMemberRecharge = cuMemberRechargeService.getCuMemberRechargeByRechargeCode(rechargeCode);
        Long pkMember = cuMemberRecharge.getPkMember();
        Integer pkAccount = cuMemberRecharge.getPkAccount();
        //币种值
        Integer accountType = cuMemberBaseService.getAccountValueById(pkAccount);
        //查询用户余额
        CuMemberAccount cuMemberAccount = cuMemberAccountService.queryCuMemberAccountByPkMember(pkMember);
        BigDecimal balance = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.ACCOUNT + accountType);
        //充值金额
        BigDecimal amount = cuMemberRecharge.getRechargeAmount();
        CuMemberTrade cuMemberTrade = CuMemberTrade.builder().pkMember(pkMember)
                .tradeCode(cuMemberRecharge.getRechargeCode()).pkAccount(pkAccount)
                .tradeType(ETradeType.ON_LINE_RECHARGE.getValue()).tradeClassify(ETradeClassify.RECHARGE.getValue())
                .pkRate(cuMemberRecharge.getPkRate()).tradeAmount(amount)
                .tradeBalance(balance.add(amount)).tradeBeforeBalance(balance)
                .sourceCode(rechargeCode).tradeStatue(ETradeStatus.TAKE_EFFECT.getValue())
                .remarks(ETradeType.ON_LINE_RECHARGE.getLabel()).build();
        cuMemberTrade.setPkCountry(cuMemberRecharge.getPkCountry());
        cuMemberTrade.setPkCreator(cuMemberRecharge.getPkCreator());
        //保存交易流水信息
        save(cuMemberTrade);

        CuMemberAccountParam param = CuMemberAccountParam.builder().pkMember(pkMember)
                .accountType(accountType).amount(amount).pkModified(pkMember)
                .accountClassify(ETradeClassify.RECHARGE.getValue()).pkCountry(cuMemberRecharge.getPkCountry())
                .transferType(0).build();

        //更新余额
        return cuMemberAccountService.updateMemberAccountByMemberCode(param);
    }

    @Override
    public List<Long> batchQueryCuMemberTradeSeq(Integer rowNum) {
        return baseMapper.batchQueryCuMemberTradeSeq(rowNum);
    }

    @Override
    public void batchInsertCuMemberTrade(List<CuMemberTrade> cuMemberTradeList) {
        List<List<?>> cutList = cuMemberBonusSettle.handleCutList(cuMemberTradeList);
        cutList.forEach(memberTradeList ->
                baseMapper.batchInsertCuMemberTrade(memberTradeList));
    }


    @Override
    public List<CuMemberTrade> selectMemberTradeBySourceCode(String sourceCode) {
        return baseMapper.selectMemberTradeBySourceCode(sourceCode);
    }


    @Override
    public List<Integer> selectTradeType(Long pkMember, Integer pkCountry) {
        return baseMapper.selectTradeType(pkMember, pkCountry);
    }
}
