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.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.constant.EnumsPrefixConstants;
import com.hzs.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.constant.MemberFieldConstants;
import com.hzs.common.core.constant.SystemFieldConstants;
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.DateUtils;
import com.hzs.common.core.utils.reflect.ReflectUtils;
import com.hzs.common.domain.member.account.CuMemberAccount;
import com.hzs.common.domain.member.account.CuMemberAccountLog;
import com.hzs.common.domain.member.account.CuMemberAccountRechargeExt;
import com.hzs.common.domain.member.base.CuMember;
import com.hzs.common.domain.member.ext.CuMemberAccountExt;
import com.hzs.common.domain.system.config.BdAccount;
import com.hzs.common.domain.system.sys.SysUser;
import com.hzs.member.account.dto.*;
import com.hzs.member.account.mapper.CuMemberAccountMapper;
import com.hzs.member.account.service.ICuMemberAccountLogService;
import com.hzs.member.account.service.ICuMemberAccountService;
import com.hzs.member.account.service.ICuMemberBaseService;
import com.hzs.member.account.vo.*;
import com.hzs.member.base.service.ICuMemberService;
import com.hzs.member.handlebusiness.vo.BusinessMemberVO;
import com.hzs.system.base.ITransactionServiceApi;
import com.hzs.system.config.IAccountServiceApi;
import com.hzs.system.sys.IApprovalServiceApi;
import com.hzs.system.sys.dto.ApprovalInfoDTO;
import com.hzs.system.sys.dto.ApprovalSubmitDTO;
import com.hzs.system.sys.dto.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
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;

/**
 * 会员账户信息 服务实现类
 */
@Service
@Slf4j
public class CuMemberAccountServiceImpl extends ServiceImpl<CuMemberAccountMapper, CuMemberAccount> implements ICuMemberAccountService {

    @Autowired
    private ICuMemberBaseService iCuMemberBaseService;
    @Autowired
    private ICuMemberService iCuMemberService;
    @Autowired
    private ICuMemberAccountLogService iCuMemberAccountLogService;

    @DubboReference
    IApprovalServiceApi iApprovalServiceApi;
    @DubboReference
    IAccountServiceApi iAccountServiceApi;
    @DubboReference
    ITransactionServiceApi iTransactionServiceApi;

    @Override
    public List<CuMemberAccountExt> queryMemberAccountByCondition(CuMemberAccount cuMemberAccount) {
        return baseMapper.queryMemberAccountByCondition(cuMemberAccount);
    }

    @Override
    public Boolean updateMemberAccount(CuMemberAccount cuMemberAccount, Long pkModified) {
        cuMemberAccount.setPkModified(pkModified);
        return baseMapper.updateMemberAccount(cuMemberAccount) > 0;
    }

    @Override
    public BigDecimal selectBalanceByMemberCode(Long pkMember, Integer accountType) {
        return baseMapper.selectBalanceByMemberCode(pkMember, accountType);
    }

    @Override
    public Integer updateMemberAccountByMemberCode(CuMemberAccountParam cuMemberAccountParam) {
        BigDecimal amount = cuMemberAccountParam.getAmount();
        CuMemberAccount cuMemberAccount = new CuMemberAccount();
        cuMemberAccount.setPkMember(cuMemberAccountParam.getPkMember());
        switch (cuMemberAccountParam.getAccountType()) {
            case 1:
                cuMemberAccount.setAccount1(amount);
                break;
            case 2:
                cuMemberAccount.setAccount2(amount);
                break;
            case 3:
                cuMemberAccount.setAccount3(amount);
                break;
            case 4:
                this.getBonusAccount(cuMemberAccount, cuMemberAccountParam.getAccountClassify(), amount, cuMemberAccountParam.getTransferType());
                break;
            case 5:
                cuMemberAccount.setAccount5(amount);
                break;
            case 6:
                cuMemberAccount.setAccount6(amount);
                break;
            case 7:
                cuMemberAccount.setAccount7(amount);
                break;
            case 8:
                cuMemberAccount.setAccount8(amount);
                break;
            case 9:
                cuMemberAccount.setAccount9(amount);
                break;
            case 10:
                cuMemberAccount.setAccount10(amount);
                break;
            case 11:
                cuMemberAccount.setAccount11(amount);
                break;
            case 12:
                cuMemberAccount.setAccount12(amount);
                break;
            case 13:
                cuMemberAccount.setAccount13(amount);
                break;
            case 14:
                cuMemberAccount.setAccount14(amount);
                break;
            default:
                break;
        }
        cuMemberAccount.setPkModified(cuMemberAccountParam.getPkModified());
        cuMemberAccount.setPkCountry(cuMemberAccountParam.getPkCountry());
        return baseMapper.updateMemberAccount(cuMemberAccount);
    }

    @Override
    public CuMemberPetitionVO showFrozenAmountPetition(CuMemberFrozenParam memberFrozenParam) {
        CuMemberFrozenAmountVO cuMemberFrozenAmountVO;
        CuMemberPetitionVO memberPetitionVo = new CuMemberPetitionVO();

        SysUser loginUser = memberFrozenParam.getSysUser();
        R<Map<Integer, ApprovalInfoDTO>> mapR = iApprovalServiceApi.queryApprovalInfo(Collections.singletonList(EApprovalBusiness.FROZEN.getValue()), memberFrozenParam.getPkCountry());
        //批次号
        String batchNum = CommonUtil.createSerialNumber(EOrderPrefix.FROZEN_CODE.getValue());
        memberPetitionVo.setBusinessNo(batchNum);
        //发起部门
        memberPetitionVo.setDeptId(loginUser.getPkDept());
        memberPetitionVo.setDeptStr(loginUser.getDeptName());
        // 发起人
        memberPetitionVo.setSponsorId(loginUser.getUserId());
        memberPetitionVo.setSponsorName(loginUser.getUserName());
        // 日期
        memberPetitionVo.setCreationDate(DateUtils.parseDateTimeToStr(DateUtils.YYYY_MM_DD_HH_MM_SS));

        // 抄送部门
        ApprovalInfoDTO approvalInfoDTO = mapR.getData().get(EApprovalBusiness.FROZEN.getValue());
        if (null != approvalInfoDTO) {
            memberPetitionVo.setItemList(approvalInfoDTO.getItemList());
            memberPetitionVo.setSendList(approvalInfoDTO.getSendList());
        }

        //在线签呈的业务列表展示
        List<CuMemberFrozenAmountVO> memberFrozenAmountVOList = new ArrayList<>();
        //冻结金额入参
        List<CuMemberFrozenDetailParam> memberFrozenDetails = memberFrozenParam.getMemberFrozenDetails();
        //用户编号
        List<String> memberCodes = memberFrozenParam.getMemberCodes();

        List<CuMember> cuMemberList = iCuMemberService.findMemberByMembercodesAndPkcountry(memberCodes, memberFrozenParam.getPkCountry());
        Map<String, CuMember> memberMap = cuMemberList.stream().collect(Collectors.toMap(CuMember::getMemberCode, o -> o));
        for (String memberCode : memberCodes) {
            for (CuMemberFrozenDetailParam frozenDetailParam : memberFrozenDetails) {
                cuMemberFrozenAmountVO = CuMemberFrozenAmountVO.builder().memberCode(memberCode)
                        .memberName(memberMap.get(memberCode).getMemberName())
                        .lockConsume(frozenDetailParam.getLockConsume())
                        .lockTransfer(frozenDetailParam.getLockTransfer())
                        .lockWithdraw(frozenDetailParam.getLockWithdraw())
                        .pkAccount(iCuMemberBaseService.translateAccountValue(frozenDetailParam.getMemberAccount()))
                        .remarks(frozenDetailParam.getRemarks()).build();
                memberFrozenAmountVOList.add(cuMemberFrozenAmountVO);
            }
        }
        memberPetitionVo.setMemberFrozenAmountVOList(memberFrozenAmountVOList);
        return memberPetitionVo;
    }

    /**
     * 获得更新账户余额 奖金账户、可提现账户、可消费账户
     * 奖金账户 = 可提现账户+可消费账户
     * 奖金账户操作时 ：入的金额 进可消费账户  出的金额 进可提现账户
     *
     * @param cuMemberAccount 会员账户余额
     * @param accountClassify 账户分类
     * @param amount          金额
     */
    private void getBonusAccount(CuMemberAccount cuMemberAccount, int accountClassify, BigDecimal amount, int transferType) {
        if (accountClassify == ETradeClassify.WITHDRAWAL.getValue()) {
            cuMemberAccount.setAccount4(amount);
            cuMemberAccount.setWithdrawAccount4(amount);
        } else if (accountClassify == ETradeClassify.TRANSFER.getValue()) {
            cuMemberAccount.setAccount4(amount);
            //转账转入方（奖金币充正时，只充可消费）
            if (transferType == ETransferType.TRANSFER_IN.getValue()) {
                cuMemberAccount.setConsumeAccount4(amount);
            }
            //转账转出方
            if (transferType == ETransferType.TRANSFER_OUT.getValue()) {
                CuMemberAccount account = queryCuMemberAccountByPkMember(cuMemberAccount.getPkMember());
                //可提现金额
                BigDecimal withdrawAccount = account.getWithdrawAccount4();
                //奖金币扣款时，先扣可提现、再扣可消费
                if (withdrawAccount.add(amount).compareTo(BigDecimal.ZERO) < 0) {
                    cuMemberAccount.setWithdrawAccount4(withdrawAccount.negate());
                    cuMemberAccount.setConsumeAccount4(amount.add(withdrawAccount));
                } else {
                    cuMemberAccount.setWithdrawAccount4(amount);
                }
            }
        } else if (accountClassify == ETradeClassify.RECHARGE.getValue()) {
            cuMemberAccount.setAccount4(amount);
            cuMemberAccount.setConsumeAccount4(amount);
        } else {
            cuMemberAccount.setAccount4(amount);
        }

    }

    @Override
    public CuMemberAccount queryCuMemberAccountByPkMember(Long pkMember) {
        LambdaQueryWrapper<CuMemberAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CuMemberAccount::getPkMember, pkMember);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public List<CuMemberAccount> queryCuMemberAccountByPkMembers(List<Long> pkMemberList) {
        LambdaQueryWrapper<CuMemberAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CuMemberAccount::getPkMember, pkMemberList);
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public CuMemberAccountVO queryWalletBalanceByPkMember(Long pkMember, Integer pkCountry) {
        CuMemberWalletBalanceVO memberWalletBalanceVO;
        List<CuMemberWalletBalanceVO> memberWalletBalanceVOList = new ArrayList<>();
        List<CuMemberRechargeAccountParam> cuMemberRechargeAccountParams = baseMapper.queryWalletBalanceByPkMember(pkMember);
        //根据币种值查询币种
        List<BdAccount> accounts = iAccountServiceApi.memberAccountByType(pkCountry).getData();
        Map<Integer, BdAccount> accountMap = accounts.stream().collect(Collectors.toMap(BdAccount::getFieldValue, Function.identity()));
        BigDecimal total = BigDecimal.ZERO;
        if (CollUtil.isNotEmpty(cuMemberRechargeAccountParams)) {
            for (CuMemberRechargeAccountParam memberRechargeAccountParam : cuMemberRechargeAccountParams) {
                Integer accountType = memberRechargeAccountParam.getAccountType();
                memberWalletBalanceVO = BeanUtil.copyProperties(memberRechargeAccountParam, CuMemberWalletBalanceVO.class);
                BdAccount bdAccount = accountMap.get(accountType);
                if (isShow(bdAccount, memberWalletBalanceVO)) {
                    memberWalletBalanceVO.setUnavailableBalance(memberRechargeAccountParam.getBalance().subtract(memberRechargeAccountParam.getAvailableBalance()));
                    total = total.add(memberRechargeAccountParam.getBalance());
                    memberWalletBalanceVO.setPkAccountId(bdAccount.getPkId());
                    memberWalletBalanceVO.setPkAccount(iCuMemberBaseService.translateAccountValue(bdAccount.getPkId()));
                    memberWalletBalanceVO.setIsRecharge(bdAccount.getIsRecharge());
                    memberWalletBalanceVO.setIsTransfer(bdAccount.getIsTransfer());
                    memberWalletBalanceVO.setIsWithdrawal(bdAccount.getIsWithdrawal());
                    memberWalletBalanceVO.setBackgroundImg(bdAccount.getBackgroundImg());
                    memberWalletBalanceVOList.add(memberWalletBalanceVO);
                }
            }
        }
        CuMemberAccountVO cuMemberAccountVO = new CuMemberAccountVO();
        cuMemberAccountVO.setWalletTotalAmount(total);
        cuMemberAccountVO.setMemberWalletBalanceVOList(memberWalletBalanceVOList);
        return cuMemberAccountVO;
    }

    /**
     * 根据配置 是否显示币种
     *
     * @param bdAccount             币种
     * @param memberWalletBalanceVO 钱包余额
     * @return Boolean
     */
    private Boolean isShow(BdAccount bdAccount, CuMemberWalletBalanceVO memberWalletBalanceVO) {
        if (bdAccount == null) {
            return false;
        }
        //是否固定
        Integer isRegular = bdAccount.getIsRegular();
        BigDecimal balance = memberWalletBalanceVO.getBalance();
        //设置固定为禁止，余额不为零时，显示
        return isRegular.equals(EYesNo.YES.getIntValue()) || (isRegular.equals(EYesNo.NO.getIntValue()) && balance.compareTo(BigDecimal.ZERO) > 0);
    }

    @Override
    public List<CuMemberAccountShowVO> selectAccountDetail(Long pkMember, Integer pkCountry) {
        CuMemberAccountShowVO cuMemberAccountShowVO;
        CuMemberAccount cuMemberAccount = this.queryCuMemberAccountByPkMember(pkMember);
        List<BdAccount> bdAccounts = iCuMemberBaseService.getAccountByCountryId(pkCountry);
        List<CuMemberAccountShowVO> memberAccountShowVOList = new ArrayList<>();
        for (BdAccount bdAccount : bdAccounts) {
            cuMemberAccountShowVO = new CuMemberAccountShowVO();
            Integer pkAccount = bdAccount.getPkId();
            cuMemberAccountShowVO.setAcccountId(pkAccount);

            //余额
            BigDecimal balance = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.ACCOUNT + pkAccount);
            cuMemberAccountShowVO.setBalance(balance);
            cuMemberAccountShowVO.setSort(bdAccount.getSort());
            memberAccountShowVOList.add(cuMemberAccountShowVO);
            //翻译余额账户
            String accountName = iTransactionServiceApi.readTransactionByCache(EnumsPrefixConstants.ACCOUNT + pkAccount, LocaleContextHolder.getLocale().toLanguageTag()).getData();
            cuMemberAccountShowVO.setAccountName(accountName);
        }
        return memberAccountShowVOList;
    }

    @Override
    public List<CuMemberAccountExt> queryMemberAccountByPkcountry(Integer pkCountry) {
        return baseMapper.queryMemberAccountByPkCountry(pkCountry);
    }

    @Override
    public List<CuMemberRechargeAccountParam> queryMemberAccountByMemberCode(String memberCode, List<Integer> accountTypes, Integer pkCountry) {
        List<Integer> pkAccounts = new ArrayList<>();
        for (Integer accountType : accountTypes) {
            pkAccounts.add(iCuMemberBaseService.getAccountValueById(accountType));
        }
        List<CuMemberRechargeAccountParam> cuMemberRechargeAccountParams = baseMapper.queryMemberAccountByMemberCode(memberCode, pkAccounts, null);
        if (CollUtil.isNotEmpty(cuMemberRechargeAccountParams)) {
            List<BdAccount> accountList = iCuMemberBaseService.getAccountByCountryId(pkCountry);
            //币种value对应的币种对象
            Map<Integer, BdAccount> accountMap = accountList.stream().collect(Collectors.toMap(BdAccount::getFieldValue, o -> o));
            for (CuMemberRechargeAccountParam CuMemberRechargeAccountParam : cuMemberRechargeAccountParams) {
                Integer accountType = CuMemberRechargeAccountParam.getAccountType();
                Integer pkAccount = accountMap.get(accountType).getPkId();
                CuMemberRechargeAccountParam.setPkAccount(pkAccount);
                CuMemberRechargeAccountParam.setAccountType(iCuMemberBaseService.translateAccountValue(pkAccount));
            }
        }
        return cuMemberRechargeAccountParams;
    }

    @Override
    public List<CuMemberRechargeAccountParam> queryBatchRechargeAccount(List<Integer> pkAccounts, Integer pkCountry) {
        List<CuMemberRechargeAccountParam> accountParams = new ArrayList<>();
        if (CollUtil.isNotEmpty(pkAccounts)) {
            for (Integer pkAccount : pkAccounts) {
                CuMemberRechargeAccountParam param = new CuMemberRechargeAccountParam();
                param.setPkAccount(pkAccount);
                param.setAccountType(iCuMemberBaseService.translateAccountValue(pkAccount));
                accountParams.add(param);
            }
        }
        return accountParams;
    }

    @Override
    public Boolean updateBatchMemberAccountByPkmember(String batch, Long pkModified, int type) {
        return baseMapper.updateBatchMemberAccountByPkmember(batch, pkModified, type);
    }

    @Override
    public List<CuMemberAccountExt> queryMemberAccountByMemberCodes(List<CuMemberRechargeVO> memberCodes, List<String> memberCodeStrs) {
        return baseMapper.queryMemberAccountByMemberCodes(memberCodes, memberCodeStrs);
    }

    @Override
    public List<CuMemberWalletDetailVO> queryMemberAccountAllByMemberCodes(List<String> memberCodes, Integer pkCountry) {
        List<CuMemberWalletDetailVO> memberWalletDetailVOList = new ArrayList<>();
        List<CuMemberAccountExt> cuMemberAccountExts = baseMapper.queryMemberAccountAllByMemberCodes(memberCodes);
        convertCuMemberAccountVO(memberWalletDetailVOList, cuMemberAccountExts, pkCountry);
        return memberWalletDetailVOList;
    }


    @Override
    public Object[] selectMemberAccountList(CuMemberWalletDetailVO memberWalletDetailVO) {
        List<CuMemberAccountExt> cuMemberAccountExts;
        List<CuMemberWalletDetailVO> memberWalletDetailVOList = new ArrayList<>();
        Integer plevel = memberWalletDetailVO.getPlevel();
        Integer slevel = memberWalletDetailVO.getSlevel();
        //查询默认钱包明细
        if ((null == plevel && null == slevel) || (plevel != null && plevel.equals(1) && null == slevel) || (slevel != null && slevel.equals(1) && null == plevel)) {
            cuMemberAccountExts = baseMapper.selectDefaultMemberAccountList(memberWalletDetailVO);
        } else {
            cuMemberAccountExts = baseMapper.selectMemberAccountList(memberWalletDetailVO);
        }
        convertCuMemberAccountVO(memberWalletDetailVOList, cuMemberAccountExts, memberWalletDetailVO.getPkCountry());
        return new Object[]{cuMemberAccountExts, memberWalletDetailVOList};

    }

    /**
     * 转换VO
     *
     * @param cuMemberAccountVOList 余额VO
     * @param cuMemberAccountExts   余额信息
     */
    private void convertCuMemberAccountVO(List<CuMemberWalletDetailVO> cuMemberAccountVOList, List<CuMemberAccountExt> cuMemberAccountExts, Integer pkCountry) {
        CuMemberWalletDetailVO memberWalletDetailVO;
        if (CollUtil.isNotEmpty(cuMemberAccountExts)) {
            //查询币种值
            List<BdAccount> allAccounts = iCuMemberBaseService.getAccountByCountryId(pkCountry);
            Map<Integer, BdAccount> map = allAccounts.stream().collect(Collectors.toMap(BdAccount::getFieldValue, o -> o));
            for (CuMemberAccountExt cuMemberAccountExt : cuMemberAccountExts) {
                memberWalletDetailVO = new CuMemberWalletDetailVO();
                BeanUtils.copyProperties(cuMemberAccountExt, memberWalletDetailVO);
                for (BdAccount bdAccount : allAccounts) {
                    Integer pkAccount = bdAccount.getFieldValue();
                    BigDecimal availableBalance;
                    //账户金额
                    BigDecimal account = ReflectUtils.invokeGetter(memberWalletDetailVO, MemberFieldConstants.ACCOUNT + pkAccount);
                    account = account == null ? BigDecimal.ZERO : account;
                    if (pkAccount <= MagicNumberConstants.ACC0UNT_LOCK_NUM) {
                        //锁定消费
                        BigDecimal lockConsume = ReflectUtils.invokeGetter(memberWalletDetailVO, MemberFieldConstants.LOCK_ACCOUNT + pkAccount);
                        lockConsume = lockConsume == null ? BigDecimal.ZERO : lockConsume;
                        //锁定转账
                        BigDecimal lockTransfer = ReflectUtils.invokeGetter(memberWalletDetailVO, MemberFieldConstants.LOCK_TRANSFER_ACCOUNT + pkAccount);
                        lockTransfer = lockTransfer == null ? BigDecimal.ZERO : lockTransfer;
                        availableBalance = account.subtract(lockConsume).subtract(lockTransfer);
                    } else if (pkAccount.equals(13)) {
                        //锁定消费
                        BigDecimal lockConsume = ReflectUtils.invokeGetter(memberWalletDetailVO, MemberFieldConstants.LOCK_ACCOUNT + pkAccount);
                        lockConsume = lockConsume == null ? BigDecimal.ZERO : lockConsume;
                        availableBalance = account.subtract(lockConsume);
                    } else {
                        availableBalance = account;
                    }

                    if (pkAccount.equals(EAccount.BONUS.getValue())) {
                        //锁定提现
                        BigDecimal lockWithdraw = ReflectUtils.invokeGetter(memberWalletDetailVO, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + pkAccount);
                        availableBalance = availableBalance.subtract(lockWithdraw);
                        //可提现账户
                        BigDecimal withdrawAccount = ReflectUtils.invokeGetter(memberWalletDetailVO, MemberFieldConstants.WITHDRAW_ACCOUNT + pkAccount);
                        memberWalletDetailVO.setSubmitAccount4(withdrawAccount.subtract(lockWithdraw));
                    }
                    ReflectUtils.invokeSetter(memberWalletDetailVO, MemberFieldConstants.AVAILABLE_ACCOUNT + pkAccount, availableBalance);
                }
                noIncludeAccount(memberWalletDetailVO, map);
                cuMemberAccountVOList.add(memberWalletDetailVO);
            }
        }

    }

    private void noIncludeAccount(CuMemberWalletDetailVO memberWalletDetailVO, Map<Integer, BdAccount> map) {
        for (int i = 1; i < MagicNumberConstants.ACC0UNT_NUM + 1; i++) {
            if (null == map.get(i)) {
                ReflectUtils.invokeSetter(memberWalletDetailVO, MemberFieldConstants.ACCOUNT + i, null);
                ReflectUtils.invokeSetter(memberWalletDetailVO, MemberFieldConstants.LOCK_TRANSFER_ACCOUNT + i, null);
                ReflectUtils.invokeSetter(memberWalletDetailVO, MemberFieldConstants.LOCK_ACCOUNT + i, null);
            }
        }
    }

    @Override
    public List<Long> selectPkMembersByMemberCode(List<String> memberCodes, Integer pkCountry) {
        return baseMapper.selectPkMembersByMemberCode(memberCodes, pkCountry);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean frozenAmount(CuMemberFrozenParam memberFrozenParam) {
        boolean result = false;
        CuMemberAccountExt memberAccount = getCuMemberAccount(memberFrozenParam);
        LoginUser loginUser = memberFrozenParam.getLoginUser();
        List<Long> pkMembers = memberFrozenParam.getPkMembers();
        if (null != memberAccount) {
            memberAccount.setPkModified(loginUser.getUserId());
            memberAccount.setPkMembers(pkMembers);
            CuMemberAccountLog cuMemberAccountLog = packageCuMemberAccountLog(memberFrozenParam, memberAccount);
            result = iCuMemberAccountLogService.save(cuMemberAccountLog);
        }
        //提交审批
        submitApproval(memberFrozenParam);
        return result;
    }

    @Override
    public Integer approvalPass(String frozenData) {
        CuMemberAccountExt memberAccount = JSONUtil.toBean(frozenData, CuMemberAccountExt.class);
        return baseMapper.updateFrozenAmountInfo(memberAccount);
    }


    /**
     * 组装锁定账户信息
     *
     * @param memberFrozenParam 冻结入参
     * @param memberAccount     会员账户信息
     * @return CuMemberAccountLog
     */
    private CuMemberAccountLog packageCuMemberAccountLog(CuMemberFrozenParam memberFrozenParam, CuMemberAccountExt memberAccount) {
        CuMemberPetitionVO memberPetitionVo = memberFrozenParam.getMemberPetitionVo();
        Long pkMember = memberFrozenParam.getLoginUser().getUserId();
        CuMemberAccountLog cuMemberAccountLog = CuMemberAccountLog.builder().approvalCode(memberPetitionVo.getBusinessNo())
                .approveState(EApproveRechargeStatus.WAIT.getValue())
                .approveTime(new Date()).approver(pkMember)
                .lockAccountData(JSONUtil.toJsonStr(memberAccount)).build();
        cuMemberAccountLog.setPkCountry(memberFrozenParam.getPkCountry());
        cuMemberAccountLog.setPkCreator(pkMember);
        return cuMemberAccountLog;
    }

    /**
     * 拼装账户冻结信息
     *
     * @param memberFrozenParam 账户冻结参数
     * @return CuMemberAccount
     */
    private CuMemberAccountExt getCuMemberAccount(CuMemberFrozenParam memberFrozenParam) {
        CuMemberAccountExt cuMemberAccount = null;
        List<CuMemberFrozenDetailParam> memberFrozenDetails = memberFrozenParam.getMemberFrozenDetails();
        if (CollUtil.isNotEmpty(memberFrozenDetails)) {
            cuMemberAccount = new CuMemberAccountExt();
            for (CuMemberFrozenDetailParam param : memberFrozenDetails) {
                Integer memberAccount = param.getMemberAccount();
                Integer accountValue = iCuMemberBaseService.getAccountValueById(memberAccount);
                BigDecimal lockConsume = param.getLockConsume();
                if (null != lockConsume && lockConsume.compareTo(BigDecimal.ZERO) > 0) {
                    ReflectUtils.invokeSetter(cuMemberAccount, MemberFieldConstants.LOCK_ACCOUNT + accountValue, lockConsume);
                }
                BigDecimal lockTransfer = param.getLockTransfer();
                if (null != lockTransfer && lockTransfer.compareTo(BigDecimal.ZERO) > 0) {
                    ReflectUtils.invokeSetter(cuMemberAccount, MemberFieldConstants.LOCK_TRANSFER_ACCOUNT + accountValue, lockTransfer);
                }
                BigDecimal lockWithdraw = param.getLockWithdraw();
                if (null != lockWithdraw && lockWithdraw.compareTo(BigDecimal.ZERO) > 0) {
                    ReflectUtils.invokeSetter(cuMemberAccount, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + accountValue, lockWithdraw);
                }

                String remarks = param.getRemarks();
                if (StringUtils.isNotEmpty(remarks)) {
                    ReflectUtils.invokeSetter(cuMemberAccount, MemberFieldConstants.ACCOUNT + accountValue + MemberFieldConstants.ACCOUNT_REMARKS, remarks);
                }

            }
        }
        return cuMemberAccount;
    }

    /**
     * 提交审批
     *
     * @param cuMemberFrozenParam 冻结信息
     */
    private void submitApproval(CuMemberFrozenParam cuMemberFrozenParam) {
        //调用审批接口，修改审批状态
        CuMemberPetitionVO memberPetitionVo = cuMemberFrozenParam.getMemberPetitionVo();
        List<CuMemberFrozenAmountVO> memberFrozenAmountVOList = memberPetitionVo.getMemberFrozenAmountVOList();
        Set<Long> pkMemberIds = getPkMemberIds(cuMemberFrozenParam);
        ApprovalSubmitDTO approvalSubmitDTO = ApprovalSubmitDTO.builder().eApprovalBusiness(EApprovalBusiness.FROZEN)
                .businessCode(memberPetitionVo.getBusinessNo()).businessData(JSONUtil.toJsonStr(memberFrozenAmountVOList))
                .signType(ESignType.getEnumByValue(memberPetitionVo.getSignType())).userIdList(memberPetitionVo.getUserIdList())
                .sendIdList(memberPetitionVo.getSendIdList()).remark(memberPetitionVo.getDescription()).pkMemberList(pkMemberIds).build();

        R<String> submit = iApprovalServiceApi.submit(approvalSubmitDTO, cuMemberFrozenParam.getLoginUser());
        if (!submit.isSuccess()) {
            log.error("====" + submit.getData());
            throw new RuntimeException(submit.getMsg());
        }
    }


    /**
     * 获取充值用户主键信息
     *
     * @param cuMemberFrozenParam
     * @return Set<Long>
     */
    private Set<Long> getPkMemberIds(CuMemberFrozenParam cuMemberFrozenParam) {
        return CollUtil.newHashSet(cuMemberFrozenParam.getPkMembers());
    }

    @Override
    public List<CuMemberAccountExt> queryMemberAccountByPkMember(List<MemberAmountDTO> pkMembers) {
        return baseMapper.queryMemberAccountByPkMember(pkMembers);
    }


    @Override
    public Boolean batchUpdateMemberAccountByPkmember(List<MemberAmountDTO> pkMemberList, int pkAccount, Integer isWithdraw) {
        return baseMapper.batchUpdateMemberAccountByPkMember(pkMemberList, pkAccount, isWithdraw);
    }

    @Override
    public Boolean batchUpdateMemberAccountByPkMemberCountry(List<MemberAmountDTO> pkMemberList, Integer isWithdraw) {
        return baseMapper.batchUpdateMemberAccountByPkMemberCountry(pkMemberList, isWithdraw);
    }

    @Override
    public Integer batchUpdateWalletStateByPkMember(List<Integer> businessValueList, List<BusinessMemberVO> businessMemberList, Long updatePkMember) {
        return baseMapper.batchUpdateWalletStateByPkMember(businessValueList, businessMemberList, updatePkMember);
    }

    @Override
    public List<CuMemberAccount> selectMemberAccountByPkMember(List<Long> pkMembers) {
        return baseMapper.selectMemberAccountByPkMember(pkMembers);
    }


    @Override
    public List<CuMemberAccountExt> queryAccountAndMemberInfo(List<Long> memberIdList) {
        return baseMapper.queryAccountAndMemberInfo(memberIdList);
    }

    @Override
    public Object[] queryMemberAccountByMemberCodeAndName(CuMemberAccountVO cuMemberAccountVO) {
        CuMemberAccountExtVO cuMemberAccountExtVO;
        List<CuMemberAccountExtVO> cuMemberAccountExtVOList = new ArrayList<>();
        List<CuMemberAccountExt> cuMemberAccountExtList = baseMapper.queryMemberAccountByMemberCodeAndName(cuMemberAccountVO);
        if (CollUtil.isNotEmpty(cuMemberAccountExtList)) {
            //已选择的币种值
            List<Integer> selectedPkAccounts = cuMemberAccountVO.getPkAccounts();
            Integer pkCountry = cuMemberAccountVO.getPkCountry();
            //汇率
            BigDecimal exchangeRate = iCuMemberBaseService.getCurrency(pkCountry).getInExchangeRate();
            //配置的币种
            List<BdAccount> bdAccounts = iCuMemberBaseService.getAccountByCountryId(pkCountry);
            List<Integer> allAccountValues = bdAccounts.stream().map(BdAccount::getFieldValue).collect(Collectors.toList());
            for (CuMemberAccountExt cuMemberAccountExt : cuMemberAccountExtList) {
                cuMemberAccountExtVO = BeanUtil.copyProperties(cuMemberAccountExt, CuMemberAccountExtVO.class);
                getCuMemberAccountExtVO(cuMemberAccountExtVO, selectedPkAccounts, allAccountValues, exchangeRate);
                cuMemberAccountExtVOList.add(cuMemberAccountExtVO);
            }
        }
        return new Object[]{cuMemberAccountExtList, cuMemberAccountExtVOList};
    }

    @Override
    public List<CuMemberAccountExportVO> selectFrozenAmountExport(CuMemberAccountVO cuMemberAccountVO) {
        CuMemberAccountExportVO memberAccountExportVO;
        List<CuMemberAccountExportVO> memberAccountExportVOList = new ArrayList<>();
        List<CuMemberAccountExt> cuMemberAccountExtList = baseMapper.queryMemberAccountByMemberCodeAndName(cuMemberAccountVO);
        if (CollUtil.isNotEmpty(cuMemberAccountExtList)) {
            Integer pkCountry = cuMemberAccountVO.getPkCountry();
            //已选择的币种值
            List<Integer> selectedPkAccounts = cuMemberAccountVO.getPkAccounts();
            //汇率
            BigDecimal exchangeRate = iCuMemberBaseService.getCurrency(pkCountry).getInExchangeRate();
            //配置的币种
            for (CuMemberAccountExt cuMemberAccountExt : cuMemberAccountExtList) {
                memberAccountExportVO = CuMemberAccountExportVO.builder()
                        .memberCode(cuMemberAccountExt.getMemberCode())
                        .memberName(cuMemberAccountExt.getMemberName()).build();
                getCuMemberAccountExtVO(memberAccountExportVO, cuMemberAccountExt, selectedPkAccounts, exchangeRate);
                memberAccountExportVOList.add(memberAccountExportVO);
            }
        }
        return memberAccountExportVOList;
    }


    /**
     * 根据前端选择的币种返回显示内容
     *
     * @param memberAccountExportVO 账户信息
     * @param selectedPkAccounts    前端选择的币种
     * @return CuMemberAccountExtVO
     */
    private CuMemberAccountExportVO getCuMemberAccountExtVO(CuMemberAccountExportVO memberAccountExportVO, CuMemberAccountExt cuMemberAccountExt, List<Integer> selectedPkAccounts, BigDecimal exchangeRate) {
        BigDecimal lockConsume = BigDecimal.ZERO;
        BigDecimal lockTransfer = BigDecimal.ZERO;
        if (CollUtil.isNotEmpty(selectedPkAccounts)) {
            for (Integer pkAccount : selectedPkAccounts) {
                //币种
                BigDecimal account = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.ACCOUNT + pkAccount);
                if (null == account) {
                    continue;
                }
                ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.ACCOUNT + pkAccount, account);
                BigDecimal settleAccount = account.divide(exchangeRate, 4, RoundingMode.HALF_UP);
                ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.SETTLE_ACCOUNT + pkAccount, settleAccount);
                if (pkAccount <= 10) {
                    //锁定消费
                    lockConsume = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.LOCK_ACCOUNT + pkAccount);
                    ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.LOCK_ACCOUNT + pkAccount, lockConsume);

                    BigDecimal settleLockConsume = lockConsume.divide(exchangeRate, 4, RoundingMode.HALF_UP);
                    ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.LOCK_SETTLE_ACCOUNT + pkAccount, settleLockConsume);
                    //锁定转账
                    lockTransfer = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.LOCK_TRANSFER_ACCOUNT + pkAccount);
                    ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.LOCK_TRANSFER_ACCOUNT + pkAccount, lockTransfer);

                    BigDecimal settleLockTransfer = lockTransfer.divide(exchangeRate, 4, RoundingMode.HALF_UP);
                    ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.LOCK_SETTLE_TRANSFER_ACCOUNT + pkAccount, settleLockTransfer);
                }
                //可用金额
                BigDecimal availableAccount = account.subtract(lockConsume).subtract(lockTransfer);
                //锁定提现
                if (pkAccount.equals(EAccount.BONUS.getValue())) {
                    BigDecimal lockWithdraw = ReflectUtils.invokeGetter(cuMemberAccountExt, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + pkAccount);
                    availableAccount = availableAccount.subtract(lockWithdraw);

                    ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + pkAccount, lockWithdraw);

                    BigDecimal settleLockWithdraw = lockWithdraw.divide(exchangeRate, 4, RoundingMode.HALF_UP);
                    ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.LOCK_SETTLE_WITHDRAW_ACCOUNT + pkAccount, settleLockWithdraw);
                }
                //可用金额
                ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.AVAILABLE_ACCOUNT + pkAccount, availableAccount);

                BigDecimal settleAvailableAccount = availableAccount.divide(exchangeRate, 4, RoundingMode.HALF_UP);
                ReflectUtils.invokeSetter(memberAccountExportVO, MemberFieldConstants.SETTLE_AVAILABLE_ACCOUNT + pkAccount, settleAvailableAccount);
            }
        }

        return memberAccountExportVO;
    }

    /**
     * 根据前端选择的币种返回显示内容
     *
     * @param cuMemberAccountExtVO 账户信息
     * @param selectedPkAccounts   前端选择的币种
     * @param allAccountValues     配置的币种值
     * @return CuMemberAccountExtVO
     */
    private CuMemberAccountExtVO getCuMemberAccountExtVO(CuMemberAccountExtVO cuMemberAccountExtVO, List<Integer> selectedPkAccounts, List<Integer> allAccountValues, BigDecimal exchangeRate) {
        BigDecimal lockConsume = BigDecimal.ZERO;
        BigDecimal lockTransfer = BigDecimal.ZERO;

        if (CollUtil.isEmpty(selectedPkAccounts)) {
            selectedPkAccounts = allAccountValues;
        }
        for (Integer pkAccount : selectedPkAccounts) {
            //币种
            BigDecimal account = ReflectUtils.invokeGetter(cuMemberAccountExtVO, MemberFieldConstants.ACCOUNT + pkAccount);
            if (null == account) {
                continue;
            }
            BigDecimal settleAccount = account.divide(exchangeRate, 4, RoundingMode.HALF_UP);
            ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.SETTLE_ACCOUNT + pkAccount, settleAccount);
            if (pkAccount <= 10) {
                //锁定消费
                lockConsume = ReflectUtils.invokeGetter(cuMemberAccountExtVO, MemberFieldConstants.LOCK_ACCOUNT + pkAccount);
                BigDecimal settleLockConsume = lockConsume.divide(exchangeRate, 4, RoundingMode.HALF_UP);
                ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.LOCK_SETTLE_ACCOUNT + pkAccount, settleLockConsume);
                //锁定转账
                lockTransfer = ReflectUtils.invokeGetter(cuMemberAccountExtVO, MemberFieldConstants.LOCK_TRANSFER_ACCOUNT + pkAccount);
                BigDecimal settleLockTransfer = lockTransfer.divide(exchangeRate, 4, RoundingMode.HALF_UP);
                ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.LOCK_SETTLE_TRANSFER_ACCOUNT + pkAccount, settleLockTransfer);
            }
            //可用金额
            BigDecimal availableAccount = account.subtract(lockConsume).subtract(lockTransfer);
            //锁定提现
            if (pkAccount.equals(EAccount.BONUS.getValue())) {
                BigDecimal lockWithdraw = ReflectUtils.invokeGetter(cuMemberAccountExtVO, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + pkAccount);
                availableAccount = availableAccount.subtract(lockWithdraw);

                BigDecimal settleLockWithdraw = lockWithdraw.divide(exchangeRate, 4, RoundingMode.HALF_UP);
                ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.LOCK_SETTLE_WITHDRAW_ACCOUNT + pkAccount, settleLockWithdraw);
            }
            //可用金额
            ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.AVAILABLE_ACCOUNT + pkAccount, availableAccount);

            BigDecimal settleAvailableAccount = availableAccount.divide(exchangeRate, 4, RoundingMode.HALF_UP);
            ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.SETTLE_AVAILABLE_ACCOUNT + pkAccount, settleAvailableAccount);
        }
        //末选中的币种 置为null 前台不显示
        allAccountValues.removeAll(selectedPkAccounts);
        for (Integer account : allAccountValues) {
            ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.ACCOUNT + account, null);
            if (account <= 10) {
                ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.LOCK_ACCOUNT + account, null);
                ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.LOCK_TRANSFER_ACCOUNT + account, null);
            }
            if (account.equals(EAccount.BONUS.getValue())) {
                ReflectUtils.invokeSetter(cuMemberAccountExtVO, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + account, null);
            }
        }
        return cuMemberAccountExtVO;
    }

    @Override
    public void updateMemberAccountGrantByPeriod(Integer pkCountry, Integer startPeriod, Integer endPeriod) {
        baseMapper.updateMemberAccountGrantByPeriod(pkCountry, startPeriod, endPeriod);
    }

    @Override
    public void updateMemberAccountWithdrawalByPeriod(Integer startPeriod, Integer endPeriod, Integer pkCountry) {
        baseMapper.updateMemberAccountWithdrawalByPeriod(startPeriod, endPeriod, pkCountry);
    }

    @Override
    public CuMemberRechargeAccountParam findMemberBalanceById(Integer pkAccount, Long pkMember) {
        List<CuMemberRechargeAccountParam> cuMemberRechargeAccountParams = baseMapper.queryMemberAccountByMemberCode(null, Collections.singletonList(pkAccount), pkMember);
        return CollUtil.isNotEmpty(cuMemberRechargeAccountParams) ? cuMemberRechargeAccountParams.get(0) : null;
    }


    @Override
    public Boolean batchUpdateBonusAccountByPkMember(List<CuMemberBonusAccountParam> bonusList, int operateType, Long pkModified) {
        return baseMapper.batchUpdateBonusAccountByPkMember(bonusList, operateType, pkModified);
    }

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

    @Override
    public void deleteCuMemberAccountByPkMember(Long pkMember, Long pkApprove, Date currentDateTime) {
        UpdateWrapper<CuMemberAccount> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set(SystemFieldConstants.DEL_FLAG, EYesNo.NO.getIntValue());
        updateWrapper.set(SystemFieldConstants.PK_MODIFIED, pkApprove);
        updateWrapper.set(SystemFieldConstants.MODIFIED_TIME, currentDateTime);
        updateWrapper.eq(MemberFieldConstants.PK_MEMBER, pkMember);
        update(updateWrapper);
    }

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

    @Override
    public int insertBatchCuMemberAccount(List<CuMemberAccount> memberAccountList) {
        return baseMapper.insertBatchCuMemberAccount(memberAccountList);
    }

    @Override
    public CuMemberAccountExt queryAccountSummaryByMember(String memberCode, Integer pkCountry) {
        return baseMapper.queryAccountSummaryByMember(memberCode, pkCountry);
    }

    @Override
    public CuMemberAccountExt queryAccountSummaryByVertex(Long pkVertex, Integer pkCountry) {
        return baseMapper.queryAccountSummaryByVertex(pkVertex, pkCountry);
    }

}

