package com.jeequan.jeepay.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrderCount;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.mchconfig.MchDivisionConfig;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.utils.DateKit;
import com.jeequan.jeepay.db.config.dynamic.DataSourceSwitch;
import com.jeequan.jeepay.db.config.dynamic.DynamicDataSource;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.service.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 支付订单表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2021-04-27
 */
@Service
@Slf4j
public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {

    @Autowired private PayOrderMapper payOrderMapper;
    @Autowired private MchInfoMapper mchInfoMapper;
    @Autowired private IsvInfoMapper isvInfoMapper;
    @Autowired private AgentInfoMapper agentInfoMapper;
    @Autowired private PayOrderDivisionRecordMapper payOrderDivisionRecordMapper;
    @Autowired private StatsTradeMapper statsTradeMapper;
    @Autowired private StatsPayWayMapper statsPayWayMapper;
    @Autowired private StatsTradeService statsTradeService;
    @Autowired private MchAppService mchAppService;
    @Autowired private PayInterfaceDefineService payInterfaceDefineService;
    @Autowired private PayWayService payWayService;
    @Autowired private RefundOrderService refundOrderService;

    /** 更新订单状态  【订单生成】 --》 【支付中】 **/
    public boolean updateInit2Ing(String payOrderId, PayOrder payOrder){

        PayOrder updateRecord = new PayOrder();
        updateRecord.setState(PayOrder.STATE_ING);

        //同时更新， 未确定 --》 已确定的其他信息。  如支付接口的确认、 费率的计算。
        updateRecord.setIfCode(payOrder.getIfCode());
        updateRecord.setWayCode(payOrder.getWayCode());
        updateRecord.setWayCodeType(payOrder.getWayCodeType());
        updateRecord.setMchFeeRate(payOrder.getMchFeeRate());
        updateRecord.setMchFeeAmount(payOrder.getMchFeeAmount());
        updateRecord.setMchOrderFeeAmount(payOrder.getMchOrderFeeAmount());
        updateRecord.setCashFee(payOrder.getCashFee());
        updateRecord.setCashRate(payOrder.getCashRate());
        updateRecord.setChannelUser(payOrder.getChannelUser());
        updateRecord.setChannelOrderNo(payOrder.getChannelOrderNo());
        updateRecord.setDivisionMode(payOrder.getDivisionMode()); // 分账模式更新。

        // 服务商机构号或子商户号
        updateRecord.setChannelIsvNo(payOrder.getChannelIsvNo());
        updateRecord.setChannelMchNo(payOrder.getChannelMchNo());
        updateRecord.setChannelBizData(payOrder.getChannelBizData());
        if(StringUtils.isNotEmpty(payOrder.getPayData())){
            updateRecord.setPayData(payOrder.getPayData());
        }
        return update(updateRecord, new LambdaUpdateWrapper<PayOrder>()
                .eq(PayOrder::getPayOrderId, payOrderId).eq(PayOrder::getState, PayOrder.STATE_INIT));
    }

    /** 更新订单状态  【支付中】 --》 【支付成功】 **/
    public boolean updateIng2Success(String payOrderId, ChannelRetMsg retMsg){

        PayOrder updateRecord = new PayOrder();
        updateRecord.setState(PayOrder.STATE_SUCCESS);
        updateRecord.setChannelOrderNo(retMsg.getChannelOrderId());
        updateRecord.setChannelUser(retMsg.getChannelUserId());
        updateRecord.setSuccessTime(new Date());
        updateRecord.setDrType(StringUtils.isNotBlank(retMsg.getDrType()) ? retMsg.getDrType() : CS.DrType.OTHER.getType());
        if(StringUtils.isNotBlank(retMsg.getPlatformOrderNo())){
            updateRecord.setPlatformOrderNo(retMsg.getPlatformOrderNo());
        }
        if(StringUtils.isNotBlank(retMsg.getPlatformMchOrderNo())){
            updateRecord.setPlatformMchOrderNo(retMsg.getPlatformMchOrderNo());
        }
        if(StringUtils.isNotBlank(retMsg.getWayCodeType())){
            updateRecord.setWayCodeType(retMsg.getWayCodeType());
        }
        if(retMsg.getChannelBizData() != null){
            updateRecord.setChannelBizData(retMsg.getChannelBizData().toString());
        }
        if(retMsg.getChannelBizData() != null){
            updateRecord.setChannelBizData(retMsg.getChannelBizData().toString());
        }
        if(StringUtils.isNotBlank(retMsg.getChannelUserId())){
            updateRecord.setChannelUser(retMsg.getChannelUserId());
        }
        return update(updateRecord, new LambdaUpdateWrapper<PayOrder>()
                .eq(PayOrder::getPayOrderId, payOrderId).eq(PayOrder::getState, PayOrder.STATE_ING));
    }


    /** 更新订单状态  【支付中】 --》 【支付失败】 **/
    public boolean updateIng2Fail(String payOrderId, ChannelRetMsg retMsg){

        PayOrder updateRecord = new PayOrder();
        updateRecord.setState(PayOrder.STATE_FAIL);
        updateRecord.setErrCode(retMsg.getChannelErrCode());
        updateRecord.setErrMsg(retMsg.getChannelErrMsg());
        updateRecord.setChannelOrderNo(retMsg.getChannelOrderId());
        updateRecord.setChannelUser(retMsg.getChannelUserId());

        return update(updateRecord, new LambdaUpdateWrapper<PayOrder>()
                .eq(PayOrder::getPayOrderId, payOrderId).eq(PayOrder::getState, PayOrder.STATE_ING));
    }


    /** 更新订单状态  【支付中】 --》 【支付成功/支付失败】 **/
    public boolean updateIng2SuccessOrFail(String payOrderId, Byte updateState, ChannelRetMsg retMsg){

        if(updateState == PayOrder.STATE_ING){
            return true;
        }else if(updateState == PayOrder.STATE_SUCCESS){
            return updateIng2Success(payOrderId, retMsg);
        }else if(updateState == PayOrder.STATE_FAIL){
            return updateIng2Fail(payOrderId, retMsg);
        }
        return false;
    }

    /** 更新订单状态  【订单生成】 --》 【订单关闭】 **/
    public boolean updateInit2Close(String payOrderId){

        PayOrder updateRecord = new PayOrder();
        updateRecord.setState(PayOrder.STATE_CLOSED);

        return update(updateRecord, new LambdaUpdateWrapper<PayOrder>()
                .eq(PayOrder::getPayOrderId, payOrderId).eq(PayOrder::getState, PayOrder.STATE_INIT));
    }

    /** 更新订单状态  【支付中】 --》 【订单关闭】 **/
    public boolean updateIng2Close(String payOrderId){

        PayOrder updateRecord = new PayOrder();
        updateRecord.setState(PayOrder.STATE_CLOSED);

        return update(updateRecord, new LambdaUpdateWrapper<PayOrder>()
                .eq(PayOrder::getPayOrderId, payOrderId).in(PayOrder::getState, PayOrder.STATE_ING,PayOrder.STATE_INIT));
    }

    /** 更新订单状态  【支付中】 --》 【订单关闭】 **/
    public boolean updateClose2Ing(String payOrderId) {
        PayOrder updateRecord = new PayOrder();
        updateRecord.setState(PayOrder.STATE_ING);

        return update(updateRecord, new LambdaUpdateWrapper<PayOrder>()
                .eq(PayOrder::getPayOrderId, payOrderId).eq(PayOrder::getState, PayOrder.STATE_CLOSED));
    }

    /** 查询商户订单 **/
    public PayOrder queryMchOrder(String mchNo, String payOrderId, String mchOrderNo){

        if(StringUtils.isNotEmpty(payOrderId)){
            return getOne(PayOrder.gw().eq(PayOrder::getMchNo, mchNo).eq(PayOrder::getPayOrderId, payOrderId));
        }else if(StringUtils.isNotEmpty(mchOrderNo)){
            return getOne(PayOrder.gw().eq(PayOrder::getMchNo, mchNo).eq(PayOrder::getMchOrderNo, mchOrderNo));
        }else{
            return null;
        }
    }


    public PayOrderCount payCount(String mchNo, String agentNo, String topAgentNo, String storeId, Byte state,
                        Byte refundState, String dayStart, String dayEnd, String epUserId, List<String> storeIdList) {
        return payCount(mchNo, agentNo, topAgentNo, storeId, state, refundState, dayStart, dayEnd, epUserId, storeIdList, null);
    }

    public PayOrderCount payCount(String mchNo, String agentNo, String topAgentNo, String storeId, Byte state,
                        Byte refundState, String dayStart, String dayEnd, String epUserId, List<String> storeIdList, List<String> agentSubList) {
        HashMap<String, Object> param = new HashMap();
        if (state != null) {
            param.put("state", state);
        }
        if (refundState != null) {
            param.put("refundState", refundState);
        }
        if (StrUtil.isNotBlank(mchNo)) {
            param.put("mchNo", mchNo);
        }
        if (StrUtil.isNotBlank(agentNo)) {
            param.put("agentNo", agentNo);
        }
        if (StrUtil.isNotBlank(topAgentNo)) {
            param.put("topAgentNo", topAgentNo);
        }
        if (StrUtil.isNotBlank(storeId)) {
            param.put("storeId", storeId);
        }
        if (StrUtil.isNotBlank(epUserId)) {
            param.put("epUserId", epUserId);
        }
        if (StrUtil.isNotBlank(dayStart)) {
            param.put("createTimeStart", dayStart);
        }
        if (StrUtil.isNotBlank(dayEnd)) {
            param.put("createTimeEnd", dayEnd);
        }
        param.put("storeIdList", storeIdList);

        return payOrderMapper.payCount(param, agentSubList);
    }

    public List<PayOrderCount> payTypeCount(String mchNo, String storeId, List<String> agentSubList,
                                  Byte state, Byte refundState, String dayStart, String dayEnd, List<String> storeIdList, String dateRange) {
        Map param = new HashMap<>();
        if (state != null) {
            param.put("state", state);
        }
        if (refundState != null) {
            param.put("refundState", refundState);
        }
        if (StrUtil.isNotBlank(mchNo)) {
            param.put("mchNo", mchNo);
        }
        if (StrUtil.isNotBlank(storeId)) {
            param.put("storeId", storeId);
        }
        if (CollUtil.isNotEmpty(agentSubList)) {
            param.put("agentSubList", agentSubList);
        }
        if (StrUtil.isNotBlank(dayStart)) {
            param.put("createTimeStart", dayStart);
        }
        if (StrUtil.isNotBlank(dayEnd)) {
            param.put("createTimeEnd", dayEnd);
        }
        param.put("storeIdList", storeIdList);

        List<PayOrderCount> otherList = new ArrayList<>();
        List<PayOrderCount> todayList = new ArrayList<>();

        // left-包含今天，right-包含其他日期
        MutablePair<Boolean, Boolean> mutablePair = statsTradeService.parseQueryDate(dateRange);

        DateTime today = DateUtil.date(); // 当前时间

        // 含其他日期
        if (mutablePair.right) {
            otherList = statsPayWayMapper.payTypeCount(param);

            // 含今日
            if (mutablePair.left) {
                param.put("createTimeStart", DateUtil.beginOfDay(today));
                param.put("createTimeEnd", DateUtil.endOfDay(today));
                todayList = payOrderMapper.payTypeCount(param);

                if (CollUtil.isEmpty(otherList)) {
                    return todayList;
                }

                for (PayOrderCount otherMap : otherList) {
                    for (PayOrderCount todayMap : todayList) {
                        if (todayMap.getWayType().equals(otherMap.getWayType())) {
                            otherMap.setTotalSuccNum(otherMap.getTotalSuccNum() + todayMap.getTotalSuccNum());
                            otherMap.setTotalSuccAmt(otherMap.getTotalSuccAmt() + todayMap.getTotalSuccAmt());
                        }
                    }
                }
            }
        }
        // 不含其他日期，含今天
        else if (mutablePair.left) {
            param.put("createTimeStart", DateUtil.beginOfDay(today));
            param.put("createTimeEnd", DateUtil.endOfDay(today));
            todayList = payOrderMapper.payTypeCount(param);
            return todayList;
        }

        return otherList;
    }

    /** 更新订单为 超时状态 **/
    public Integer updateOrderExpired(){

        PayOrder payOrder = new PayOrder();
        payOrder.setState(PayOrder.STATE_CLOSED);

        return baseMapper.update(payOrder,
                PayOrder.gw()
                        .in(PayOrder::getState, Arrays.asList(PayOrder.STATE_INIT, PayOrder.STATE_ING))
                        .le(PayOrder::getExpiredTime, new Date())
        );
    }

    /** 更新订单 通知状态 --> 已发送 **/
    public int updateNotifySent(String payOrderId){
        PayOrder payOrder = new PayOrder();
        payOrder.setNotifyState(CS.YES);
        payOrder.setPayOrderId(payOrderId);
        return baseMapper.updateById(payOrder);
    }

    /** 首页支付统计 **/
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public JSONObject mainPagePayCount(String mchNo, List<String> agentSubList, JSONObject paramJSON) {
        String dateRange = paramJSON.getString("queryDateRange");
        String storeId = paramJSON.getString("storeId");
        if (StringUtils.isEmpty(dateRange)) {
            dateRange = "near2now_30";
        }
        // 获取查询时间请求参数  [开始时间,  结束时间]
        Date[] queryDateRangeArray = DateKit.getQueryDateRange(dateRange);
        String createdStart = DateUtil.formatDateTime(queryDateRangeArray[0]);
        String createdEnd = DateUtil.formatDateTime(queryDateRangeArray[1]);

        Map<String, Object> param = new HashMap<>(); // 条件参数
        // 计算两时间间隔天数
        int daySpace = Math.toIntExact(DateUtil.betweenDay(DateUtil.parseDate(createdStart), DateUtil.parseDate(createdEnd), true));

        if (StrUtil.isNotBlank(mchNo)) {
            param.put("mchNo", mchNo);
        }
        if (StrUtil.isNotBlank(storeId)) {
            param.put("storeId", storeId);
        }
        if (CollUtil.isNotEmpty(agentSubList)) {
            param.put("agentSubList", agentSubList);
        }
        param.put("createTimeStart", createdStart);
        param.put("createTimeEnd", createdEnd);
        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        param.put("storeIdList", storeIdList);

        // 查询收款的记录
        List<PayOrderCount> otherList = new ArrayList<>();
        List<PayOrderCount> todayList = new ArrayList<>();

        // left-包含今天，right-包含其他日期
        MutablePair<Boolean, Boolean> mutablePair = statsTradeService.parseQueryDate(dateRange);

        DateTime today = DateUtil.date(); // 当前时间

        // 含其他日期
        if (mutablePair.right) {
            otherList = statsTradeMapper.selectOrderCount(param);

            // 含今日
            if (mutablePair.left) {
                param.put("createTimeStart", DateUtil.beginOfDay(today));
                param.put("createTimeEnd", DateUtil.endOfDay(today));
                todayList = payOrderMapper.selectOrderCount(param);

                if (CollUtil.isEmpty(otherList)) {
                    return getPayCountResJson(daySpace, createdEnd, todayList);
                }

                for (PayOrderCount todayMap : todayList) {
                    if (todayMap.getGroupDate().equals(DateUtil.formatDate(today))) {
                        otherList.add(0, todayMap);
                    }
                }
            }
        }
        // 不含其他日期，含今天
        else if (mutablePair.left) {
            param.put("createTimeStart", DateUtil.beginOfDay(today));
            param.put("createTimeEnd", DateUtil.endOfDay(today));
            todayList = payOrderMapper.selectOrderCount(param);
            return getPayCountResJson(daySpace, createdEnd, todayList);
        }

        // 生成前端返回参数类型
        return getPayCountResJson(daySpace, createdEnd, otherList);
    }

    /** 首页支付类型统计 **/
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public ArrayList mainPagePayTypeCount(String mchNo, List<String> agentSubList, JSONObject paramJSON) {
        String dateRange = paramJSON.getString("queryDateRange");
        String storeId = paramJSON.getString("storeId");
        // 获取查询时间请求参数  [开始时间,  结束时间]
        Date[] queryDateRangeArray = DateKit.getQueryDateRange(dateRange);
        String createdStart = DateUtil.formatDateTime(queryDateRangeArray[0]);
        String createdEnd = DateUtil.formatDateTime(queryDateRangeArray[1]);
        // 返回数据列
        ArrayList array = new ArrayList<>();
        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);

        // 统计列表
        List<PayOrderCount> payCountMap = payTypeCount(mchNo, storeId, agentSubList, PayOrder.STATE_SUCCESS, null, createdStart, createdEnd, storeIdList, dateRange);

        // 支付方式名称标注
        for (PayOrderCount count:payCountMap) {
            count.setName(CS.PAY_WAY_CODE_TYPE_MAP.get(count.getWayType()));
        }
        array.add(payCountMap);
        return array;
    }

    /** 生成首页交易统计数据类型 **/
    public JSONObject getPayCountResJson(int daySpace, String createdStart, List<PayOrderCount> payOrderList) {
        // 返回结果
        JSONObject resJson = new JSONObject();
        ArrayList<String> dayArray = new ArrayList<>();
        ArrayList<String> payAmountArray = new ArrayList<>();
        ArrayList<String> refundAmountArray = new ArrayList<>();
        ArrayList<String> payCountArray = new ArrayList<>();

        List<Map> dayList = new ArrayList<>();
        DateTime endDay = DateUtil.parseDateTime(createdStart);
        // 先判断间隔天数 根据天数设置空的list
        for (int i = 0; i <= daySpace ; i++) {
            Map<String, String> map = new HashMap<>();
            String dateFormat = DateUtil.format(DateUtil.offsetDay(endDay, -i), DatePattern.NORM_DATE_PATTERN);
            map.put("date", dateFormat);
            dayList.add(map);
            dayArray.add(dateFormat);
        }
        // 日期倒序排列
        Collections.reverse(dayList);
        Collections.reverse(dayArray);

        for (Map dayMap:dayList) {
            String payAmount = "";
            String refundAmount = "";
            String payCount = "";
            for (PayOrderCount payOrderMap:payOrderList) {
                if (dayMap.get("date").equals(payOrderMap.getGroupDate())) {
                    payAmount = payOrderMap.getTotalSuccAmt().toString();
                    refundAmount = payOrderMap.getTotalRefundAmt().toString();
                    payCount = payOrderMap.getTotalSuccNum().toString();
                }
            }
            if (StringUtils.isEmpty(payAmount)) {
                payAmount = "0";
                refundAmount = "0";
                payCount = "0";
            }
            payAmountArray.add(payAmount);
            refundAmountArray.add(refundAmount);
            payCountArray.add(payCount);
        }
        resJson.put("resDateArr", dayArray);
        resJson.put("resPayAmountArr", payAmountArray);
        resJson.put("resRefAmountArr", refundAmountArray);
        resJson.put("resPayCountArr", payCountArray);

        return resJson;
    }


    /**
     *  计算支付订单商家入账金额
     * 商家订单入账金额 （支付金额 - 手续费 - 退款金额 - 总分账金额） ( 是否扣减手续费取决于商户的配置 )
     * @author terrfly
     * @date 2021/8/26 16:39
     */
    public Long calMchIncomeAmount(PayOrder dbPayOrder, String calBaseAmountType) {

        if (StringUtils.isEmpty(calBaseAmountType)) {
            calBaseAmountType = MchDivisionConfig.CAL_BASE_AMOUNT_TYPE_INCOME_AMOUNT;
        }

        // 商家订单入账金额
        Long mchIncomeAmount = 0L;

        if(dbPayOrder.getDiscountAmt() != null){
            //商户入账金额等于 订单金额减去优惠金额 实际付款金额
            mchIncomeAmount = dbPayOrder.getAmount() - dbPayOrder.getDiscountAmt();
        }
        if (MchDivisionConfig.CAL_BASE_AMOUNT_TYPE_INCOME_AMOUNT.equals(calBaseAmountType)) {
            //商家订单入账金额 （支付金额 - 手续费 - 退款金额 - 总分账金额）
            mchIncomeAmount = dbPayOrder.getAmount() - dbPayOrder.getMchFeeAmount() - dbPayOrder.getRefundAmount();
        } else if (MchDivisionConfig.CAL_BASE_AMOUNT_TYPE_ORDER_AMOUNT.equals(calBaseAmountType)) {
            //商家订单入账金额 （支付金额 - 退款金额 - 总分账金额）
            mchIncomeAmount = dbPayOrder.getAmount() - dbPayOrder.getRefundAmount();
        }
        //减去已分账金额
        mchIncomeAmount -= payOrderDivisionRecordMapper.sumSuccessDivisionAmount(dbPayOrder.getPayOrderId());

        return mchIncomeAmount <= 0 ? 0 : mchIncomeAmount;

    }

    /**
     * 通用列表查询条件
     * @param payOrder
     * @param paramJSON
     * @param
     * @return
     */
    public IPage<PayOrder> listByPage(IPage<PayOrder> iPage, PayOrder payOrder, JSONObject paramJSON) {
        // 时间范围条件
        Date[] dateRange = payOrder.buildQueryDateRange();
        if (dateRange[0] != null) {
            payOrder.setFirstDate(dateRange[0]);
        }
        if (dateRange[1] != null) {
            payOrder.setLastDate(dateRange[1]);
        }
        if (!StringUtils.isAnyBlank(payOrder.getDeviceNo(), payOrder.getDeviceType())) {
            payOrder.setDeviceNo(payOrder.getDeviceNo());
            payOrder.setDeviceType(payOrder.getDeviceType());
        }
        // 多状态查询
        if (StringUtils.isNotEmpty(paramJSON.getString("unionOrderState"))) {
            String[] stateArr = paramJSON.getString("unionOrderState").split(",");
            List<String> statesList = Arrays.asList(stateArr);
            payOrder.setUnionOrderState(statesList);
        }
        // 多状态查询
        if (StringUtils.isNotEmpty(paramJSON.getString("unionWayCodeType"))) {
            String[] wayCodeTypeArr = paramJSON.getString("unionWayCodeType").split(",");
            List<String> wayCodeTypeList = Arrays.asList(wayCodeTypeArr);
            payOrder.setUnionWayCodeType(wayCodeTypeList);
        }
        IPage<PayOrder> listByPage = payOrderMapper.getListByPage(iPage, payOrder);
        listByPage.getRecords().forEach(item->{
            //手机号脱敏
            if (StringUtils.isNotEmpty(item.getAgentContactTel())){
                item.setAgentContactTel(DesensitizedUtil.mobilePhone(item.getAgentContactTel()));
            }
            if (StringUtils.isNotEmpty(item.getMchUserPhone())){
                item.setMchUserPhone(DesensitizedUtil.mobilePhone(item.getMchUserPhone()));
            }
            //处理收单手续费字符串问题
            try {
                if (StringUtils.isNotEmpty(item.getMchFeeRate())){
                    item.setMchFeeRateNum("0");
                    String mchFeeRate = item.getMchFeeRate();
                    if (mchFeeRate.contains("单笔费率")){
                        int colonIndex = mchFeeRate.indexOf("：");
                        int percentIndex = mchFeeRate.indexOf("%");
                        if (colonIndex != -1 && percentIndex != -1) {
                            String extractedData = mchFeeRate.substring(colonIndex + 1, percentIndex + 1).trim();
                            item.setMchFeeRateNum(extractedData);
                        }
                    }
                }else {
                    item.setMchFeeRateNum("0");
                }
            }catch (Exception e){
                item.setMchFeeRateNum("0");
            }
        });

        return listByPage;
    }

    /**
     * 服务商、商户数量统计
     * @return
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public JSONObject isvAndMchCount() {
        JSONObject resJson = new JSONObject();
        // 服务商总数
        long isvCount = isvInfoMapper.selectCount(IsvInfoEntity.gw());
        // 服务商总数
        long agentCount = SysConfigService.IS_HAS_AGENT_ENT ? agentInfoMapper.selectCount(AgentInfo.gw()) : 0 ;
        // 商户总数
        long mchCount = mchInfoMapper.selectCount(MchInfo.gw());
        // 特约商户&普通商户总数
        long normalMchCount = mchInfoMapper.selectCount(MchInfo.gw().eq(MchInfo::getType, MchInfo.TYPE_NORMAL));
        long isvSubMchCount = mchCount - normalMchCount;
        resJson.put("totalMch", mchCount);
        resJson.put("totalAgent", agentCount);
        resJson.put("totalIsv", isvCount);
        resJson.put("normalMchCount", normalMchCount);
        resJson.put("isvSubMchCount", isvSubMchCount);
        return resJson;
    }

    /**
     * 今日、昨日交易统计
     * @param mchNo
     * @return
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public JSONObject payDayCount(String mchNo, String agentNo, String topAgentNo, JSONObject paramJSON) {
        String dateRange = paramJSON.getString("queryDateRange");
        String storeId = paramJSON.getString("storeId");    // 门店ID
        String epUserId = paramJSON.getString("epUserId");
        String isQueryAll = (String) paramJSON.getOrDefault("isQueryAll", "");
        if (StringUtils.isNotEmpty(topAgentNo)) {
            agentNo = null;
        }
        String createdStart = null;
        String createdEnd = null;

        if (StringUtils.isEmpty(isQueryAll)) {
            // 获取查询时间请求参数  [开始时间,  结束时间]
            Date[] queryDateRangeArray = DateKit.getQueryDateRange(dateRange);
            if (StringUtils.isEmpty(dateRange)) {   // 如果未传入参数默认为当天
                // 今日时间范围
                queryDateRangeArray = DateKit.getQueryDateRange("today");
            }
            createdStart = DateUtil.formatDateTime(queryDateRangeArray[0]);
            createdEnd = DateUtil.formatDateTime(queryDateRangeArray[1]);
        }
        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);

        HashMap<String, Object> countMap = new HashMap<>();
        // 成功交易统计
        PayOrderCount payCountMap = payCount(mchNo, agentNo, topAgentNo, storeId, PayOrder.STATE_SUCCESS, null, createdStart, createdEnd, epUserId, storeIdList);
        // 退款交易统计
        PayOrderCount refundCountMap = payCount(mchNo, agentNo, topAgentNo, storeId, null, PayOrder.REFUND_STATE_NONE, createdStart, createdEnd, epUserId, storeIdList);
        // 全部交易统计
        PayOrderCount allCountMap = payCount(mchNo, agentNo, topAgentNo, storeId, null, null, createdStart, createdEnd, epUserId, storeIdList);
        countMap.put("payAmount", payCountMap.getTotalAmt());
        countMap.put("payCount", payCountMap.getTotalNum());
        countMap.put("refundAmount", refundCountMap.getTotalRefundAmt());
        countMap.put("refundCount", refundCountMap.getTotalNum());
        countMap.put("allCount", allCountMap.getTotalNum());
        // 返回对象
        JSONObject resJson = new JSONObject();
        resJson.put("dayCount", countMap);
        return resJson;
    }

    /**
     * 交易统计
     * @param mchNo
     * @return
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Map<String, Object> tradeCount(String mchNo, String agentNo, List<String> agentSubList, JSONObject paramJSON) {
        String dateRange = paramJSON.getString("queryDateRange");
        String storeId = paramJSON.getString("storeId");    // 门店ID
        String epUserId = paramJSON.getString("epUserId");
        String isQueryAll = (String) paramJSON.getOrDefault("isQueryAll", "");

        String createdStart = null;
        String createdEnd = null;

        if (StringUtils.isEmpty(isQueryAll)) {
            // 获取查询时间请求参数  [开始时间,  结束时间]
            Date[] queryDateRangeArray = DateKit.getQueryDateRange(dateRange);
            if (StringUtils.isEmpty(dateRange)) {   // 如果未传入参数默认为当天
                // 今日时间范围
                queryDateRangeArray = DateKit.getQueryDateRange("today");
            }
            createdStart = DateUtil.formatDateTime(queryDateRangeArray[0]);
            createdEnd = DateUtil.formatDateTime(queryDateRangeArray[1]);
        }

        HashMap<String, Object> countMap = new HashMap<>();
        // 成功交易统计
        PayOrderCount payCountMap = payCount(mchNo, agentNo, null, storeId, PayOrder.STATE_SUCCESS, null, createdStart, createdEnd, epUserId, null, agentSubList);
        // 退款交易统计
        PayOrderCount refundCountMap = payCount(mchNo, agentNo, null, storeId, null, PayOrder.REFUND_STATE_NONE, createdStart, createdEnd, epUserId, null, agentSubList);
        // 全部交易统计
        PayOrderCount allCountMap = payCount(mchNo, agentNo, null, storeId, null, null, createdStart, createdEnd, epUserId, null, agentSubList);
        countMap.put("payAmount", payCountMap.getTotalAmt());
        countMap.put("payCount", payCountMap.getTotalNum());
        countMap.put("refundAmount", refundCountMap.getTotalRefundAmt());
        countMap.put("refundCount", refundCountMap.getTotalNum());
        countMap.put("allCount", allCountMap.getTotalNum());

        return countMap;
    }

    /**
     * 交易趋势统计
     * @param paramJSON
     * @param mchNo
     * @return
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public JSONObject payTrendCount(JSONObject paramJSON, String mchNo, List<String> agentSubList) {
        // 返回参数
        ArrayList<String> resAmountList = new ArrayList<>();
        ArrayList<String> resDayList = new ArrayList<>();
        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);

        // 当前日期
        DateTime today = DateUtil.date();
        String timeStar = "";
        String timeEnd = "";
        String queryParamVal = "near2now_30"; // 默认为近30天
        int recentDay = paramJSON.getIntValue("recentDay");
        String storeId = paramJSON.getString("storeId");
        if (recentDay == 7) {   // 近7天
            queryParamVal = "near2now_7";
        }
        Date[] dateRanges = DateKit.getQueryDateRange(queryParamVal);
        timeStar = DateUtil.formatDateTime(dateRanges[0]);
        timeEnd = DateUtil.formatDateTime(dateRanges[1]);

        Map<String, Object> paramMap = new HashMap<>();
        if (StrUtil.isNotBlank(mchNo)) {
            paramMap.put("mchNo", mchNo);
        }
        if (StrUtil.isNotBlank(storeId)) {
            paramMap.put("storeId", storeId);
        }
        if (CollUtil.isNotEmpty(agentSubList)) {
            paramMap.put("agentSubList", agentSubList);
        }
        paramMap.put("createTimeStart", timeStar);
        paramMap.put("createTimeEnd", timeEnd);

        paramMap.put("storeIdList", storeIdList);
        List<PayOrderCount> payOrderList = statsTradeMapper.selectOrderCount(paramMap);
        // 日期listMap
        List<Map> dayList = new ArrayList<>();
        // 先判断间隔天数 根据天数设置空的list
        for (int i = 0; i < recentDay ; i++) {
            Map<String, String> map = new HashMap<>();
            String formatDay = DateUtil.format(DateUtil.offsetDay(today, -i), DatePattern.NORM_DATE_PATTERN);
            String formatDayMd = DateUtil.format(DateUtil.offsetDay(today, -i), "MM-dd");
            map.put("date", formatDay);
            dayList.add(map);
            resDayList.add(formatDayMd);
        }
        // 日期倒序排列
        Collections.reverse(dayList);
        Collections.reverse(resDayList);

        // 查询今日数据
        paramMap.put("createTimeStart", DateUtil.beginOfDay(today));
        paramMap.put("createTimeEnd", DateUtil.endOfDay(today));
        List<PayOrderCount> todayList = payOrderMapper.selectOrderCount(paramMap);

        for (Map dayMap:dayList) {
            String payAmount = "";
            // 如果金额不为空，获取金额数据
            for (PayOrderCount payOrderMap:payOrderList) {
                if (dayMap.get("date").equals(payOrderMap.getGroupDate())) {
                    payAmount = payOrderMap.getTotalSuccAmt().toString();
                }
            }

            // 替换今日数据
            if (dayMap.get("date").equals(DateUtil.formatDate(today))) {
                for (PayOrderCount todayMap : todayList) {
                    if (dayMap.get("date").equals(todayMap.getGroupDate())) {
                        payAmount = todayMap.getTotalSuccAmt().toString();
                    }
                }
            }

            if (StringUtils.isEmpty(payAmount)) {
                payAmount = "0";
            }
            // 存入返回金额数组
            resAmountList.add(payAmount);
        }

        JSONObject resJson = new JSONObject();
        resJson.put("dateList", resDayList);
        resJson.put("payAmountList", resAmountList);
        return resJson;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/2/11 10:06
     * @describe: 支付订单统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount orderCount(PayOrder payOrder, JSONObject paramJSON, List<String> allAgentNoList) {
        Map paramsMap = getParamsMap(payOrder, paramJSON);
        PayOrderCount resMap = payOrderMapper.payOrderCount(paramsMap, allAgentNoList);
        // 返回对象
        return resMap;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 商户统计列表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> countListByMch(PayOrder payOrder, JSONObject paramJSON, List<String> agentSubList) {
        Page<PayOrderCount> page = new Page<>();
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        Long count = payOrderMapper.countByMch(paramsMap, agentSubList);
        if (count != 0) {
            List<PayOrderCount> resList = payOrderMapper.countListByMch(paramsMap, agentSubList);
            page.setTotal(count);
            page.setRecords(resList);
        }
        return page;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 商户门店统计列表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> countListByStore(PayOrder payOrder, JSONObject paramJSON) {
        Page<PayOrderCount> page = new Page<>();
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);

        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        paramsMap.put("storeIdList", storeIdList);

        Long count = payOrderMapper.countByStore(paramsMap);
        if (count != 0) {
            List<PayOrderCount> resList = payOrderMapper.countListByStore(paramsMap);
            page.setTotal(count);
            page.setRecords(resList);
        }
        return page;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 商户支付方式统计列表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> countListByWayCode(PayOrder payOrder, JSONObject paramJSON) {
        Page<PayOrderCount> page = new Page<>();
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        paramsMap.put("storeIdList", storeIdList);

        Long count = payOrderMapper.countByWayCode(paramsMap);
        if (count != 0) {
            List<PayOrderCount> resList = payOrderMapper.countListByWayCode(paramsMap);
            page.setTotal(count);
            page.setRecords(resList);
        }
        return page;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 商户支付类型统计列表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> countListByWayCodeType(PayOrder payOrder, JSONObject paramJSON) {
        Page<PayOrderCount> page = new Page<>();
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        paramsMap.put("storeIdList", storeIdList);

        Long count = payOrderMapper.countByWayCodeType(paramsMap);
        if (count != 0) {
            List<PayOrderCount> resList = payOrderMapper.countListByWayCodeType(paramsMap);
            // 写入支付类型名称
            for (PayOrderCount orderCount : resList) {
                orderCount.setName(CS.PAY_WAY_CODE_TYPE_MAP.get(orderCount.getWayType()));
            }
            page.setTotal(count);
            page.setRecords(resList);
        }
        return page;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 交易报表列表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> countListByTransaction(PayOrder payOrder, JSONObject paramJSON, List<String> agentSubList) {
        Page<PayOrderCount> page = new Page<>();
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        paramsMap.remove("createTimeStart");
        paramsMap.remove("createTimeEnd");

        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        paramsMap.put("storeIdList", storeIdList);

        // 时间范围
        String dateRange = paramJSON.getString("queryDateRange");
        // 时间范围类型 日 月 年
        String queryDateType = paramJSON.getString("queryDateType");
        if (StringUtils.isNotEmpty(dateRange)) {
            Date[] queryDateRangeArray = DateKit.getQueryDateRange(dateRange);

            String createdStart = DateUtil.format(queryDateRangeArray[0], DatePattern.NORM_DATE_PATTERN);
            String createdEnd = DateUtil.format(queryDateRangeArray[1], DatePattern.NORM_DATE_PATTERN);

            if (StrUtil.isNotBlank(createdStart)) {
                paramsMap.put("startDayTime", createdStart);
            }
            if (StrUtil.isNotBlank(createdEnd)) {
                paramsMap.put("endDayTime", createdEnd);
            }
        }else {
            Date today = new Date();
            DateTime dateTime = DateUtil.offsetDay(today, -30);
            String endDayTime = DateUtil.format(today, DatePattern.NORM_DATE_PATTERN);
            String startDayTime = DateUtil.format(dateTime, DatePattern.NORM_DATE_PATTERN);
            paramsMap.put("startDayTime", startDayTime);
            paramsMap.put("endDayTime", endDayTime);
        }

        String dateFormat = "'%Y-%m-%d'";
        if ("month".equals(queryDateType)) {
            dateFormat = "'%Y-%m'";
        }else if ("year".equals(queryDateType)) {
            dateFormat = "'%Y'";
        }
        // 时间格式
        paramsMap.put("dateFormat", dateFormat);
        Long count = payOrderMapper.countByTransaction(paramsMap, agentSubList);
        if (count != 0) {
            List<PayOrderCount> resList = payOrderMapper.countListByTransaction(paramsMap, agentSubList);
            page.setTotal(count);
            page.setRecords(resList);
        }
        return page;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 服务商统计列表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> countListByAgent(PayOrder payOrder, JSONObject paramJSON, List<String> agentSubList) {
        Page<PayOrderCount> page = new Page<>();
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        Long count = payOrderMapper.countByAgent(paramsMap, null);
        if (count != 0) {
            List<PayOrderCount> resList = payOrderMapper.countListByAgent(paramsMap, agentSubList);
            page.setTotal(count);
            page.setRecords(resList);
        }
        return page;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 服务商统计列表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> countListByIsv(PayOrder payOrder, JSONObject paramJSON) {
        Page<PayOrderCount> page = new Page<>();
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        Long count = payOrderMapper.countByIsv(paramsMap);
        if (count != 0) {
            List<PayOrderCount> resList = payOrderMapper.countListByIsv(paramsMap);
            page.setTotal(count);
            page.setRecords(resList);
        }
        return page;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 通道列表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> countListByChannel(PayOrder payOrder, JSONObject paramJSON) {
        Page<PayOrderCount> page = new Page<>();
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        Long count = payOrderMapper.countByChannel(paramsMap);
        if (count != 0) {
            List<PayOrderCount> resList = payOrderMapper.countListByChannel(paramsMap);
            page.setTotal(count);
            page.setRecords(resList);
        }
        return page;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 设备统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> countListByDevice(PayOrder payOrder, JSONObject paramJSON, List<String> agentSubList) {
        Page<PayOrderCount> page = new Page<>();
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);

        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        paramsMap.put("storeIdList", storeIdList);

        Long count = payOrderMapper.countByDevice(paramsMap, agentSubList);
        if (count != 0) {
            List<PayOrderCount> resList = payOrderMapper.countListByDevice(paramsMap, agentSubList);
            page.setTotal(count);
            page.setRecords(resList);
        }
        return page;
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 商户统计总计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount totalByMch(PayOrder payOrder, JSONObject paramJSON, List<String> agentSubList) {
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        return payOrderMapper.totalByMch(paramsMap, agentSubList);
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 商户门店统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount totalByStore(PayOrder payOrder, JSONObject paramJSON) {
        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        paramsMap.put("storeIdList", storeIdList);
        return payOrderMapper.totalByStore(paramsMap);
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 商户支付方式统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount totalByWayCode(PayOrder payOrder, JSONObject paramJSON) {
        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        paramsMap.put("storeIdList", storeIdList);
        return payOrderMapper.totalByWayCode(paramsMap);
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 商户支付类型统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount totalByWayCodeType(PayOrder payOrder, JSONObject paramJSON) {
        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        paramsMap.put("storeIdList", storeIdList);
        return payOrderMapper.totalByWayCodeType(paramsMap);
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 报表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount totalByTransaction(PayOrder payOrder, JSONObject paramJSON, List<String> agentSubList) {
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        paramsMap.remove("createTimeStart");
        paramsMap.remove("createTimeEnd");

        // 门店ID列表
        List<String> storeIdList = getStoreIdList(paramJSON);
        paramsMap.put("storeIdList", storeIdList);
        // 时间范围
        String dateRange = paramJSON.getString("queryDateRange");
        // 时间范围类型 日 月 年
        String queryDateType = paramJSON.getString("queryDateType");
        if (StringUtils.isNotEmpty(dateRange)) {
            Date[] queryDateRangeArray = DateKit.getQueryDateRange(dateRange);

            String createdStart = DateUtil.format(queryDateRangeArray[0], DatePattern.NORM_DATE_PATTERN);
            String createdEnd = DateUtil.format(queryDateRangeArray[1], DatePattern.NORM_DATE_PATTERN);

            if (StrUtil.isNotBlank(createdStart)) {
                paramsMap.put("startDayTime", createdStart);
            }
            if (StrUtil.isNotBlank(createdEnd)) {
                paramsMap.put("endDayTime", createdEnd);
            }
        }else {
            Date today = new Date();
            DateTime dateTime = DateUtil.offsetDay(today, -30);
            String endDayTime = DateUtil.format(today, DatePattern.NORM_DATE_PATTERN);
            String startDayTime = DateUtil.format(dateTime, DatePattern.NORM_DATE_PATTERN);
            paramsMap.put("startDayTime", startDayTime);
            paramsMap.put("endDayTime", endDayTime);
        }

        String dateFormat = "'%Y-%m-%d'";
        if ("month".equals(queryDateType)) {
            dateFormat = "'%Y-%m'";
        }else if ("year".equals(queryDateType)) {
            dateFormat = "'%Y'";
        }
        // 时间格式
        paramsMap.put("dateFormat", dateFormat);
        return payOrderMapper.totalByTransaction(paramsMap, agentSubList);
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 服务商
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount totalByAgent(PayOrder payOrder, JSONObject paramJSON, List<String> agentSubList) {
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        return payOrderMapper.totalByAgent(paramsMap, agentSubList);
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 服务商
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount totalByIsv(PayOrder payOrder, JSONObject paramJSON) {
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        return payOrderMapper.totalByIsv(paramsMap);
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 通道
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount totalByChannel(PayOrder payOrder, JSONObject paramJSON) {
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        return payOrderMapper.totalByChannel(paramsMap);
    }

    /**
     * @author: xiaoyu
     * @date: 2022/5/24 9:31
     * @describe: 设备
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount totalByDevice(PayOrder payOrder, JSONObject paramJSON, List<String> agentSubList) {
        HashMap<String, Object> paramsMap = (HashMap<String, Object>) getParamsMap(payOrder, paramJSON);
        return payOrderMapper.totalByDevice(paramsMap, agentSubList);
    }


    /**
     * @author: xiaoyu
     * @date: 2022/2/10 17:41
     * @describe: 查询参数map
     */
    public Map getParamsMap(PayOrder payOrder, JSONObject paramJSON) {
        HashMap<String, Object> paramsMap = new HashMap<>();

        String dateRange = paramJSON.getString("queryDateRange");

        if (!StringUtils.isEmpty(dateRange)) {
            // 获取查询时间请求参数  [开始时间,  结束时间]
            Date[] queryDateRangeArray = DateKit.getQueryDateRange(dateRange);

            String createdStart = DateUtil.formatDateTime(queryDateRangeArray[0]);
            String createdEnd = DateUtil.formatDateTime(queryDateRangeArray[1]);

            if (StrUtil.isNotBlank(createdStart)) {
                paramsMap.put("createTimeStart", createdStart);
            }
            if (StrUtil.isNotBlank(createdEnd)) {
                paramsMap.put("createTimeEnd", createdEnd);
            }
        }
        int pageNumber = paramJSON.getIntValue("pageNumber");
        int pageSize = paramJSON.getIntValue("pageSize");
        if (pageNumber != 0) {
            paramsMap.put("pageNumber", (pageNumber - 1) * pageSize);
        }
        if (pageSize != 0) {
            paramsMap.put("pageSize", pageSize);
        }
        // 排序类型
        MutablePair<Boolean, String> sortInfo = getSortInfo(paramJSON);
        if (sortInfo == null) {
            paramsMap.put("orderType", "round DESC");
        }else {
            paramsMap.put("orderType", sortInfo.right + (sortInfo.left?" ASC":" DESC"));
        }

        // 三合一订单
        if (paramJSON != null && StringUtils.isNotEmpty(paramJSON.getString("unionOrderId"))) {
            paramsMap.put("unionOrderId", paramJSON.getString("unionOrderId"));
        }
        if (payOrder.getState() != null) {
            paramsMap.put("state", payOrder.getState());
        }
        if (payOrder.getRefundState() != null) {
            paramsMap.put("refundState", payOrder.getRefundState());
        }
        if (StrUtil.isNotBlank(payOrder.getMchNo())) {
            paramsMap.put("mchNo", payOrder.getMchNo());
        }
        if (StrUtil.isNotBlank(payOrder.getMchName())) {
            paramsMap.put("mchName", payOrder.getMchName());
        }
        if (StrUtil.isNotBlank(payOrder.getAgentNo())) {
            paramsMap.put("agentNo", payOrder.getAgentNo());
        }
        if (StrUtil.isNotBlank(paramJSON.getString("agentName"))) {
            paramsMap.put("agentName", paramJSON.getString("agentName"));
        }
        if (StrUtil.isNotBlank(payOrder.getTopAgentNo())) {
            paramsMap.put("topAgentNo", payOrder.getTopAgentNo());
        }
        if (StrUtil.isNotBlank(payOrder.getIsvNo())) {
            paramsMap.put("isvNo", payOrder.getIsvNo());
        }
        if (StrUtil.isNotBlank(payOrder.getAppId())) {
            paramsMap.put("appId", payOrder.getAppId());
        }
        if (StrUtil.isNotBlank(payOrder.getWayCode())) {
            paramsMap.put("wayCode", payOrder.getWayCode());
        }
        if (StrUtil.isNotBlank(payOrder.getWayCodeType())) {
            paramsMap.put("wayCodeType", payOrder.getWayCodeType());
        }
        if (payOrder.getNotifyState() != null) {
            paramsMap.put("notifyState", payOrder.getNotifyState());
        }
        if (payOrder.getDivisionState() != null) {
            paramsMap.put("divisionState", payOrder.getDivisionState());
        }
        if (payOrder.getStoreId() != null) {
            paramsMap.put("storeId", payOrder.getStoreId());
        }
        if (StrUtil.isNotBlank(payOrder.getIfCode())) {
            paramsMap.put("ifCode", payOrder.getIfCode());
        }
        if (StrUtil.isNotBlank(paramJSON.getString("ifName"))) {
            paramsMap.put("ifName", paramJSON.getString("ifName"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("wayType"))) {
            paramsMap.put("wayType", paramJSON.getString("wayType"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("deviceType"))) {
            paramsMap.put("deviceType", paramJSON.getString("deviceType"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("deviceNo"))) {
            paramsMap.put("deviceNo", paramJSON.getString("deviceNo"));
        }
        return paramsMap;
    }

    public BigDecimal totalAmount(String agentNo, Long sysUserId, String createdStart, String createdEnd) {

        QueryWrapper<PayOrder> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(StringUtils.isNotBlank(agentNo), PayOrder::getAgentNo, agentNo); // 服务商号
        wrapper.lambda().eq(sysUserId != null, PayOrder::getEpUserId, sysUserId);
        wrapper.lambda().ge(StringUtils.isNotBlank(createdStart), PayOrder::getCreatedAt, createdStart); // 开始时间
        wrapper.lambda().le(StringUtils.isNotBlank(createdEnd), PayOrder::getCreatedAt, createdEnd); // 结束时间

        wrapper.select("ifnull(sum(amount), 0) as totalAmount");
        Map<String, Object> map = this.getMap(wrapper);

        return (BigDecimal) map.get("totalAmount");
    }

    /** 获取排序字段 MutablePair<是否正序， 排序字段> **/
    protected MutablePair<Boolean, String> getSortInfo(JSONObject paramJSON) {

        String sortField = paramJSON.getString("sortField");
        String sortOrderFlag = paramJSON.getString("sortOrder");
        if(StringUtils.isAllEmpty(sortField, sortField)){
            return null;
        }

        return MutablePair.of("ascend".equalsIgnoreCase(sortOrderFlag), sortField);
    }

    public PayOrder getOneByChannelOrderId(String ifCode, String channelOrderId) {
        List<PayOrder> list = list(PayOrder.gw()
                .eq(PayOrder::getChannelOrderNo, channelOrderId)
                .eq(PayOrder::getIfCode, ifCode)
        );
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    private List<String> getStoreIdList(JSONObject paramJSON) {
        List<String> storeIdList = null;
        String string = paramJSON.getString("storeIdList");
        if (StringUtils.isNotEmpty(string)) {
            string = string.replace("[", "[\"").replace("]", "\"]");
            storeIdList = JSONObject.parseObject(string, List.class);
        }
       return storeIdList;
    }

    public PayOrder selectOneByPlatformMchOrderNo(String platformMchOrderNo) {
        List<PayOrder> payOrderList = this.list(PayOrder.gw().eq(PayOrder::getPlatformMchOrderNo, platformMchOrderNo));
        if (CollUtil.isEmpty(payOrderList)) {
            throw new BizException("订单不存在");
        }
        if (payOrderList.size() > 1) {
            throw new BizException("订单多于两条");
        }
        return payOrderList.get(0);
    }

    /**
     * 订单状态刷新
     * @param payOrderId
     */
    public PayOrder refreshOrder(String payOrderId) {

        return null;
//
//        //查询支付接口是否存在
//        IPayOrderQueryService queryService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(payOrder.getIfCode()) + "PayOrderQueryService", IPayOrderQueryService.class);
//        // 支付通道接口实现不存在
//        if(queryService == null){
//            throw new BizException("未获取到接口");
//        }
//        //查询出商户应用的配置信息
//        MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfo(payOrder.getMchNo(), payOrder.getAppId());
//        try {
//            ChannelRetMsg channelRetMsg = queryService.query(payOrder, mchAppConfigContext);
//            log.info("补单[{}]查询结果为：{}", payOrderId, channelRetMsg);
//            // 查询成功
//            if(channelRetMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_SUCCESS) {
//                if (updateIng2Success(payOrderId, channelRetMsg.getChannelOrderId(), channelRetMsg.getChannelUserId(),
//                        channelRetMsg.getPlatformOrderNo(), channelRetMsg.getPlatformMchOrderNo())) {
//                    //订单支付成功，其他业务逻辑
//                    payOrderProcessService.confirmSuccess(payOrder, mchAppConfigContext);
//                }
//            }else if(channelRetMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_FAIL){  //确认失败
//                //1. 更新支付订单表为失败状态
//                updateIng2Fail(payOrderId, channelRetMsg.getChannelOrderId(), channelRetMsg.getChannelUserId(), channelRetMsg.getChannelErrCode(), channelRetMsg.getChannelErrMsg());
//            }else{
//                throw new BizException("渠道返回订单状态一致，无需处理");
//            }
//        } catch (Exception e) {
//            throw new BizException("接口处理异常");
//        }
    }

    public List<PayOrder> listMchSuccTradeData( String settleType, Date startDate, Date endDate) {
        return baseMapper.listMchSuccTradeData(settleType,startDate,endDate);
    }

    /**
     * 更新扩展金额
     * @param payOrderId
     * @param extDivAmt
     * @return
     */
    public int updateExtDivAmt(String payOrderId, long extDivAmt) {
        return baseMapper.updateExtDivAmt(payOrderId,extDivAmt);
    }

    public void updateDivState(String payOrderId, byte divState) {
        baseMapper.updateDivState(payOrderId,divState);
    }

    /**
     * 更新营销活动金额
     * @param payOrderId
     * @param amount
     */
    public void updateMarketAmt(String payOrderId,Long amount) {
        baseMapper.updateMarketAmt(payOrderId,amount);
    }

    /**
     * 根据账单上的流水号 查询订单信息
     * @param cxMchOrderNo
     * @return
     */
    public PayOrder getPlatformMchOrderNo(String cxMchOrderNo) {
        return baseMapper.getPlatformMchOrderNo(cxMchOrderNo);
    }

    //退款总金额
    public Long getNumberData(PayOrder payOrder, Date startDate, Date endDate) {
        Long totalRefundAmount = 0L;
        List<RefundOrder> refundOrderList = refundOrderService.list(RefundOrder.gw().eq(RefundOrder::getMchExtNo, payOrder.getMchExtNo()).eq(RefundOrder::getExtParam,RefundOrder.REFUND_ACCOUNT_DEFAULT)
                .eq(RefundOrder::getState,2)
                .between(RefundOrder::getCreatedAt, startDate, endDate));
        if (!refundOrderList.isEmpty()){
            for (RefundOrder refundOrder : refundOrderList) {
                totalRefundAmount += refundOrder.getRefundAmount();
            }
        }
        return totalRefundAmount;
    }

    /**
     * 获取订单性情
     * @param payOrderId
     * @return
     */
    public PayOrder getDetails(String payOrderId){
        PayOrder payOrder = payOrderMapper.selectById(payOrderId);
        if (payOrder == null) {
            throw new BizException("该记录不存在！");
        }
        //处理收单手续费字符串问题
        try {
            if (StringUtils.isNotEmpty(payOrder.getMchFeeRate())){
                payOrder.setMchFeeRateNum("0");
                String mchFeeRate = payOrder.getMchFeeRate();
                if (mchFeeRate.contains("单笔费率")){
                    int colonIndex = mchFeeRate.indexOf("：");
                    int percentIndex = mchFeeRate.indexOf("%");
                    if (colonIndex != -1 && percentIndex != -1) {
                        String extractedData = mchFeeRate.substring(colonIndex + 1, percentIndex + 1).trim();
                        payOrder.setMchFeeRateNum(extractedData);
                    }
                }
            }else {
                payOrder.setMchFeeRateNum("0");
            }
        }catch (Exception e){
            payOrder.setMchFeeRateNum("0");
        }

        return payOrder;
    }

    /**
     * 路由数据统计
     * @param page
     * @param entity
     * @return
     */
    public IPage<PayOrderCount> routePageList(Page<PayOrderCount> page, PayOrderCount entity) {
        Date[] dateRange = entity.buildQueryDateRange();
        return baseMapper.routePageList(page,entity,dateRange);
    }

    /**
     * 路由数据统计
     * @param entity
     * @return
     */
    public PayOrderCount routeCount(PayOrderCount entity) {
        Date[] dateRange = entity.buildQueryDateRange();
        return baseMapper.routeCount(entity,dateRange);
    }
}
