package com.sckw.payment.service;

import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sckw.core.common.enums.NumberConstant;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.page.PageRes;
import com.sckw.core.utils.*;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.manage.api.RemoteManageService;
import com.sckw.manage.api.model.dto.res.FindEntCooperateResVo;
import com.sckw.payment.api.model.constant.ChannelEnum;
import com.sckw.payment.api.model.dto.WalletDto;
import com.sckw.payment.api.model.dto.common.R;
import com.sckw.payment.dao.KwpWalletRefundMapper;
import com.sckw.payment.dao.KwpWalletTransferMapper;
import com.sckw.payment.job.AsyncPool;
import com.sckw.payment.model.KwpWallet;
import com.sckw.payment.model.KwpWalletRefund;
import com.sckw.payment.model.KwpWalletRelation;
import com.sckw.payment.model.KwpWalletTransfer;
import com.sckw.payment.model.constant.*;
import com.sckw.payment.model.dto.WalletInfoDto;
import com.sckw.payment.model.dto.WalletRelationDto;
import com.sckw.payment.model.dto.common.BusinessNo;
import com.sckw.payment.model.dto.common.Page;
import com.sckw.payment.model.dto.page.CashPage;
import com.sckw.payment.model.dto.page.PrePayWalletPage;
import com.sckw.payment.model.dto.wallet.*;
import com.sckw.payment.model.vo.PrePayWalletVo;
import com.sckw.payment.model.vo.req.*;
import com.sckw.payment.model.vo.req.page.MoneyPage;
import com.sckw.payment.model.vo.req.page.PrePayPage;
import com.sckw.payment.model.vo.req.page.RefundPage;
import com.sckw.payment.model.vo.res.*;
import com.sckw.redis.config.RedisLockUtil;
import com.sckw.redis.constant.RedisLockKey;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.EntCertificateResDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 钱包
 *
 * @author xucaiqin
 * @date 2023-08-28 15:38:53
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WalletService {
    private final PayCenterService payCenterService;
    private final KwpWalletPrepayService kwpWalletPrepayService;
    private final KwpWalletRelationService walletRelationService;
    private final WalletOrderService walletOrderService;
    private final KwpWalletRefundMapper kwpWalletRefundMapper;
    private final KwpWalletTransferMapper kwpWalletTransferMapper;
    private final RedisLockUtil redisLockUtil;
    private final KwpWalletRefundSubService kwpWalletRefundSubService;
    private final KwpWalletService kwpWalletService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteManageService remoteManageService;

    /**
     * 填充时间等参数
     *
     * @param tradeReq 请求参数
     */
    private void fillPara(MoneyPage tradeReq) {
        if (StringUtils.isNotBlank(tradeReq.getStartCreateTime())) {
            tradeReq.setStartCreateTime(StringTimeUtil.fillStart(tradeReq.getStartCreateTime()));
        }
        if (StringUtils.isNotBlank(tradeReq.getEndCreateTime())) {
            tradeReq.setEndCreateTime(StringTimeUtil.fillEnd(tradeReq.getEndCreateTime()));
        }
    }

    /**
     * 通过中台用户id转为企业名称
     *
     * @param id 中台用户id
     * @return
     */
    private String getFirmName(String id) {
        if (StringUtils.isBlank(id)) {
            return "";
        }
        Long ent = walletRelationService.getEnt(id);
        if (Objects.nonNull(ent)) {
            EntCacheResDto entCacheResDto = remoteSystemService.queryEntCacheById(ent);
            if (Objects.nonNull(entCacheResDto)) {
                return entCacheResDto.getFirmName();
            }
        }
        return "";
    }

    /**
     * 根据中台用户id查询企业id
     *
     * @param id 中台用户id
     * @return
     */
    private Long getEnt(String id) {
        if (StringUtils.isBlank(id)) {
            return null;
        }
        return walletRelationService.getEnt(id);
    }

    /**
     * 查询中台用户id
     *
     * @param id
     * @return
     */
    private String getUid(Long id) {
        if (Objects.isNull(id)) {
            return null;
        }
        return walletRelationService.getRelation(id);
    }

    /**
     * 通过企业名称查询关联的中台用户id
     *
     * @param entName
     * @return
     */
    private List<String> findFilter(String entName) {
        if (StringUtils.isNotBlank(entName)) {
            Long entId = LoginUserHolder.getEntId();
            List<FindEntCooperateResVo> allCooperateEnt = remoteManageService.findAllCooperateEnt(entId);
            if (!CollectionUtils.isEmpty(allCooperateEnt)) {
                List<Long> collect = allCooperateEnt.stream().filter(a -> StringUtils.contains(a.getEntName(), entName)).map(FindEntCooperateResVo::getEntId).toList();
                List<String> res = new ArrayList<>();
                for (Long aLong : collect) {
                    String relation = walletRelationService.getRelation(aLong);
                    if (StringUtils.isNotBlank(relation) && !res.contains(relation)) {
                        res.add(relation);
                    }
                }
                return res;
            }
        }
        return new ArrayList<>();
    }

    /**
     * 通过企业名称查询关联的中台用户id
     *
     * @param entName
     * @return "uid,uid,uid"
     */
    private String findFilterStr(String entName) {
        List<String> filter = findFilter(entName);
        return StringUtils.join(filter, ",");
    }

    /**
     * 金额转元并转字符串
     *
     * @param money
     * @return
     */
    private String dfMoney(Long money) {
        if (Objects.isNull(money)) {
            return "0.00";
        }
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(money / 100.0D);
    }

    /**
     * 退款中金额和相关操作
     *
     * @param change 是否需要转换预付人与预收人
     * @return
     */
    private void refundMoney(PrePayWallet prePayWallet, PrePayWalletVo prePayWalletVo, boolean change) {
        DecimalFormat df = new DecimalFormat("0.00");
        List<KwpWalletRefund> query = walletOrderService.query(change, prePayWallet.getUid(), prePayWallet.getFilter(), prePayWallet.getChannel());
        if (!CollectionUtils.isEmpty(query)) {
            BigDecimal reduce = query.stream().map(KwpWalletRefund::getMoney).reduce(BigDecimal.ZERO, (o, n) -> {
                if (Objects.isNull(n)) {
                    return o.add(new BigDecimal("0.0"));
                }
                return o.add(n);
            });
            prePayWalletVo.setRefundApMoney(df.format(reduce));
        } else {
            prePayWalletVo.setRefundApMoney("0.00");
        }
    }

    /**
     * 更新时间填充
     *
     * @param prePayWalletVo
     */
    private void time(PrePayWalletVo prePayWalletVo) {
        prePayWalletVo.setUpdateTime(kwpWalletService.queryTime(prePayWalletVo.getUid(), prePayWalletVo.getFilter(), prePayWalletVo.getChannel()));
    }
    private void timeReceive(PrePayWalletVo prePayWalletVo) {
        prePayWalletVo.setUpdateTime(kwpWalletService.queryTime(prePayWalletVo.getFilter(), prePayWalletVo.getUid(), prePayWalletVo.getChannel()));
    }

    /**
     * 资金明细设置退款中金额
     *
     * @param fundVo 返回值vo
     */
    private void refundMoney2(FundVo fundVo) {
        DecimalFormat df = new DecimalFormat("0.00");
        List<KwpWalletRefund> kwpWalletRefunds = walletOrderService.queryList(fundVo.getUid(), fundVo.getFilter(), fundVo.getChannel(), RefundEnum.REFUNDING);
        if (!CollectionUtils.isEmpty(kwpWalletRefunds)) {
            BigDecimal reduce = kwpWalletRefunds.stream().map(KwpWalletRefund::getMoney).reduce(BigDecimal.ZERO, (o, n) -> {
                if (Objects.isNull(n)) {
                    return o.add(new BigDecimal("0.0"));
                }
                return o.add(n);
            });
            fundVo.setRefundMoney(df.format(reduce));
        } else {
            fundVo.setRefundMoney("0.00");
        }
    }

    /**
     * 计算转账中金额
     *
     * @param fundVo
     */
    private void transferMoney(FundVo fundVo) {
        DecimalFormat df = new DecimalFormat("0.00");
        BigDecimal bigDecimal = kwpWalletTransferMapper.sumMoney(fundVo);
        fundVo.setTransferMoney(df.format(bigDecimal));
    }

    /**
     * 相关操作
     *
     * @param fundVo
     */
    private void action(FundVo fundVo) {
        KwpWallet kwpWallet = kwpWalletService.queryOne(fundVo.getUid(), fundVo.getFilter(), fundVo.getChannel());
        if (Objects.nonNull(kwpWallet)) {
            fundVo.setAction(kwpWallet.getAction());
            fundVo.setUpdateTime(kwpWallet.getActionTime());
        }
    }

    /**
     * 按钱包渠道进行统计钱包清单数量
     *
     * @param entName
     * @return
     */
    public List<ChannelCount> walletCount(String entName) {
        Long entId = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId);
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("暂未开通电子钱包");
        }
        List<String> filterList = new ArrayList<>();
        //筛选指定企业的数据
        if (StringUtils.isNotBlank(entName)) {
            filterList = findFilter(entName);
        } else {
            //筛选所有的
            filterList.add("");
        }
        List<ChannelCount> channelDetails = new ArrayList<>();
        HashMap<String, Integer> mapCount = new HashMap<>();
        int all = 0;
        for (String filter : filterList) {
            R<List<WalletDto>> wallet = payCenterService.wallet(uid, null, filter);
            if (wallet.getStatus()) {
                List<WalletDto> data = wallet.getData();
                if (!CollectionUtils.isEmpty(data)) {
                    all += data.size();
                    Map<String, List<WalletDto>> map = data.stream().collect(Collectors.groupingBy(WalletDto::getChannel));
                    for (Map.Entry<String, List<WalletDto>> one : map.entrySet()) {
                        List<WalletDto> value = one.getValue();
                        Integer size = CollectionUtils.isEmpty(value) ? 0 : value.size();
                        mapCount.compute(one.getKey(), (k, v) -> Objects.isNull(v) ? size : size + v);
                    }
                }
            }
        }
        //所有的
        mapCount.put(WalletChannelEnum.ALL.getChannel(), all);
        ChannelCount channelCount;
        for (WalletChannelEnum value : WalletChannelEnum.values()) {
            channelCount = new ChannelCount(value.getValue(), value.getDesc(), value.getChannel(), Objects.isNull(mapCount.get(value.getChannel())) ? 0 : mapCount.get(value.getChannel()));
            channelDetails.add(channelCount);
        }
        return channelDetails;
    }

    /**
     * 钱包总览信息
     *
     * @return
     */
    public WalletDetail walletOverview(boolean queryChannel) {
        Long entId = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId);
        if (StringUtils.isBlank(uid)) {
            return new WalletDetail(LoginUserHolder.getEntName(), "-", "-", "-", 0, new ArrayList<>());
        }
        //钱包总览信息
        R<WalletOverview> wallet = payCenterService.general(uid);
        if (wallet.getStatus()) {
            WalletOverview data = wallet.getData();
            List<ChannelDetail> channelDetails = new ArrayList<>();
            //是否查询渠道详情 适配app端
            if (queryChannel) {
                //查询钱包清单，统计个渠道金额数量等
                R<List<WalletDto>> wallet1 = payCenterService.wallet(uid, null, "");
                if (wallet1.getStatus()) {
                    List<WalletDto> data1 = wallet1.getData();
                    if (!CollectionUtils.isEmpty(data1)) {
                        // 渠道,渠道下的钱包作为的map
                        Map<String, List<WalletDto>> map = data1.stream().collect(Collectors.groupingBy(WalletDto::getChannel));
                        ChannelDetail channelDetail;
                        for (Map.Entry<String, List<WalletDto>> one : map.entrySet()) {
                            //channel
                            String key = one.getKey();
                            //channel下的钱包
                            List<WalletDto> value = one.getValue();
                            Long money = 0L;
                            Long totalMoney = 0L;
                            if (!CollectionUtils.isEmpty(value)) {
                                for (WalletDto walletDto : value) {
                                    money += walletDto.getMoney();
                                    totalMoney += walletDto.getTotalMoney();
                                }
                            }
                            channelDetail = new ChannelDetail();
                            channelDetail.setChannel(key);
                            channelDetail.setName(WalletChannelEnum.getDesc(key));
                            channelDetail.setMoney(String.valueOf(money / 100D));
                            channelDetail.setTotalMoney(String.valueOf(totalMoney / 100D));
                            channelDetail.setOpenFlag(true);
                            channelDetails.add(channelDetail);
                        }
                    }
                }
            } else {
                List<String> channels = data.getChannels();
                if (!CollectionUtils.isEmpty(channels)) {
                    ChannelDetail channelDetail;
                    for (String channel : channels) {
                        channelDetail = new ChannelDetail();
                        channelDetail.setChannel(channel);
                        channelDetail.setName(WalletChannelEnum.getDesc(channel));
                        channelDetail.setMoney("-");
                        channelDetail.setTotalMoney("-");
                        channelDetail.setOpenFlag(true);
                        channelDetails.add(channelDetail);
                    }
                }
            }
            return new WalletDetail(LoginUserHolder.getEntName(), String.valueOf(data.getTotalMoney() / 100D), String.valueOf(data.getChargingMoney()), String.valueOf(data.getWdingMoney()), data.getChannelTotal(), channelDetails);
        }
        return new WalletDetail(LoginUserHolder.getEntName(), "-", "-", "-", 0, new ArrayList<>());
    }

    /**
     * 渠道开通情况
     *
     * @return
     */
    public Object channel() {
        String uid = walletRelationService.getRelation(LoginUserHolder.getEntId());
        if (StringUtils.isNotBlank(uid)) {
            R<WalletOverview> wallet = payCenterService.general(uid);
            if (wallet.getStatus()) {
                WalletOverview data = wallet.getData();
                //已开通的渠道
                List<String> channels = data.getChannels();

                List<ChannelDetail> res = new ArrayList<>();
                for (WalletChannelEnum value : WalletChannelEnum.channelEnumList()) {
                    ChannelDetail channelDetail = new ChannelDetail();
                    channelDetail.setUid(uid);
                    channelDetail.setChannel(value.getChannel());
                    channelDetail.setName(value.getDesc());
                    channelDetail.setMoney("-");
                    channelDetail.setTotalMoney("-");
                    channelDetail.setOpenFlag(channels.contains(value.getChannel()));
                    res.add(channelDetail);
                }
                return res;
            }
        }
        return WalletChannelEnum.channelEnumList().stream().map(a -> {
            ChannelDetail channelDetail = new ChannelDetail();
            channelDetail.setUid("");
            channelDetail.setChannel(a.getChannel());
            channelDetail.setName(a.getDesc());
            channelDetail.setMoney("-");
            channelDetail.setTotalMoney("-");
            channelDetail.setOpenFlag(false);
            return channelDetail;
        }).collect(Collectors.toList());
    }

    /**
     * 查询资金明细
     *
     * @return
     */
    public Object walletDetail(WalletDetailReq walletDetailReq) {
        log.info("查询资金明细:{}", JSONObject.toJSONString(walletDetailReq));
        Long entId = LoginUserHolder.getEntId();
        //查询我方企业开通的渠道
        String uid = walletRelationService.getRelation(entId);
        if (StringUtils.isBlank(uid)) {
            return PageRes.handPage(walletDetailReq.getPage(), walletDetailReq.getPageSize(), new ArrayList<>());
        }
        ChannelEnum channelEnum = null;
        if (StringUtils.isNotBlank(walletDetailReq.getChannel())) {
            channelEnum = ChannelEnum.getByValue(walletDetailReq.getChannel());
            if (Objects.isNull(channelEnum)) {
                throw new BusinessException("支付通道不存在");
            }
        }
        List<WalletDto> res = new ArrayList<>();
        long sum = 0L;
        //筛选企业
        String entName = walletDetailReq.getEntName();
        if (StringUtils.isNotBlank(entName)) {
            List<String> filterList = findFilter(entName);
            //未筛选出数据
            if (CollectionUtils.isEmpty(filterList)) {
                return PageRes.handPage(walletDetailReq.getPage(), walletDetailReq.getPageSize(), new ArrayList<>());
            }
            for (String filter : filterList) {
                R<Wallet> walletR = payCenterService.walletSum(uid, channelEnum, filter);
                if (walletR.getStatus()) {
                    Wallet data = walletR.getData();
                    sum += data.getTotalMoney();
                    List<WalletDto> rows = data.getRows();
                    if (CollectionUtils.isEmpty(rows)) {
                        continue;
                    }
                    res.addAll(rows);
                }
            }
        } else {
            //不搜索往来单位
            R<Wallet> wallet = payCenterService.walletSum(uid, channelEnum, "");
            if (wallet.getStatus()) {
                Wallet data = wallet.getData();
                sum += data.getTotalMoney();
                if (!CollectionUtils.isEmpty(data.getRows())) {
                    res.addAll(data.getRows());
                }
            }
        }

        List<FundVo> vo = new ArrayList<>();
        FundVo fundVo;

        //组装res数据
        for (WalletDto re : res) {
            fundVo = new FundVo();
            BeanUtils.copyProperties(re, fundVo);
            fundVo.setChannelLabel(ChannelEnum.getDesc(re.getChannel()));
            fundVo.setUidName(getFirmName(re.getUid()));
            fundVo.setFilterName(getFirmName(re.getFilter()));
            fundVo.setMoney(dfMoney(re.getMoney()));
            fundVo.setWithdrawingMoney(dfMoney(re.getWithdrawingMoney()));
            fundVo.setChargingMoney(dfMoney(re.getChargingMoney()));
            fundVo.setTotalMoney(dfMoney(re.getTotalMoney()));
            refundMoney2(fundVo);
            transferMoney(fundVo);
            action(fundVo);
            vo.add(fundVo);
        }
        DecimalFormat df = new DecimalFormat("0.00");
        return new MorePageRes<>(walletDetailReq.getPage(), walletDetailReq.getPageSize(), vo, df.format(sum / 100.0D));
    }

    /**
     * 运营端查询资金明细
     *
     * @param walletDetailReq
     * @return
     */
    public Object walletDetail2(WalletDetailReq walletDetailReq) {
        log.info("运营端查询资金明细:{}", JSONObject.toJSONString(walletDetailReq));
        List<String> all = walletRelationService.getAll();
        if (CollectionUtils.isEmpty(all)) {
            return PageRes.handPage(walletDetailReq.getPage(), walletDetailReq.getPageSize(), new ArrayList<>());
        }

        ChannelEnum channelEnum = null;
        if (StringUtils.isNotBlank(walletDetailReq.getChannel())) {
            channelEnum = ChannelEnum.getByValue(walletDetailReq.getChannel());
            if (Objects.isNull(channelEnum)) {
                throw new BusinessException("支付通道不存在");
            }
        }

        List<WalletDto> res = new ArrayList<>();
        long sum = 0L;
        //筛选企业
        String entName = walletDetailReq.getEntName();
        if (StringUtils.isNotBlank(entName)) {
            List<String> filterList = findFilter(entName);
            //未筛选出数据
            if (CollectionUtils.isEmpty(filterList)) {
                return PageRes.handPage(walletDetailReq.getPage(), walletDetailReq.getPageSize(), new ArrayList<>());
            }
            for (String uid : all) {
                for (String filter : filterList) {
                    R<Wallet> walletR = payCenterService.walletSum(uid, channelEnum, filter);
                    if (walletR.getStatus()) {
                        Wallet data = walletR.getData();
                        sum += data.getTotalMoney();
                        List<WalletDto> rows = data.getRows();
                        if (CollectionUtils.isEmpty(rows)) {
                            continue;
                        }
                        res.addAll(rows);
                    }
                }
            }
        } else {
            //不搜索往来单位
            for (String uid : all) {
                R<Wallet> wallet = payCenterService.walletSum(uid, channelEnum, "");
                if (wallet.getStatus()) {
                    Wallet data = wallet.getData();
                    sum += data.getTotalMoney();
                    if (!CollectionUtils.isEmpty(data.getRows())) {
                        res.addAll(data.getRows());
                    }
                }
            }
        }

        List<FundVo> vo = new ArrayList<>();
        FundVo fundVo;

        //组装res数据
        for (WalletDto re : res) {
            fundVo = new FundVo();
            BeanUtils.copyProperties(re, fundVo);
            fundVo.setChannelLabel(ChannelEnum.getDesc(re.getChannel()));
            fundVo.setUidName(getFirmName(re.getUid()));
            fundVo.setFilterName(getFirmName(re.getFilter()));
            fundVo.setMoney(dfMoney(re.getMoney()));
            fundVo.setWithdrawingMoney(dfMoney(re.getWithdrawingMoney()));
            fundVo.setChargingMoney(dfMoney(re.getChargingMoney()));
            fundVo.setTotalMoney(dfMoney(re.getTotalMoney()));
            refundMoney2(fundVo);
            transferMoney(fundVo);
            action(fundVo);
            vo.add(fundVo);
        }
        DecimalFormat df = new DecimalFormat("0.00");
        return new MorePageRes<>(walletDetailReq.getPage(), walletDetailReq.getPageSize(), vo, df.format(sum / 100.0D));
    }

    /**
     * 新增账目
     *
     * @return
     */
    public Object addWallet(AddWalletReq addWalletReq) {
        log.info("新增账目：{}", JSONObject.toJSONString(addWalletReq));
        Long entId1 = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId1);
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("您暂未开通电子钱包");
        }
        String entId = addWalletReq.getEntId();
        String filter = walletRelationService.getRelation(Long.parseLong(entId));
        if (StringUtils.isBlank(filter)) {
            throw new BusinessException("合作单位暂未开通电子钱包");
        }
        ChannelEnum channelEnum = ChannelEnum.getByValue(addWalletReq.getChannel());
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }
        //1.开通钱包
        R<Object> objectR = payCenterService.walletIndex(uid, channelEnum, filter, "");
        log.info("新增账目-开通钱包：{}", JSONObject.toJSONString(objectR));
        if (!objectR.getStatus()) {
            throw new BusinessException(StringUtils.isBlank(objectR.getMsg()) ? "钱包开通失败" : objectR.getMsg());
        }
        //2.发起充值
        R<PayIndex> payIndexR = payCenterService.payIndex(uid, filter, channelEnum, addWalletReq.bigMoney(addWalletReq.getMoney()));
        log.info("新增账目-发起充值：{}", JSONObject.toJSONString(payIndexR));
        if (!payIndexR.getStatus()) {
            throw new BusinessException(StringUtils.isBlank(payIndexR.getMsg()) ? "充值失败" : payIndexR.getMsg());
        }
        KwpWallet kwpWallet = new KwpWallet();
        kwpWallet.setUid(uid);
        kwpWallet.setFilter(filter);
        kwpWallet.setChannel(channelEnum.getChannel());
        kwpWallet.setAction(WalletActionEnum.CHARGING.getDesc());
        kwpWallet.setActionTime(LocalDateTime.now());
        kwpWallet.setRemark("");
        kwpWallet.setOrderNo(Objects.nonNull(payIndexR.getData()) ? payIndexR.getData().getOrderNo() : "");
        kwpWallet.setStatus(WalletActionEnum.CHARGING.getStatus());
        kwpWalletService.saveOrUpdate(kwpWallet);
        return payIndexR.getData();
    }

    /**
     * 账目充值
     *
     * @return
     */
    public Object addWalletMoney(WalletAppendReq addWalletReq) {
        log.info("账目充值：{}", JSONObject.toJSONString(addWalletReq));
        Long entId1 = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId1);
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("您暂未开通电子钱包");
        }
        String filter = addWalletReq.getFilter();
        ChannelEnum channelEnum = ChannelEnum.getByChannel(addWalletReq.getChannel());
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }
        //发起充值
        R<PayIndex> payIndexR = payCenterService.payIndex(uid, filter, channelEnum, addWalletReq.bigMoney(addWalletReq.getMoney()));
        log.info("账目充值-发起充值：{}", JSONObject.toJSONString(payIndexR));
        if (!payIndexR.getStatus()) {
            throw new BusinessException(StringUtils.isBlank(payIndexR.getMsg()) ? "充值失败" : payIndexR.getMsg());
        }
        KwpWallet kwpWallet = new KwpWallet();
        kwpWallet.setUid(uid);
        kwpWallet.setFilter(filter);
        kwpWallet.setChannel(channelEnum.getChannel());
        kwpWallet.setAction(WalletActionEnum.CHARGING.getDesc());
        kwpWallet.setActionTime(LocalDateTime.now());
        kwpWallet.setRemark("");
        kwpWallet.setOrderNo(Objects.nonNull(payIndexR.getData()) ? payIndexR.getData().getOrderNo() : "");
        kwpWallet.setStatus(WalletActionEnum.CHARGING.getStatus());
        kwpWalletService.saveOrUpdate(kwpWallet);
        return payIndexR.getData();
    }

    /**
     * 提现
     * 重新提现：只针对汇付
     * 1.余额转出
     * 2.申请提现
     *
     * @return
     */
    public Object cashOUt(CashWalletReq cashWalletReq) {
        log.info("提现：{}", JSONObject.toJSONString(cashWalletReq));
        ChannelEnum byChannel = ChannelEnum.getByChannel(cashWalletReq.getChannel());
        if (Objects.isNull(byChannel)) {
            throw new BusinessException("支付通道不存在");
        }
        R<Order> payIndexR = payCenterService.withdrawTransfer(cashWalletReq.getUid(), cashWalletReq.getFilter(), byChannel, cashWalletReq.bigMoney(cashWalletReq.getMoney()));
        if (!payIndexR.getStatus()) {
            throw new BusinessException(StringUtils.isNotBlank(payIndexR.getMsg()) ? payIndexR.getMsg() : "申请提现异常");
        }
        KwpWallet kwpWallet = new KwpWallet();
        kwpWallet.setUid(cashWalletReq.getUid());
        kwpWallet.setFilter(cashWalletReq.getFilter());
        kwpWallet.setChannel(byChannel.getChannel());
        kwpWallet.setAction(WalletActionEnum.CASHING.getDesc());
        kwpWallet.setActionTime(LocalDateTime.now());
        kwpWallet.setRemark("");
        kwpWallet.setOrderNo(Objects.nonNull(payIndexR.getData()) ? payIndexR.getData().getOrderNo() : "");
        kwpWallet.setStatus(WalletActionEnum.CASHING.getStatus());
        kwpWalletService.saveOrUpdate(kwpWallet);
        return payIndexR.getData();
    }

    /**
     * 重新提现
     * 重新提现：只针对汇付
     * 1.余额转出
     * 2.申请提现
     *
     * @return
     */
    public Object reCashOUt(CashWalletReq cashWalletReq) {
        log.info("重新提现：{}", JSONObject.toJSONString(cashWalletReq));
        ChannelEnum byChannel = ChannelEnum.getByChannel(cashWalletReq.getChannel());
        if (Objects.isNull(byChannel)) {
            throw new BusinessException("支付通道不存在");
        }
        //申请提现
        R<Order> orderR = payCenterService.withdrawTake(cashWalletReq.getUid(), byChannel, cashWalletReq.bigMoney(cashWalletReq.getMoney()), cashWalletReq.getRemark());
        log.info("重新提现-申请提现：{}", JSONObject.toJSONString(orderR));
        if (!orderR.getStatus()) {
            throw new BusinessException(StringUtils.isNotBlank(orderR.getMsg()) ? orderR.getMsg() : "申请提现异常");
        }
        return orderR.getData();
    }

    /**
     * 转账
     *
     * @return
     */
    public Object transfer(TransferReq transferReq) {
        log.info("转账：{}", JSONObject.toJSONString(transferReq));
        String key = RedisLockKey.TRANSFER + transferReq.getUid() + ":" + transferReq.getFilter();
        if (redisLockUtil.tryLock(key)) {
            try {
                ChannelEnum channelEnum = ChannelEnum.getByChannel(transferReq.getChannel());
                if (Objects.isNull(channelEnum)) {
                    throw new BusinessException("支付通道不存在");
                }
                String orderNo = OrderUtils.generateOrderNo("TF");
                KwpWalletTransfer walletTransfer = new KwpWalletTransfer();
                walletTransfer.setId(new IdWorker(NumberConstant.ONE).nextId());
                walletTransfer.setOrderNo(orderNo);
                walletTransfer.setUid(transferReq.getUid());
                walletTransfer.setFromEnt(walletRelationService.getEnt(transferReq.getUid()));
                walletTransfer.setFilter(transferReq.getFilter());
                walletTransfer.setToEnt(walletRelationService.getEnt(transferReq.getFilter()));
                walletTransfer.setChannel(transferReq.getChannel());
                walletTransfer.setMoney(transferReq.getMoney());
                walletTransfer.setRemark(transferReq.getRemark());
                walletTransfer.setCreateBy(LoginUserHolder.getUserId());
                walletTransfer.setCreateTime(LocalDateTime.now());
                walletTransfer.setUpdateBy(LoginUserHolder.getUserId());
                walletTransfer.setUpdateTime(LocalDateTime.now());
                walletTransfer.setDelFlag(Global.UN_DELETED);
                //默认已提交
                walletTransfer.setStatus(TransferEnum.APPLY.getStatus());

                List<PatchPay> list = new ArrayList<>();
                PatchPay patchPay = new PatchPay();
                patchPay.setUid(transferReq.getFilter());
                patchPay.setMoney(transferReq.bigMoney(transferReq.getMoney()));
                patchPay.setRemark(transferReq.getRemark());
                list.add(patchPay);
                R<BusinessNo> businessNoR1 = payCenterService.payAgentPayV2(transferReq.getUid(), transferReq.getFilter(), channelEnum, transferReq.bigMoney(transferReq.getMoney()), list, orderNo, "2");
                if (!businessNoR1.getStatus()) {
                    //转账失败
                    walletTransfer.setStatus(TransferEnum.FAILED.getStatus());
                    kwpWalletTransferMapper.insert(walletTransfer);
                    throw new BusinessException(StringUtils.isNotBlank(businessNoR1.getMsg()) ? businessNoR1.getMsg() : "转账失败");
                }
                //转帐中
                walletTransfer.setStatus(TransferEnum.TRANSFERRING.getStatus());
                kwpWalletTransferMapper.insert(walletTransfer);

                KwpWallet kwpWallet = new KwpWallet();
                kwpWallet.setUid(transferReq.getUid());
                kwpWallet.setFilter(transferReq.getFilter());
                kwpWallet.setChannel(channelEnum.getChannel());
                kwpWallet.setAction(WalletActionEnum.TRANSFERRING.getDesc());
                kwpWallet.setActionTime(LocalDateTime.now());
                kwpWallet.setRemark("");
                kwpWallet.setOrderNo(Objects.nonNull(businessNoR1.getData()) ? businessNoR1.getData().getBusinessNo() : "");
                kwpWallet.setStatus(WalletActionEnum.TRANSFERRING.getStatus());
                kwpWalletService.saveOrUpdate(kwpWallet);
                return businessNoR1.getData();
            } finally {
                redisLockUtil.unlock(key);
            }
        }
        return "请勿重复提交!";
    }

    /**
     * 分转元
     *
     * @param big
     * @return
     */
    private BigDecimal smallMoney(BigDecimal big) {
        if (Objects.isNull(big)) {
            return new BigDecimal("0.00");
        }
        return big.divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
    }

    /**
     * 提现记录
     *
     * @return
     */
    public Object cashList(CashPageReq cashPageReq) {
        log.info("提现记录：{}", JSONObject.toJSONString(cashPageReq));
        Long entId = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId);
        if (StringUtils.isBlank(uid)) {
            return PageRes.handPage(cashPageReq.getPage(), cashPageReq.getPageSize(), new ArrayList<>());
        }
        ChannelEnum channelEnum = null;
        if (StringUtils.isNotBlank(cashPageReq.getChannel())) {
            channelEnum = ChannelEnum.getByValue(cashPageReq.getChannel());
            if (Objects.isNull(channelEnum)) {
                throw new BusinessException("支付通道不存在");
            }
        }
        //查询中台接口
        R<CashPage> cashPageR = payCenterService.withdrawIndex(uid, channelEnum, cashPageReq.getStatus(), cashPageReq.getPage(), cashPageReq.getPageSize());
        if (!cashPageR.getStatus()) {
            return new MorePageRes<>(cashPageReq.getPage(), cashPageReq.getPageSize(), 0, 0, new ArrayList<>(), "0.00");
        }
        CashPage data = cashPageR.getData();
        List<CashItem> rows = data.getRows();
        if (!CollectionUtils.isEmpty(rows)) {
            for (CashItem row : rows) {
                row.setBalance(smallMoney(row.getBalance()));
                row.setMoney(smallMoney(row.getMoney()));
            }
        }
        //组装数据
        return new MorePageRes<>(cashPageReq.getPage(), cashPageReq.getPageSize(), data.getTotal(), (int) (data.getTotal() / cashPageReq.getPageSize() + 1), rows, String.valueOf(data.getTotalWithdrawMoney() / 100.0D));
    }

    /**
     * 运营端提现记录
     *
     * @param cashPageReq
     * @return
     */
    public Object cashList2(CashPageReq cashPageReq) {
        log.info("提现记录：{}", JSONObject.toJSONString(cashPageReq));

        List<String> all = walletRelationService.getAll();
        if (CollectionUtils.isEmpty(all)) {
            return PageRes.handPage(cashPageReq.getPage(), cashPageReq.getPageSize(), new ArrayList<>());
        }
        ChannelEnum channelEnum = null;
        if (StringUtils.isNotBlank(cashPageReq.getChannel())) {
            channelEnum = ChannelEnum.getByValue(cashPageReq.getChannel());
            if (Objects.isNull(channelEnum)) {
                throw new BusinessException("支付通道不存在");
            }
        }
        Long sum = 0L;
        List<CashItem> res = new ArrayList<>();
        for (String uid : all) {
            sum += queryAll(res, uid, channelEnum, cashPageReq.getStatus(), cashPageReq.getPage());
        }
        res.sort((c1, c2) -> {
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            if (StringUtils.isBlank(c1.getCreateTime())) {
                return 0;
            }
            if (StringUtils.isBlank(c2.getCreateTime())) {
                return 1;
            }
            LocalDateTime parse = LocalDateTime.parse(c1.getCreateTime(), df);
            LocalDateTime parse2 = LocalDateTime.parse(c2.getCreateTime(), df);
            return parse.compareTo(parse2);
        });
        res.forEach(a -> a.setUidName(getFirmName(a.getUid())));
        //组装数据
        return new MorePageRes<>(cashPageReq.getPage(), cashPageReq.getPageSize(), res, String.valueOf(sum / 100.0D));
    }

    /**
     * 查询一个钱包的所有
     *
     * @param res
     * @param uid
     * @param channelEnum
     * @param status
     * @param page
     * @return
     */
    private Long queryAll(List<CashItem> res, String uid, ChannelEnum channelEnum, String status, int page) {
        long sum = 0L;
        R<CashPage> cashPageR = payCenterService.withdrawIndex(uid, channelEnum, status, page, 10);
        if (cashPageR.getStatus()) {
            CashPage data = cashPageR.getData();
            List<CashItem> rows = data.getRows();
            sum = data.getTotalWithdrawMoney();
            if (!CollectionUtils.isEmpty(rows)) {
                for (CashItem row : rows) {
                    row.setBalance(smallMoney(row.getBalance()));
                    row.setMoney(smallMoney(row.getMoney()));
                }
                res.addAll(rows);
            }

            //计算余量
            long total = data.getTotal();
            long page1 = data.getPage();
            long pageSize1 = data.getPageSize();
            if (page1 * pageSize1 < total) {
                queryAll(res, uid, channelEnum, status, page + 1);
            }
        }
        return sum;
    }

    /**
     * 提现分类页签统计
     *
     * @param cashPageReq
     * @return
     */
    public Object cashCount(CashPageReq cashPageReq) {
        log.info("提现分类页签统计：{}", JSONObject.toJSONString(cashPageReq));
        Long entId = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId);
        if (StringUtils.isBlank(uid)) {
            return null;
        }
        ChannelEnum channelEnum = null;
        if (StringUtils.isNotBlank(cashPageReq.getChannel())) {
            channelEnum = ChannelEnum.getByValue(cashPageReq.getChannel());
            if (Objects.isNull(channelEnum)) {
                throw new BusinessException("支付通道不存在");
            }
        }
        R<List<CashCount>> listR = payCenterService.withdrawCategory(uid, channelEnum);
        if (listR.getStatus()) {
            return listR.getData();
        }
        return new ArrayList<>();
    }

    /**
     * 提现分类页签统计
     *
     * @param cashPageReq
     * @return
     */
    public Object cashCount2(CashPageReq cashPageReq) {
        log.info("运营端提现分类页签统计：{}", JSONObject.toJSONString(cashPageReq));
        List<String> all = walletRelationService.getAll();
        if (CollectionUtils.isEmpty(all)) {
            return null;
        }
        ChannelEnum channelEnum = null;
        if (StringUtils.isNotBlank(cashPageReq.getChannel())) {
            channelEnum = ChannelEnum.getByValue(cashPageReq.getChannel());
            if (Objects.isNull(channelEnum)) {
                throw new BusinessException("支付通道不存在");
            }
        }
        List<CashCount> res = new ArrayList<>();
        List<CashCount> total = new ArrayList<>();
        for (String uid : all) {
            R<List<CashCount>> listR = payCenterService.withdrawCategory(uid, channelEnum);
            if (listR.getStatus()) {
                List<CashCount> data = listR.getData();
                if (!CollectionUtils.isEmpty(data)) {
                    total.addAll(data);
                }
            }
        }
        Map<String, List<CashCount>> collect = total.stream().collect(Collectors.groupingBy(CashCount::getValue, Collectors.toList()));
        for (Map.Entry<String, List<CashCount>> map : collect.entrySet()) {
            Map<String, Long> map1 = collect.get(map.getKey()).stream().collect(Collectors.groupingBy(CashCount::getName, Collectors.summingLong(CashCount::getTotal)));
            for (Map.Entry<String, Long> one : map1.entrySet()) {
                CashCount cashCount = new CashCount();
                cashCount.setName(one.getKey());
                cashCount.setValue(map.getKey());
                cashCount.setTotal(one.getValue());
                res.add(cashCount);
            }
        }
        return res;
    }

    /**
     * 预付记录
     *
     * @return
     */
    public Object prePayList(PrePayPage prePayPage) {
        Long entId = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId);
        if (StringUtils.isBlank(uid)) {
            return new ApPageRes<>(prePayPage.getPage(), prePayPage.getPageSize(), 0, 0, new ArrayList<>());
        }
        ChannelEnum channelEnum = null;
        if (StringUtils.isNotBlank(prePayPage.getChannel())) {
            channelEnum = ChannelEnum.getByValue(prePayPage.getChannel());
            if (Objects.isNull(channelEnum)) {
                throw new BusinessException("支付通道异常");
            }
        }
        String entName = prePayPage.getEntName();
        String filter = "";
        //筛选企业名称
        if (StringUtils.isNotBlank(entName)) {
            filter = findFilterStr(entName);
        }
        // 查询预付数据
        R<PrePayWalletPage> prePayIndexPageR = payCenterService.advancePayWALLET(uid, channelEnum, filter, prePayPage.getPage(), prePayPage.getPageSize());
        if (prePayIndexPageR.getStatus()) {
            PrePayWalletPage data = prePayIndexPageR.getData();
            //数据转换
            List<PrePayWalletVo> list = new ArrayList<>();
            if (!CollectionUtils.isEmpty(data.getRows())) {
                PrePayWalletVo prePayWalletVo;
                for (PrePayWallet row : data.getRows()) {
                    prePayWalletVo = new PrePayWalletVo();
                    BeanUtils.copyProperties(row, prePayWalletVo);
                    ChannelEnum byChannel = ChannelEnum.getByChannel(row.getChannel());
                    prePayWalletVo.setChannelDict(Objects.nonNull(byChannel) ? byChannel.getValue() : "");
                    prePayWalletVo.setApMoney(dfMoney(row.getApMoney()));
                    prePayWalletVo.setUidName(getFirmName(row.getUid()));
                    prePayWalletVo.setUidEnt(getEnt(row.getUid()));
                    prePayWalletVo.setFilterName(getFirmName(row.getFilter()));
                    prePayWalletVo.setFilterEnt(getEnt(row.getFilter()));
                    prePayWalletVo.setUsingApMoney(dfMoney(row.getUsingApMoney()));
                    prePayWalletVo.setSettlingApMoney(dfMoney(row.getSettlingApMoney()));
                    prePayWalletVo.setTotalApMoney(dfMoney(row.getTotalApMoney()));
                    refundMoney(row, prePayWalletVo, false);
                    time(prePayWalletVo);
                    list.add(prePayWalletVo);
                }
            }
            ApPageRes<PrePayWalletVo> page = new ApPageRes<>(prePayPage.getPage(), prePayPage.getPageSize(), data.getTotal(), (int) (data.getTotal() / prePayPage.getPageSize() + 1), list);
            page.setApMoney(dfMoney(data.getApMoney()));
            page.setUsingApMoney(dfMoney(data.getUsingApMoney()));
            page.setTotalApMoney(dfMoney(data.getTotalApMoney()));
            return page;
        }
        return new ApPageRes<>(prePayPage.getPage(), prePayPage.getPageSize(), 0, 0, new ArrayList<>());

    }

    /**
     * 运营端预付列表
     *
     * @param prePayPage
     * @return
     */
    public Object prePayList2(PrePayPage prePayPage) {
        List<String> all = walletRelationService.getAll();
        if (CollectionUtils.isEmpty(all)) {
            return new ApPageRes<>(prePayPage.getPage(), prePayPage.getPageSize(), 0, 0, new ArrayList<>());
        }
        ChannelEnum channelEnum = null;
        if (StringUtils.isNotBlank(prePayPage.getChannel())) {
            channelEnum = ChannelEnum.getByValue(prePayPage.getChannel());
            if (Objects.isNull(channelEnum)) {
                throw new BusinessException("支付通道异常");
            }
        }
        String entName = prePayPage.getEntName();
        String filter = "";
        //筛选企业名称
        if (StringUtils.isNotBlank(entName)) {
            filter = findFilterStr(entName);
        }
        List<PrePayWalletVo> list = new ArrayList<>();
        long apSum = 0L;
        long usingApSum = 0L;
        long totalApSum = 0L;
        for (String uid : all) {
            Map<String, Long> map = queryAdvance(list, uid, channelEnum, filter, prePayPage.getPage());
            apSum += map.get("apSum");
            usingApSum += map.get("usingApSum");
            totalApSum += map.get("totalApSum");
        }
        list.forEach(this::time);
        ApPageRes<PrePayWalletVo> page = new ApPageRes<>(prePayPage.getPage(), prePayPage.getPageSize(), list);
        page.setApMoney(dfMoney(apSum));
        page.setUsingApMoney(dfMoney(usingApSum));
        page.setTotalApMoney(dfMoney(totalApSum));
        return page;

    }

    private Map<String, Long> queryAdvance(List<PrePayWalletVo> list, String uid, ChannelEnum channelEnum, String filter, int page) {
        long apSum = 0L;
        long usingApSum = 0L;
        long totalApSum = 0L;
        R<PrePayWalletPage> prePayIndexPageR = payCenterService.advancePayWALLET(uid, channelEnum, filter, page, 10);
        if (prePayIndexPageR.getStatus()) {
            PrePayWalletPage data = prePayIndexPageR.getData();
            //数据转换
            if (!CollectionUtils.isEmpty(data.getRows())) {
                apSum = data.getApMoney();
                usingApSum = data.getUsingApMoney();
                totalApSum = data.getTotalApMoney();
                PrePayWalletVo prePayWalletVo;
                for (PrePayWallet row : data.getRows()) {
                    prePayWalletVo = new PrePayWalletVo();
                    BeanUtils.copyProperties(row, prePayWalletVo);
                    ChannelEnum byChannel = ChannelEnum.getByChannel(row.getChannel());
                    prePayWalletVo.setChannelDict(Objects.nonNull(byChannel) ? byChannel.getValue() : "");
                    prePayWalletVo.setApMoney(dfMoney(row.getApMoney()));
                    prePayWalletVo.setUidName(getFirmName(row.getUid()));
                    prePayWalletVo.setUidEnt(getEnt(row.getUid()));
                    prePayWalletVo.setFilterName(getFirmName(row.getFilter()));
                    prePayWalletVo.setFilterEnt(getEnt(row.getFilter()));
                    prePayWalletVo.setUsingApMoney(dfMoney(row.getUsingApMoney()));
                    prePayWalletVo.setSettlingApMoney(dfMoney(row.getSettlingApMoney()));
                    prePayWalletVo.setTotalApMoney(dfMoney(row.getTotalApMoney()));
                    refundMoney(row, prePayWalletVo, false);
                    list.add(prePayWalletVo);
                }

                //计算余量
                long total = data.getTotal();
                long page1 = data.getPage();
                long pageSize1 = data.getPageSize();
                if (page1 * pageSize1 < total) {
                    queryAdvance(list, uid, channelEnum, filter, page + 1);
                }
            }
        }
        Long finalApSum = apSum;
        Long finalUsingApSum = usingApSum;
        Long finalTotalApSum = totalApSum;
        return new HashMap<>() {{
            put("apSum", finalApSum);
            put("usingApSum", finalUsingApSum);
            put("totalApSum", finalTotalApSum);
        }};
    }

    /**
     * 预付列表钱包统计
     *
     * @param entName
     * @return
     */
    public List<ChannelCount> prePayCount(String entName) {
        Long entId = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId);
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("暂未开通电子钱包");
        }
        List<String> filterList = new ArrayList<>();
        //筛选指定企业的数据
        if (StringUtils.isNotBlank(entName)) {
            filterList = findFilter(entName);
        }
        List<ChannelCount> channelDetails = new ArrayList<>();
        //查询预付订单渠道统计数据
        R<List<ChannelStatistics>> listR = payCenterService.advancePayWalletChannels(uid, StringUtils.join(filterList, ","));
        Map<String, Integer> mapCount;
        if (listR.getStatus()) {
            List<ChannelStatistics> data = listR.getData();
            if (!CollectionUtils.isEmpty(data)) {
                mapCount = data.stream().collect(Collectors.toMap(ChannelStatistics::getChannel, ChannelStatistics::getCount, (k, v) -> k));
            } else {
                mapCount = new HashMap<>();
            }
            mapCount.compute("all", (k, v) -> {
                Integer sum = 0;
                for (Map.Entry<String, Integer> map : mapCount.entrySet()) {
                    sum += map.getValue();
                }
                return sum;
            });
        } else {
            mapCount = new HashMap<>();
        }
        ChannelCount channelCount;
        for (WalletChannelEnum value : WalletChannelEnum.values()) {
            Integer integer = mapCount.get(value.getChannel());
            channelCount = new ChannelCount(value.getValue(), value.getDesc(), value.getChannel(), Objects.isNull(integer) ? 0 : integer);
            channelDetails.add(channelCount);
        }
        return channelDetails;
    }

    /**
     * 预收列表
     *
     * @param prePayPage
     * @return
     */
    public Object preReceiveList(PrePayPage prePayPage) {
        Long entId = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId);
        if (StringUtils.isBlank(uid)) {
            return null;
        }
        ChannelEnum channelEnum = null;
        if (StringUtils.isNotBlank(prePayPage.getChannel())) {
            channelEnum = ChannelEnum.getByValue(prePayPage.getChannel());
            if (Objects.isNull(channelEnum)) {
                throw new BusinessException("支付通道异常");
            }
        }
        String entName = prePayPage.getEntName();
        String filter = "";
        //筛选企业名称
        if (StringUtils.isNotBlank(entName)) {
            filter = findFilterStr(entName);
        }
        // 预收列表
        R<PrePayWalletPage> prePayIndexPageR = payCenterService.advancePayReceive(uid, channelEnum, filter, prePayPage.getPage(), prePayPage.getPageSize());
        if (prePayIndexPageR.getStatus()) {
            PrePayWalletPage data = prePayIndexPageR.getData();
            //数据转换
            List<PrePayWalletVo> list = new ArrayList<>();
            if (!CollectionUtils.isEmpty(data.getRows())) {
                PrePayWalletVo prePayWalletVo;
                for (PrePayWallet row : data.getRows()) {
                    prePayWalletVo = new PrePayWalletVo();
                    BeanUtils.copyProperties(row, prePayWalletVo);
                    ChannelEnum byChannel = ChannelEnum.getByChannel(row.getChannel());
                    prePayWalletVo.setChannelDict(Objects.nonNull(byChannel) ? byChannel.getValue() : "");
                    prePayWalletVo.setApMoney(dfMoney(row.getApMoney()));
                    prePayWalletVo.setUidName(getFirmName(row.getUid()));
                    prePayWalletVo.setUidEnt(getEnt(row.getUid()));
                    prePayWalletVo.setFilterName(getFirmName(row.getFilter()));
                    prePayWalletVo.setFilterEnt(getEnt(row.getFilter()));
                    prePayWalletVo.setUsingApMoney(dfMoney(row.getUsingApMoney()));
                    prePayWalletVo.setSettlingApMoney(dfMoney(row.getSettlingApMoney()));
                    prePayWalletVo.setTotalApMoney(dfMoney(row.getTotalApMoney()));
                    refundMoney(row, prePayWalletVo, true);
                    timeReceive(prePayWalletVo);
                    list.add(prePayWalletVo);
                }
            }
            ApPageRes<PrePayWalletVo> page = new ApPageRes<>(prePayPage.getPage(), prePayPage.getPageSize(), data.getTotal(), (int) (data.getTotal() / prePayPage.getPageSize() + 1), list);
            page.setApMoney(dfMoney(data.getApMoney()));
            page.setUsingApMoney(dfMoney(data.getUsingApMoney()));
            page.setTotalApMoney(dfMoney(data.getTotalApMoney()));
            return page;
        }
        return new PageRes<>(prePayPage.getPage(), prePayPage.getPageSize(), 0, 0, new ArrayList<>());
    }

    /**
     * 预收列表钱包统计
     *
     * @param entName
     * @return
     */
    public List<ChannelCount> preReceiveCount(String entName) {
        Long entId = LoginUserHolder.getEntId();
        String uid = walletRelationService.getRelation(entId);
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("暂未开通电子钱包");
        }
        List<String> filterList = new ArrayList<>();
        //筛选指定企业的数据
        if (StringUtils.isNotBlank(entName)) {
            filterList = findFilter(entName);
        }
        List<ChannelCount> channelDetails = new ArrayList<>();
        //查询预付订单渠道统计数据
        R<List<ChannelStatistics>> listR = payCenterService.advancePayReceiveChannels(uid, StringUtils.join(filterList, ","));
        Map<String, Integer> mapCount;
        if (listR.getStatus()) {
            List<ChannelStatistics> data = listR.getData();
            if (!CollectionUtils.isEmpty(data)) {
                mapCount = data.stream().collect(Collectors.toMap(ChannelStatistics::getChannel, ChannelStatistics::getCount, (k, v) -> k));
            } else {
                mapCount = new HashMap<>();
            }
            mapCount.compute("all", (k, v) -> {
                Integer sum = 0;
                for (Map.Entry<String, Integer> map : mapCount.entrySet()) {
                    sum += map.getValue();
                }
                return sum;
            });
        } else {
            mapCount = new HashMap<>();
        }
        ChannelCount channelCount;
        for (WalletChannelEnum value : WalletChannelEnum.values()) {
            Integer integer = mapCount.get(value.getChannel());
            channelCount = new ChannelCount(value.getValue(), value.getDesc(), value.getChannel(), Objects.isNull(integer) ? 0 : integer);
            channelDetails.add(channelCount);
        }
        return channelDetails;
    }

    /**
     * 预付校验
     *
     * @param prePayCheck
     * @return
     */
    public Object prePayCheck(PrePayCheck prePayCheck) {
        String uid = walletRelationService.getRelation(LoginUserHolder.getEntId());
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("您暂未开通电子钱包");
        }
        //字典
        ChannelEnum channelEnum = ChannelEnum.getByValue(prePayCheck.getChannel());
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }
        String filter = walletRelationService.getRelation(Long.parseLong(prePayCheck.getEntId()));
        if (StringUtils.isBlank(filter)) {
            throw new BusinessException("合作企业暂未开通电子钱包");
        }
        R<WalletInfo> walletInfoR = payCenterService.totalInfo(uid, channelEnum, filter);
        if (!walletInfoR.getStatus()) {
            throw new BusinessException(StringUtils.isNotBlank(walletInfoR.getMsg()) ? walletInfoR.getMsg() : "未找到交易方");
        }
        WalletInfo data = walletInfoR.getData();
        if (Objects.isNull(data)) {
            throw new BusinessException("不存在交易");
        }
        WalletInfoDto walletInfoDto = new WalletInfoDto();
        walletInfoDto.setChannel(data.getChannel());
        walletInfoDto.setApMoney(walletInfoDto.smallMoney(data.getApMoney()));
        walletInfoDto.setWdMoney(walletInfoDto.smallMoney(data.getWdMoney()));
        walletInfoDto.setMoney(walletInfoDto.smallMoney(data.getMoney()));
        return walletInfoDto;
    }

    /**
     * 新增预付
     *
     * @return
     */
    public Object addPrePay(PrePay prePay) {
        String uid = walletRelationService.getRelation(LoginUserHolder.getEntId());
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("您暂未开通电子钱包");
        }
        //字典
        ChannelEnum channelEnum = ChannelEnum.getByValue(prePay.getChannel());
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }

        String filter = walletRelationService.getRelation(Long.parseLong(prePay.getEntId()));
        if (StringUtils.isBlank(filter)) {
            throw new BusinessException("合作企业开通电子钱包");
        }
        R<Order> orderR = payCenterService.advancePayApply(uid, channelEnum, filter, prePay.bigMoney(prePay.getMoney()));
        if (!orderR.getStatus()) {
            throw new BusinessException(StringUtils.isNotBlank(orderR.getMsg()) ? orderR.getMsg() : "预付失败");
        }
        if (Objects.nonNull(orderR.getData())) {
            kwpWalletPrepayService.savePrepay(orderR.getData().getOrderNo(), PrePayEnum.ADD);
        }
        kwpWalletService.saveTime(uid, filter, channelEnum.getChannel());
        return orderR.getData();
    }

    /**
     * 预付追加
     *
     * @return
     */
    public Object prePayAppend(PrePayAppend prePay) {
        String uid = walletRelationService.getRelation(LoginUserHolder.getEntId());
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("您暂未开通电子钱包");
        }
        ChannelEnum channelEnum = ChannelEnum.getByValue(prePay.getChannel());
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }

        R<Order> orderR = payCenterService.advancePayApply(prePay.getUid(), channelEnum, prePay.getFilter(), prePay.bigMoney(prePay.getMoney()));
        if (!orderR.getStatus()) {
            throw new BusinessException(StringUtils.isNotBlank(orderR.getMsg()) ? orderR.getMsg() : "预付失败");
        }
        if (Objects.nonNull(orderR.getData())) {
            kwpWalletPrepayService.savePrepay(orderR.getData().getOrderNo(), PrePayEnum.APPEND);
        }
        kwpWalletService.saveTime(uid, prePay.getFilter(), channelEnum.getChannel());
        return orderR.getData();
    }

    /**
     * 申请退款
     * 校验预付可用余额和退款金额，退款金额不能大于预付可用余额
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Object applyRefund(ApplyRefundReq refundReq) {
        ChannelEnum channelEnum = ChannelEnum.getByChannel(refundReq.getChannel());
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }
        //校验余额
        R<WalletInfo> walletInfoR = payCenterService.totalInfo(refundReq.getUid(), channelEnum, refundReq.getFilter());
        if (!walletInfoR.getStatus()) {
            throw new BusinessException(StringUtils.isNotBlank(walletInfoR.getMsg()) ? walletInfoR.getMsg() : "未找到交易方");
        }
        WalletInfo data = walletInfoR.getData();
        if (Objects.isNull(data)) {
            throw new BusinessException("不存在交易");
        }
        //预付可用余额 分
        BigDecimal apMoney = data.getApMoney();
        apMoney = Objects.isNull(apMoney) ? BigDecimal.ZERO : apMoney;
        //退款金额 元
        BigDecimal money = refundReq.getMoney();
        //退款金额 分
        BigDecimal multiply = money.multiply(new BigDecimal("100"));
        if (multiply.compareTo(apMoney) > 0) {
            throw new BusinessException("退款金额不能大于预付可用金额");
        }

        //新增退款单
        KwpWalletRefund kwpWalletRefundAdd = new KwpWalletRefund();
        kwpWalletRefundAdd.setId(new IdWorker(NumberConstant.ONE).nextId());
        kwpWalletRefundAdd.setOrderNo(OrderUtils.generateOrderNo("RF"));
        kwpWalletRefundAdd.setUid(refundReq.getUid());
        kwpWalletRefundAdd.setFromEnt(walletRelationService.getEnt(refundReq.getUid()));
        kwpWalletRefundAdd.setFilter(refundReq.getFilter());
        kwpWalletRefundAdd.setToEnt(walletRelationService.getEnt(refundReq.getFilter()));
        kwpWalletRefundAdd.setChannel(refundReq.getChannel());
        kwpWalletRefundAdd.setMoney(refundReq.getMoney());
        kwpWalletRefundAdd.setActualMoney(new BigDecimal("0.0"));
        kwpWalletRefundAdd.setRemark(refundReq.getRemark());
        kwpWalletRefundAdd.setCreateBy(LoginUserHolder.getUserId());
        kwpWalletRefundAdd.setCreateTime(LocalDateTime.now());
        kwpWalletRefundAdd.setUpdateBy(LoginUserHolder.getUserId());
        kwpWalletRefundAdd.setUpdateTime(LocalDateTime.now());
        kwpWalletRefundAdd.setDelFlag(0);
        kwpWalletRefundAdd.setStatus(RefundEnum.APPLY.getStatus());
        kwpWalletRefundMapper.insert(kwpWalletRefundAdd);
        kwpWalletRefundSubService.saveRecord(kwpWalletRefundAdd.getId(), refundReq.getRemark(), RefundEnum.APPLY.getStatus());
        return "提交成功";
    }

    /**
     * 发起退款
     * 中台逻辑：
     * 预付 A->B 100元
     * 退款50元，调用2次清分。
     * 1. 清分 A->B 50元
     * 2. 清分 B->A 50元
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Object launchRefund(RefundReq refundReq) {
        KwpWalletRefund kwpWalletRefund = walletOrderService.queryById(refundReq.getIdLong());
        if (Objects.isNull(kwpWalletRefund)) {
            throw new BusinessException("退款订单不存在");
        }
        String key = RedisLockKey.REFUND + refundReq.getIdLong();
        if (redisLockUtil.tryLock(key)) {
            try {
                if (kwpWalletRefund.getStatus() != RefundEnum.APPLY.getStatus()) {
                    throw new BusinessException("当前退款单已提交退款申请");
                }
                ChannelEnum channelEnum = ChannelEnum.getByChannel(kwpWalletRefund.getChannel());
                if (Objects.isNull(channelEnum)) {
                    throw new BusinessException("支付通道不存在");
                }
                // 1.记账
                List<PatchPay> list = new ArrayList<>();
                PatchPay patchPay = new PatchPay();
                patchPay.setUid(kwpWalletRefund.getFilter());
                patchPay.setMoney(refundReq.bigMoney(refundReq.getMoney()));
                patchPay.setRemark(StringUtils.isBlank(refundReq.getRemark()) ? "" : refundReq.getRemark());
                list.add(patchPay);
                R<BusinessNo> businessNoR = payCenterService.payAgentPayV2(kwpWalletRefund.getUid(), kwpWalletRefund.getFilter(), channelEnum, refundReq.bigMoney(refundReq.getMoney()), list, OrderUtils.generateOrderNo("SEQ"), "1");
                if (!businessNoR.getStatus()) {
                    throw new BusinessException(StringUtils.isNotBlank(businessNoR.getMsg()) ? businessNoR.getMsg() : "退款失败");
                }
                //保存操作记录
                kwpWalletRefundSubService.saveRecord(kwpWalletRefund.getId(), refundReq.getRemark(), RefundEnum.REFUNDING.getStatus());

                Long userId = LoginUserHolder.getUserId();
                //异步提交清分退款任务
                AsyncPool.addTask(new Refund(refundReq, kwpWalletRefund, payCenterService, kwpWalletRefundMapper, userId));
                //记录操作时间
                kwpWalletService.saveTime(kwpWalletRefund.getUid(), kwpWalletRefund.getFilter(), channelEnum.getChannel());
                return businessNoR;
            } finally {
                redisLockUtil.unlock(key);
            }
        }
        throw new BusinessException("请勿重复提交退款操作");
    }

    /**
     * 发起退款校验
     *
     * @param id
     * @return
     */
    public WalletInfoDto refundCheck(Long id) {
        KwpWalletRefund kwpWalletRefund = walletOrderService.queryById(id);
        if (Objects.isNull(kwpWalletRefund)) {
            throw new BusinessException("退款订单不存在");
        }
        ChannelEnum channelEnum = ChannelEnum.getByChannel(kwpWalletRefund.getChannel());
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }
        //发起退款是预收业务，uid和filter是相反的，查询时需要方向查询钱包
        R<WalletInfo> walletInfoR = payCenterService.totalInfo(kwpWalletRefund.getFilter(), channelEnum, kwpWalletRefund.getUid());
        // 未开通钱包
        if (!walletInfoR.getStatus()) {
            WalletInfoDto walletInfoDto = new WalletInfoDto();
            walletInfoDto.setOpenFlag(false);
            return walletInfoDto;
        }
        WalletInfo data = walletInfoR.getData();
        if (Objects.isNull(data)) {
            WalletInfoDto walletInfoDto = new WalletInfoDto();
            walletInfoDto.setOpenFlag(false);
            return walletInfoDto;
        }
        WalletInfoDto walletInfoDto = new WalletInfoDto();
        walletInfoDto.setOpenFlag(true);
        walletInfoDto.setChannel(data.getChannel());
        walletInfoDto.setApMoney(walletInfoDto.smallMoney(data.getApMoney()));
        walletInfoDto.setWdMoney(walletInfoDto.smallMoney(data.getWdMoney()));
        walletInfoDto.setMoney(walletInfoDto.smallMoney(data.getMoney()));
        //申请退款金额
        walletInfoDto.setRefundMoney(kwpWalletRefund.getMoney());

        walletInfoDto.setChannelLabel(channelEnum.getDesc());
        walletInfoDto.setUid(kwpWalletRefund.getUid());
        walletInfoDto.setUidName(getFirmName(kwpWalletRefund.getUid()));
        walletInfoDto.setFilter(kwpWalletRefund.getFilter());
        walletInfoDto.setFilterName(getFirmName(kwpWalletRefund.getFilter()));
        return walletInfoDto;
    }

    /**
     * 预付追加校验
     *
     * @param appendPayCheck
     * @return
     */
    public Object appendCheck(AppendPayCheck appendPayCheck) {
        String uid = walletRelationService.getRelation(LoginUserHolder.getEntId());
        if (StringUtils.isBlank(uid)) {
            throw new BusinessException("您暂未开通电子钱包");
        }
        //字典
        ChannelEnum channelEnum = ChannelEnum.getByChannel(appendPayCheck.getChannel());
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }
        R<WalletInfo> walletInfoR = payCenterService.totalInfo(uid, channelEnum, appendPayCheck.getFilter());
        if (!walletInfoR.getStatus()) {
            throw new BusinessException(StringUtils.isNotBlank(walletInfoR.getMsg()) ? walletInfoR.getMsg() : "未找到交易方");
        }
        WalletInfo data = walletInfoR.getData();
        if (Objects.isNull(data)) {
            throw new BusinessException("不存在交易");
        }
        WalletInfoDto walletInfoDto = new WalletInfoDto();
        walletInfoDto.setOpenFlag(true);
        walletInfoDto.setChannel(data.getChannel());
        walletInfoDto.setApMoney(walletInfoDto.smallMoney(data.getApMoney()));
        walletInfoDto.setWdMoney(walletInfoDto.smallMoney(data.getWdMoney()));
        walletInfoDto.setMoney(walletInfoDto.smallMoney(data.getMoney()));
        return walletInfoDto;
    }

    /**
     * 渠道开通
     *
     * @param createUserReq
     * @return
     */
    public Object createUser(CreateUserReq createUserReq) {
        Long entId = LoginUserHolder.getEntId();
        ChannelEnum channelEnum = ChannelEnum.getByChannel(createUserReq.getChannel());
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }
        EntCacheResDto entCacheResDto = remoteSystemService.queryEntCacheById(entId);
        if (Objects.isNull(entCacheResDto)) {
            throw new BusinessException("未找到企业信息");
        }
        MemberCreate memberCreate = new MemberCreate();
        List<EntCertificateResDto> certificateInfo = entCacheResDto.getCertificateInfo();
        Map<Integer, String> certMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(certificateInfo)) {
            certMap = certificateInfo.stream().collect(Collectors.toMap(EntCertificateResDto::getType, EntCertificateResDto::getCode, (a, b) -> a));
        }
        memberCreate.setCompanyName(entCacheResDto.getFirmName());
        memberCreate.setLicense(certMap.get(3));
        memberCreate.setLegalName(entCacheResDto.getLegalName());
        memberCreate.setLegalPhone(entCacheResDto.getLegalPhone());
        //法人身份证号
        memberCreate.setLegalIds(certMap.get(2));
        memberCreate.setAccountNo("");
        memberCreate.setParentBankName("");
        memberCreate.setUnionBank("");
        memberCreate.setBankName("");
        memberCreate.setChannel(createUserReq.getChannel());
        //开通用户
        R<MemberRes> memberResR = payCenterService.memberIndex(memberCreate);
        if (!memberResR.getStatus()) {
            throw new BusinessException(StringUtils.isNotBlank(memberResR.getMsg()) ? memberResR.getMsg() : "开户失败");
        }
        MemberRes data = memberResR.getData();
        WalletRelationDto walletRelationDto = new WalletRelationDto(entId, data.getUid());
        KwpWalletRelation query = walletRelationService.query(walletRelationDto);
        if (Objects.isNull(query)) {
            walletRelationService.save(walletRelationDto);
        }
        return data;
    }

    /**
     * 驳回退款
     *
     * @param refundReq
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String backRefund(RefundBackReq refundReq) {
        KwpWalletRefund kwpWalletRefund = walletOrderService.queryById(refundReq.getIdLong());
        if (Objects.isNull(kwpWalletRefund)) {
            throw new BusinessException("退款订单不存在");
        }
        if (kwpWalletRefund.getStatus() != RefundEnum.APPLY.getStatus()) {
            throw new BusinessException("请勿重复提交");
        }
        kwpWalletRefund.setStatus(RefundEnum.BACK.getStatus());
        kwpWalletRefund.setRemark(refundReq.getRemark());
        kwpWalletRefund.setUpdateBy(LoginUserHolder.getUserId());
        kwpWalletRefund.setUpdateTime(LocalDateTime.now());
        walletOrderService.updateById(kwpWalletRefund);
        //保存操作记录
        kwpWalletRefundSubService.saveRecord(kwpWalletRefund.getId(), refundReq.getRemark(), RefundEnum.BACK.getStatus());
        return "驳回成功";
    }

    /**
     * 查询退款列表
     *
     * @param refundPage
     * @return
     */
    public Object refundList(RefundPage refundPage) {
        if (StringUtils.isNotBlank(refundPage.getStartCreateTime())) {
            refundPage.setStartCreateTime(StringTimeUtil.fillStart(refundPage.getStartCreateTime()));
        }
        if (StringUtils.isNotBlank(refundPage.getEndCreateTime())) {
            refundPage.setEndCreateTime(StringTimeUtil.fillEnd(refundPage.getEndCreateTime()));
        }
        String uid = refundPage.getUid();
        String filter = refundPage.getFilter();
        refundPage.setUid(filter);
        refundPage.setFilter(uid);
        PageRes<WalletRefundVo> walletRefundVoPageRes = walletOrderService.queryRefundList(refundPage);
        List<WalletRefundVo> list = walletRefundVoPageRes.getList();
        for (WalletRefundVo walletRefundVo : list) {
            walletRefundVo.setUidName(getFirmName(walletRefundVo.getUid()));
            walletRefundVo.setFilterName(getFirmName(walletRefundVo.getFilter()));
            walletRefundVo.setChannelLabel(ChannelEnum.getDesc(walletRefundVo.getChannel()));
            walletRefundVo.setChannelDict(ChannelEnum.getDict(walletRefundVo.getChannel()));
        }
        return walletRefundVoPageRes;
    }

    /**
     * 资金明细-充值订单列表
     *
     * @param moneyPage
     * @return
     */
    public PageRes<ChargeDetailVo> rechargeList(MoneyPage moneyPage) {
        R<RechargePage> rechargePageR = payCenterService.rechargeOrder(moneyPage.getUid(), moneyPage.getFilter(), ChannelEnum.getByChannel(moneyPage.getChannel()), moneyPage.getStartCreateTime(), moneyPage.getEndCreateTime(), moneyPage.getKeywords(), moneyPage.getPage(), moneyPage.getPageSize());
        if (!rechargePageR.getStatus()) {
            throw new BusinessException(StringUtils.isBlank(rechargePageR.getMsg()) ? "查询失败" : rechargePageR.getMsg());
        }
        RechargePage data = rechargePageR.getData();
        List<Recharge> rows = data.getRows();
        if (!CollectionUtils.isEmpty(rows)) {
            List<ChargeDetailVo> collect = rows.stream().map(a -> {
                ChargeDetailVo chargeDetailVo = new ChargeDetailVo();
                chargeDetailVo.setOrderNo(a.getOrderNo());
                chargeDetailVo.setChannel(a.getChannel());
                chargeDetailVo.setChannelDict(ChannelEnum.getDict(a.getChannel()));
                chargeDetailVo.setChannelLabel(ChannelEnum.getDesc(a.getChannel()));
                chargeDetailVo.setUid(a.getUid());
                chargeDetailVo.setUidName(getFirmName(a.getUid()));
                chargeDetailVo.setFilter(a.getFilter());
                chargeDetailVo.setFilterName(getFirmName(a.getFilter()));
                chargeDetailVo.setStatus(a.getStatus());
                chargeDetailVo.setStatusLabel(a.getStatusLabel());
                chargeDetailVo.setMoney(chargeDetailVo.smallMoney(a.getMoney()));
                chargeDetailVo.setBalance(chargeDetailVo.smallMoney(a.getAfterMoney()));
                chargeDetailVo.setRemark(a.getRemarks());
                chargeDetailVo.setCreateTime(a.getCreateTime());
                chargeDetailVo.setPayTime(a.getPayTime());
                return chargeDetailVo;
            }).collect(Collectors.toList());
            return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), data.getTotal(), (int) (data.getTotal() / data.getPageSize() + 1), collect);
        }
        return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), 0, 0, new ArrayList<>());
    }

    /**
     * 资金明细-转账订单
     *
     * @param moneyPage
     * @return
     */
    public PageRes<WalletDetailBase> transferOrder(MoneyPage moneyPage) {
        PageHelper.startPage(moneyPage.getPage(), moneyPage.getPageSize());
        List<KwpWalletTransfer> kwpWalletTransfers = kwpWalletTransferMapper.pageList(moneyPage);
        PageInfo<KwpWalletTransfer> pageInfo = new PageInfo<>(kwpWalletTransfers);
        ArrayList<WalletDetailBase> res = new ArrayList<>();
        WalletDetailBase walletDetailBase;

        for (KwpWalletTransfer kwpWalletTransfer : kwpWalletTransfers) {
            walletDetailBase = new WalletDetailBase();
            walletDetailBase.setOrderNo(kwpWalletTransfer.getOrderNo());
            walletDetailBase.setChannel(kwpWalletTransfer.getChannel());
            walletDetailBase.setChannelDict(ChannelEnum.getDict(kwpWalletTransfer.getChannel()));
            walletDetailBase.setChannelLabel(ChannelEnum.getDesc(kwpWalletTransfer.getChannel()));
            walletDetailBase.setUid(kwpWalletTransfer.getUid());
            walletDetailBase.setUidName(getFirmName(kwpWalletTransfer.getUid()));
            walletDetailBase.setFilter(kwpWalletTransfer.getFilter());
            walletDetailBase.setFilterName(getFirmName(kwpWalletTransfer.getFilter()));
            walletDetailBase.setStatus(kwpWalletTransfer.getStatus());
            walletDetailBase.setStatusLabel(TransferEnum.getDesc(kwpWalletTransfer.getStatus()));
            walletDetailBase.setMoney(kwpWalletTransfer.getMoney());
            walletDetailBase.setRemark(kwpWalletTransfer.getRemark());
            walletDetailBase.setCreateTime(DateTimeUtil.format(kwpWalletTransfer.getCreateTime()));
            res.add(walletDetailBase);
        }
        return PageRes.build(pageInfo, res);
    }

    /**
     * 资金明细-退款订单
     *
     * @param moneyPage
     * @return
     */
    public PageRes<WalletDetailBase> refundOrder(MoneyPage moneyPage) {
        RefundPage refundPage = new RefundPage();
        BeanUtils.copyProperties(moneyPage, refundPage);
        PageRes<WalletRefundVo> walletRefundVoPageRes = walletOrderService.queryRefundList(refundPage);
        List<WalletRefundVo> list = walletRefundVoPageRes.getList();
        List<WalletDetailBase> res = new ArrayList<>();
        WalletDetailBase walletDetailBase;
        for (WalletRefundVo walletRefundVo : list) {
            walletDetailBase = new WalletDetailBase();
            walletDetailBase.setOrderNo(walletRefundVo.getOrderNo());
            walletDetailBase.setChannel(walletRefundVo.getChannel());
            walletDetailBase.setChannelDict(ChannelEnum.getDict(walletRefundVo.getChannel()));
            walletDetailBase.setChannelLabel(ChannelEnum.getDesc(walletRefundVo.getChannel()));
            walletDetailBase.setUid(walletRefundVo.getUid());
            walletDetailBase.setUidName(getFirmName(walletRefundVo.getUid()));
            walletDetailBase.setFilter(walletRefundVo.getFilter());
            walletDetailBase.setFilterName(getFirmName(walletRefundVo.getFilter()));
            walletDetailBase.setStatus(walletRefundVo.getStatus());
            walletDetailBase.setStatusLabel(RefundEnum.getDesc(walletRefundVo.getStatus()));
            walletDetailBase.setMoney(walletRefundVo.getMoney());
            walletDetailBase.setRemark(walletRefundVo.getRemark());
            walletDetailBase.setCreateTime(DateTimeUtil.format(walletRefundVo.getCreateTime()));
            res.add(walletDetailBase);
        }
        return new PageRes<>(walletRefundVoPageRes.getPage(), walletRefundVoPageRes.getPageSize(), walletRefundVoPageRes.getSize(), walletRefundVoPageRes.getPages(), res);
    }

    /**
     * 资金明细-提现订单
     *
     * @param moneyPage
     * @return
     */
    public PageRes<WalletDetailBase> cashOrder(MoneyPage moneyPage) {
        String channel = moneyPage.getChannel();
        ChannelEnum channelEnum = ChannelEnum.getByChannel(channel);
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道不存在");
        }
        R<CashPage> cashPageR = payCenterService.withdrawIndex(moneyPage.getUid(), channelEnum, "all", moneyPage.getPage(), moneyPage.getPageSize());
        if (!cashPageR.getStatus()) {
            return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), 0, 0, new ArrayList<>());
        }
        CashPage data = cashPageR.getData();
        List<CashItem> rows = data.getRows();
        List<WalletDetailBase> collect = rows.stream().map(a -> {
            WalletDetailBase walletDetailBase = new WalletDetailBase();
            walletDetailBase.setOrderNo(a.getOrderNo());
            walletDetailBase.setChannel(a.getChannel());
            walletDetailBase.setChannelDict(ChannelEnum.getDict(a.getChannel()));
            walletDetailBase.setChannelLabel(ChannelEnum.getDesc(a.getChannel()));
            walletDetailBase.setUid(a.getUid());
            walletDetailBase.setUidName(getFirmName(a.getUid()));
            walletDetailBase.setFilter("");
            walletDetailBase.setFilterName("");
            walletDetailBase.setStatus(a.getStatus());
            walletDetailBase.setStatusLabel(a.getStatusLabel());
            walletDetailBase.setMoney(walletDetailBase.smallMoney(a.getMoney()));
            walletDetailBase.setRemark(a.getRemarks());
            walletDetailBase.setCreateTime(a.getCreateTime());

            return walletDetailBase;
        }).collect(Collectors.toList());
        return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), data.getTotal(), (int) (data.getTotal() / moneyPage.getPageSize() + 1), collect);
    }

    /**
     * 预付-退款订单
     *
     * @param moneyPage
     * @return
     */
    public PageRes<WalletDetailBase> prePayRefund(MoneyPage moneyPage) {
        RefundPage refundPage = new RefundPage();
        BeanUtils.copyProperties(moneyPage, refundPage);
        PageRes<WalletRefundVo> walletRefundVoPageRes = walletOrderService.queryRefundList(refundPage);
        List<WalletRefundVo> list = walletRefundVoPageRes.getList();
        List<WalletDetailBase> res = new ArrayList<>();
        WalletDetailBase walletDetailBase;
        for (WalletRefundVo walletRefundVo : list) {
            walletDetailBase = new WalletDetailBase();
            walletDetailBase.setOrderNo(walletRefundVo.getOrderNo());
            walletDetailBase.setChannel(walletRefundVo.getChannel());
            walletDetailBase.setChannelDict(ChannelEnum.getDict(walletRefundVo.getChannel()));
            walletDetailBase.setChannelLabel(ChannelEnum.getDesc(walletRefundVo.getChannel()));
            walletDetailBase.setUid(walletRefundVo.getUid());
            walletDetailBase.setUidName(getFirmName(walletRefundVo.getUid()));
            walletDetailBase.setFilter(walletRefundVo.getFilter());
            walletDetailBase.setFilterName(getFirmName(walletRefundVo.getFilter()));
            walletDetailBase.setStatus(walletRefundVo.getStatus());
            walletDetailBase.setStatusLabel(RefundEnum.getDesc(walletRefundVo.getStatus()));
            walletDetailBase.setMoney(walletRefundVo.getMoney());
            walletDetailBase.setRemark(walletRefundVo.getRemark());
            walletDetailBase.setCreateTime(DateTimeUtil.format(walletRefundVo.getCreateTime()));
            res.add(walletDetailBase);
        }
        return new PageRes<>(walletRefundVoPageRes.getPage(), walletRefundVoPageRes.getPageSize(), walletRefundVoPageRes.getSize(), walletRefundVoPageRes.getPages(), res);
    }

    /**
     * 预收-退款订单
     *
     * @param moneyPage
     * @return
     */
    public PageRes<WalletDetailBase> preReceiveRefund(MoneyPage moneyPage) {
        if (StringUtils.isNotBlank(moneyPage.getStartCreateTime())) {
            moneyPage.setStartCreateTime(StringTimeUtil.fillStart(moneyPage.getStartCreateTime()));
        }
        if (StringUtils.isNotBlank(moneyPage.getEndCreateTime())) {
            moneyPage.setEndCreateTime(StringTimeUtil.fillEnd(moneyPage.getEndCreateTime()));
        }
        String uid = moneyPage.getUid();
        String filter = moneyPage.getFilter();
        moneyPage.setUid(filter);
        moneyPage.setFilter(uid);
        RefundPage refundPage = new RefundPage();
        BeanUtils.copyProperties(moneyPage, refundPage);
        PageRes<WalletRefundVo> walletRefundVoPageRes = walletOrderService.queryRefundList(refundPage);
        List<WalletRefundVo> list = walletRefundVoPageRes.getList();
        List<WalletDetailBase> res = new ArrayList<>();
        WalletDetailBase walletDetailBase;
        for (WalletRefundVo walletRefundVo : list) {
            walletDetailBase = new WalletDetailBase();
            walletDetailBase.setOrderNo(walletRefundVo.getOrderNo());
            walletDetailBase.setChannel(walletRefundVo.getChannel());
            walletDetailBase.setChannelDict(ChannelEnum.getDict(walletRefundVo.getChannel()));
            walletDetailBase.setChannelLabel(ChannelEnum.getDesc(walletRefundVo.getChannel()));
            walletDetailBase.setUid(walletRefundVo.getUid());
            walletDetailBase.setUidName(getFirmName(walletRefundVo.getUid()));
            walletDetailBase.setFilter(walletRefundVo.getFilter());
            walletDetailBase.setFilterName(getFirmName(walletRefundVo.getFilter()));
            walletDetailBase.setStatus(walletRefundVo.getStatus());
            walletDetailBase.setStatusLabel(RefundEnum.getDesc(walletRefundVo.getStatus()));
            walletDetailBase.setMoney(walletRefundVo.getMoney());
            walletDetailBase.setRemark(walletRefundVo.getRemark());
            walletDetailBase.setCreateTime(DateTimeUtil.format(walletRefundVo.getCreateTime()));
            res.add(walletDetailBase);
        }
        return new PageRes<>(walletRefundVoPageRes.getPage(), walletRefundVoPageRes.getPageSize(), walletRefundVoPageRes.getSize(), walletRefundVoPageRes.getPages(), res);
    }

    /**
     * 详细记录-提现
     *
     * @param cashDetailReq
     * @return
     */
    public CashDetailVo cashDetail(CashDetailReq cashDetailReq) {
        R<CashDetail> cashDetailR = payCenterService.withdrawDetail(cashDetailReq.getUid(), cashDetailReq.getOrderNo());
        if (!cashDetailR.getStatus()) {
            throw new BusinessException(cashDetailR.getMsg());
        }
        CashDetail data = cashDetailR.getData();
        CashDetailVo cashDetailVo = new CashDetailVo();
        cashDetailVo.setOrderNo(data.getOrderNo());
        cashDetailVo.setChannel(data.getChannel());
        cashDetailVo.setChannelDict(ChannelEnum.getDict(data.getChannel()));
        cashDetailVo.setChannelLabel(ChannelEnum.getDesc(data.getChannel()));
        cashDetailVo.setUid(data.getUid());
        cashDetailVo.setUidName(getFirmName(data.getUid()));
        cashDetailVo.setStatus(data.getStatus());
        cashDetailVo.setStatusLabel(data.getStatusLabel());
        cashDetailVo.setMoney(cashDetailVo.smallMoney(data.getMoney()));
        cashDetailVo.setCreateTime(data.getCreateTime());
        cashDetailVo.setFinishTime(data.getFinishTime());
        List<CashLog> cashLogs = data.getLogs();
        if (!CollectionUtils.isEmpty(cashLogs)) {
            List<Logs> collect = cashLogs.stream().map(a -> {
                Logs logs = new Logs();
                logs.setOrderNo(a.getOrderNo());
                logs.setChannelLabel(ChannelEnum.getDesc(data.getChannel()));
                logs.setStatus(a.getStatus());
                logs.setStatusLabel(a.getStatusLabel());
                logs.setRemark(a.getContent());
                logs.setCreateTime(a.getCreateTime());
                return logs;
            }).sorted((c1, c2) -> {
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                if (StringUtils.isBlank(c1.getCreateTime())) {
                    return 0;
                }
                if (StringUtils.isBlank(c2.getCreateTime())) {
                    return 1;
                }
                LocalDateTime parse = LocalDateTime.parse(c1.getCreateTime(), df);
                LocalDateTime parse2 = LocalDateTime.parse(c2.getCreateTime(), df);
                return parse.compareTo(parse2);
            }).collect(Collectors.toList());
            cashDetailVo.setLogs(collect);
        }
        return cashDetailVo;
    }

    /**
     * 贸易订单预支付下单时，冻结预付款金额
     *
     * @param payEntId     支付方企业
     * @param channel      渠道
     * @param receiveEntId 收款方企业
     * @param money        冻结金额（分）
     * @param orderNo      订单流水
     * @return
     */
    public HttpResult freezeMoney(Long payEntId, ChannelEnum channel, Long receiveEntId, Long money, String orderNo) {
        String uid = getUid(payEntId);
        String filter = getUid(receiveEntId);
        R<Freeze> freezeR = payCenterService.walletFreeze(uid, channel, filter, money, orderNo);
        if (!freezeR.getStatus()) {
            log.error("资金冻结异常：{}", JSONObject.toJSONString(freezeR));
            return HttpResult.error(freezeR.getMsg());
        }
        return HttpResult.ok("冻结成功");
    }

    /**
     * 预付-详细记录
     *
     * @param moneyPage
     * @return
     */
    public PageRes<PrePayDetailVo> prePayOrder(MoneyPage moneyPage) {
        ChannelEnum byChannel = ChannelEnum.getByChannel(moneyPage.getChannel());
        if (Objects.isNull(byChannel)) {
            throw new BusinessException("支付通道异常");
        }
        R<Page<PrePayIndex2>> pageR = payCenterService.advancePayIndex2(moneyPage.getUid(), byChannel, moneyPage.getFilter(), moneyPage.getPage(), moneyPage.getPageSize(), moneyPage.getKeywords());
        if (!pageR.getStatus()) {
            return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), 0, 0, new ArrayList<>());
        }
        Page<PrePayIndex2> data = pageR.getData();
        if (Objects.nonNull(data)) {
            List<PrePayIndex2> rows = data.getRows();
            if (!CollectionUtils.isEmpty(rows)) {
                List<PrePayDetailVo> collect = rows.stream().map(a -> {
                    PrePayDetailVo prePayDetailVo = new PrePayDetailVo();
                    prePayDetailVo.setBalance(prePayDetailVo.smallMoney(a.getApBalance()));
                    prePayDetailVo.setOrderNo(a.getOrderNo());
                    prePayDetailVo.setChannel(a.getChannel());
                    prePayDetailVo.setChannelDict(ChannelEnum.getDict(a.getChannel()));
                    prePayDetailVo.setChannelLabel(ChannelEnum.getDesc(a.getChannel()));
                    prePayDetailVo.setUid(moneyPage.getUid());
                    prePayDetailVo.setUidName(getFirmName(moneyPage.getUid()));
                    prePayDetailVo.setFilter(moneyPage.getFilter());
                    prePayDetailVo.setFilterName(getFirmName(moneyPage.getFilter()));
                    Integer action = kwpWalletPrepayService.getAction(a.getOrderNo());
                    prePayDetailVo.setStatus(action);
                    prePayDetailVo.setStatusLabel(PrePayEnum.getByStatus(action));
                    prePayDetailVo.setMoney(prePayDetailVo.smallMoney(a.getMoney()));
                    prePayDetailVo.setRemark(a.getRemarks());
                    prePayDetailVo.setCreateTime(a.getCreateTime());
                    return prePayDetailVo;
                }).collect(Collectors.toList());
                return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), data.getTotal(), (int) (data.getTotal() / data.getPageSize() + 1), collect);
            }
        }
        return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), 0, 0, new ArrayList<>());
    }

    /**
     * 预收-详细记录
     *
     * @param moneyPage
     * @return
     */
    public PageRes<PrePayDetailVo> preReceiveOrder(MoneyPage moneyPage) {
        ChannelEnum byChannel = ChannelEnum.getByChannel(moneyPage.getChannel());
        if (Objects.isNull(byChannel)) {
            throw new BusinessException("支付通道异常");
        }
        R<Page<PrePayIndex2>> pageR = payCenterService.advancePayIndex2(moneyPage.getFilter(), byChannel, moneyPage.getUid(), moneyPage.getPage(), moneyPage.getPageSize(), moneyPage.getKeywords());
        if (!pageR.getStatus()) {
            return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), 0, 0, new ArrayList<>());
        }
        Page<PrePayIndex2> data = pageR.getData();
        if (Objects.nonNull(data)) {
            List<PrePayIndex2> rows = data.getRows();
            if (!CollectionUtils.isEmpty(rows)) {
                List<PrePayDetailVo> collect = rows.stream().map(a -> {
                    PrePayDetailVo prePayDetailVo = new PrePayDetailVo();
                    prePayDetailVo.setBalance(prePayDetailVo.smallMoney(a.getApBalance()));
                    prePayDetailVo.setOrderNo(a.getOrderNo());
                    prePayDetailVo.setChannel(a.getChannel());
                    prePayDetailVo.setChannelDict(ChannelEnum.getDict(a.getChannel()));
                    prePayDetailVo.setChannelLabel(ChannelEnum.getDesc(a.getChannel()));
                    prePayDetailVo.setUid(moneyPage.getUid());
                    prePayDetailVo.setUidName(getFirmName(moneyPage.getUid()));
                    prePayDetailVo.setFilter(moneyPage.getFilter());
                    prePayDetailVo.setFilterName(getFirmName(moneyPage.getFilter()));
                    Integer action = kwpWalletPrepayService.getAction(a.getOrderNo());
                    prePayDetailVo.setStatus(action);
                    prePayDetailVo.setStatusLabel(PrePayEnum.getByStatus(action));
                    prePayDetailVo.setMoney(prePayDetailVo.smallMoney(a.getMoney()));
                    prePayDetailVo.setRemark(a.getRemarks());
                    prePayDetailVo.setCreateTime(a.getCreateTime());
                    return prePayDetailVo;
                }).collect(Collectors.toList());
                return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), data.getTotal(), (int) (data.getTotal() / data.getPageSize() + 1), collect);
            }
        }
        return new PageRes<>(moneyPage.getPage(), moneyPage.getPageSize(), 0, 0, new ArrayList<>());
    }

    /**
     * 会员注册信息
     *
     * @param uid
     * @param channel
     * @return
     */
    public Object userInfo(String uid, String channel) {
        ChannelEnum channelEnum = ChannelEnum.getByChannel(channel);
        if (Objects.isNull(channelEnum)) {
            throw new BusinessException("支付通道异常");
        }
        R<JSONObject> user = payCenterService.user(uid, channelEnum);
        if (!user.getStatus()) {
            throw new BusinessException(StringUtils.isNotBlank(user.getMsg()) ? user.getMsg() : "会员信息不存在");
        }
        return user.getData();
    }

    /**
     * 退款处理
     *
     * @param refundReq
     * @param kwpWalletRefund
     * @param payCenterService
     * @param kwpWalletRefundMapper
     * @param userId
     */
    private record Refund(RefundReq refundReq, KwpWalletRefund kwpWalletRefund, PayCenterService payCenterService,
                          KwpWalletRefundMapper kwpWalletRefundMapper, Long userId) implements Runnable {
        private final static Logger log = LoggerFactory.getLogger(Refund.class);

        @Override
        public void run() {
            ChannelEnum channelEnum = ChannelEnum.getByChannel(kwpWalletRefund.getChannel());
            List<PatchPay> list = new ArrayList<>();
            PatchPay patchPay = new PatchPay();
            patchPay.setUid(kwpWalletRefund.getFilter());
            patchPay.setMoney(refundReq.bigMoney(refundReq.getMoney()));
            patchPay.setRemark(refundReq.getRemark());
            list.add(patchPay);
            log.info("异步提交清分退款任务");
            R<BusinessNo> businessNoR1 = payCenterService.payAgentPayV2(kwpWalletRefund.getFilter(), kwpWalletRefund.getUid(), channelEnum, refundReq.bigMoney(refundReq.getMoney()), list, OrderUtils.generateOrderNo("SEQ"), "2");
            if (businessNoR1.getStatus()) {
                kwpWalletRefund.setActualMoney(refundReq.getMoney());
                kwpWalletRefund.setUpdateBy(userId);
                kwpWalletRefund.setUpdateTime(LocalDateTime.now());
                kwpWalletRefund.setStatus(RefundEnum.REFUNDING.getStatus());
                kwpWalletRefundMapper.updateById(kwpWalletRefund);
            }
        }
    }

}
