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.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
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.utils.DateKit;
import com.jeequan.jeepay.core.utils.JsonKit;
import com.jeequan.jeepay.db.config.dynamic.DataSourceSwitch;
import com.jeequan.jeepay.db.config.dynamic.DynamicDataSource;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.db.entity.StatsTrade;
import com.jeequan.jeepay.service.mapper.StatsTradeMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 交易数据统计表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2022-12-20
 */
@Service
public class StatsTradeService extends ServiceImpl<StatsTradeMapper, StatsTrade> {

    /**
     * 统计数据入库
     */
    public void handleStats(Date beginDate, Date endDate) {
        handleStats(beginDate, endDate, null);
    }

    /**
     * 统计数据入库
     */
    public void handleStats(Date beginDate, Date endDate, String mchNo) {
        // 统计beginDate数据
        List<StatsTrade> statsTrades = getStatsData(beginDate, endDate, mchNo);
        if (CollUtil.isEmpty(statsTrades)) {
            return;
        }

        // 入库前清空数据，防止重复，  统计条件和删除条件一致
        delStats(beginDate, mchNo);

        boolean result = this.saveBatch(statsTrades);
        if (!result) {
            throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_CREATE);
        }
    }

    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    private List<StatsTrade> getStatsData(Date beginDate, Date endDate, String mchNo) {
        Map<String, Object> params = new HashMap<>();
        params.put("beginDate", beginDate);
        params.put("endDate", endDate);

        if (StringUtils.isNotBlank(mchNo)) {
            params.put("mchNo", mchNo);
        }

        // 查询数据集合
        List<StatsTrade> statsTrades = baseMapper.selectTradeStats(params);
        if (CollUtil.isEmpty(statsTrades)) {
            return null;
        }

        statsTrades.forEach(statsTrade -> {
            statsTrade.setState(CS.YES);
            statsTrade.setStatsDate(beginDate);
        });

        return statsTrades;
    }

    private void delStats(Date beginDate, String mchNo) {
        LambdaQueryWrapper<StatsTrade> queryWrapper = StatsTrade.gw().eq(StatsTrade::getStatsDate, DateUtil.formatDate(beginDate));
        queryWrapper.eq(StringUtils.isNotBlank(mchNo), StatsTrade::getMchNo, mchNo);

        this.remove(queryWrapper);
    }

    /**
     * 门店统计页 -- 数据统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount selectTotalByStore(JSONObject paramJSON, List<String> agentSubList) {
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, agentSubList);

        PayOrderCount todayData = new PayOrderCount();

        // 包含今天，查询今天数据
        if (mutablePair.left) {
            DateTime now = DateUtil.date();
            params.put("beginDate", DateUtil.beginOfDay(now));
            params.put("endDate", DateUtil.endOfDay(now));
            todayData = baseMapper.selectTodayStats4Store(params);
        }

        // 包含除今天外的其他日期
        if (mutablePair.right) {
            PayOrderCount otherData = baseMapper.selectStats4Store(params);

            if (mutablePair.left) {
                // 包含今天，合并数据
                return addTotalStatsData(todayData, otherData);
            }

            return otherData;
        }

        return todayData;
    }

    /**
     * 门店统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> selectStoreStatsList(JSONObject paramJSON) {
        List<PayOrderCount> resList = new ArrayList<>();
        Page<PayOrderCount> page = new Page<>(paramJSON.getIntValue("pageNumber"), paramJSON.getIntValue("pageSize"));
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, null);
        if (params != null && params.get("orderType") != null) {
            String orderType = params.get("orderType") + ", createdAt DESC";
            params.put("orderType", orderType);
        }

        page.setTotal(baseMapper.selectStoreTradeStatsCount(params));

        // 包含今天，查询今天数据
        if (mutablePair.left) {
            DateTime now = DateUtil.date();
            params.put("beginDate", DateUtil.beginOfDay(now));
            params.put("endDate", DateUtil.endOfDay(now));

            resList = baseMapper.selectStoreTodayTradeStatsList(params);
        }

        // 包含除今天外的其他日期
        if (mutablePair.right) {
            // 包含今天，查询数据需去掉分页，加上今天数据中查询的商户号集合
            if (mutablePair.left) {
                params.remove("pageNumber");
                params.remove("pageSize");

                // 查询今天数据为空，那也不会有历史数据，直接返回
                if (CollUtil.isEmpty(resList)) {
                    page.setRecords(resList);
                    return page;
                }

                List<String> storeIdList = new ArrayList<>();
                resList.forEach(i -> {
                    storeIdList.add(i.getStoreId());
                });
                params.put("storeIdList", storeIdList);
            }

            List<PayOrderCount> otherDateList = baseMapper.selectStoreStatsList(params);
            if (mutablePair.left) {
                // 包含今天，合并数据
                resList.forEach(todayData -> {
                    String storeId = todayData.getStoreId();

                    otherDateList.forEach(otherData -> {
                        if (StringUtils.isNotEmpty(otherData.getStoreId()) && storeId.equals(otherData.getStoreId())) {
                            addData(todayData, otherData);
                        }
                    });
                });
            }else {
                resList = otherDateList;
            }
        }

        page.setRecords(resList);
        return page;
    }

    /**
     * 商户统计页 -- 数据统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount selectTotalByMch(JSONObject paramJSON, List<String> agentSubList) {
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, agentSubList);

        PayOrderCount todayData = new PayOrderCount();

        // 包含今天，查询今天数据
        if (mutablePair.left) {
            DateTime now = DateUtil.date();
            params.put("beginDate", DateUtil.beginOfDay(now));
            params.put("endDate", DateUtil.endOfDay(now));
            todayData = baseMapper.selectTodayStats4Mch(params);
        }

        // 包含除今天外的其他日期
        if (mutablePair.right) {
            PayOrderCount otherData = baseMapper.selectStats4Mch(params);

            if (mutablePair.left) {
                // 包含今天，合并数据
                return addTotalStatsData(todayData, otherData);
            }

            return otherData;
        }

        return todayData;
    }


    /**
     * 商户统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> selectMchStatsList(JSONObject paramJSON, List<String> agentSubList) {

        List<PayOrderCount> resList = new ArrayList<>();
        Page<PayOrderCount> page = new Page<>(paramJSON.getIntValue("pageNumber"), paramJSON.getIntValue("pageSize"));
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));
        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, agentSubList);
        if (params != null && params.get("orderType") != null) {
            String orderType = params.get("orderType") + ", createdAt DESC";
            params.put("orderType", orderType);
        }
        page.setTotal(baseMapper.selectMchTodayTradeStatsCount(params));

        // 包含今天，查询今天数据
        if (mutablePair.left) {
            DateTime now = DateUtil.date();
            params.put("beginDate", DateUtil.beginOfDay(now));
            params.put("endDate", DateUtil.endOfDay(now));

            resList = baseMapper.selectMchTodayTradeStatsList(params);
        }

        // 包含除今天外的其他日期
        if (mutablePair.right) {
            // 包含今天，查询数据需去掉分页，加上今天数据中查询的商户号集合
            if (mutablePair.left) {
                params.remove("pageNumber");
                params.remove("pageSize");

                // 查询今天数据为空，那也不会有历史数据，直接返回
                if (CollUtil.isEmpty(resList)) {
                    page.setRecords(resList);
                    return page;
                }

                List<String> mchNoList = new ArrayList<>();
                resList.forEach(i -> {
                    mchNoList.add(i.getMchNo());
                });
                params.put("mchNoList", mchNoList);
            }

            List<PayOrderCount> otherDateList = baseMapper.selectMchStatsList(params);
            if (mutablePair.left) {
                // 包含今天，合并数据
                resList.forEach(todayData -> {
                    String mchNo = todayData.getMchNo();

                    otherDateList.forEach(otherData -> {
                        if (mchNo.equals(otherData.getMchNo())) {
                            addData(todayData, otherData);
                        }
                    });
                });
            }else {
                resList = otherDateList;
            }
        }

        page.setRecords(resList);
        return page;
    }

    /**
     * 服务商统计页 -- 数据统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount selectTotalByAgent(JSONObject paramJSON, List<String> agentSubList) {
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, agentSubList);

        PayOrderCount todayData = new PayOrderCount();

        // 包含今天，查询今天数据
        if (mutablePair.left) {
            DateTime now = DateUtil.date();
            params.put("beginDate", DateUtil.beginOfDay(now));
            params.put("endDate", DateUtil.endOfDay(now));
            todayData = baseMapper.selectTodayStats4Agent(params);
        }

        // 包含除今天外的其他日期
        if (mutablePair.right) {
            PayOrderCount otherData = baseMapper.selectStats4Agent(params);

            if (mutablePair.left) {
                // 包含今天，合并数据
                return addTotalStatsData(todayData, otherData);
            }

            return otherData;
        }

        return todayData;
    }

    /**
     * 服务商统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> selectAgentStatsList(JSONObject paramJSON, List<String> agentSubList) {
        List<PayOrderCount> resList = new ArrayList<>();
        Page<PayOrderCount> page = new Page<>(paramJSON.getIntValue("pageNumber"), paramJSON.getIntValue("pageSize"));

        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, agentSubList);
        if (params != null && params.get("orderType") != null) {
            String orderType = ((String) params.get("orderType"));
            params.put("orderType", orderType);
        }

        page.setTotal(baseMapper.selectAgentTradeStatsCount(params));

        // 包含今天，查询今天数据
        if (mutablePair.left) {
            DateTime now = DateUtil.date();
            params.put("beginDate", DateUtil.beginOfDay(now));
            params.put("endDate", DateUtil.endOfDay(now));

            resList = baseMapper.selectAgentTodayTradeStatsList(params);
        }

        // 包含除今天外的其他日期
        if (mutablePair.right) {
            // 包含今天，查询数据需去掉分页，加上今天数据中查询的商户号集合
            if (mutablePair.left && CollUtil.isNotEmpty(resList)) {
                params.remove("pageNumber");
                params.remove("pageSize");

                List<String> agentNoList = new ArrayList<>();
                resList.forEach(i -> agentNoList.add(i.getAgentNo()));
                params.put("agentNoList", agentNoList);
            }

            List<PayOrderCount> otherDateList = baseMapper.selectAgentStatsList(params);
            if (mutablePair.left) {
                // 包含今天，合并数据
                resList.forEach(todayData -> {
                    String agentNo = todayData.getAgentNo();
                    otherDateList.forEach(otherData -> {
                        if (agentNo.equals(otherData.getAgentNo())) {
                            addData(todayData, otherData);
                        }
                    });
                });
            }else {
                resList = otherDateList;
            }
        }

        page.setRecords(resList);
        return page;
    }

    /**
     * 服务商统计页 -- 数据统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount selectTotalByIsv(JSONObject paramJSON) {
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, null);
        PayOrderCount todayData = new PayOrderCount();

        // 包含今天，查询今天数据
        if (mutablePair.left) {
            DateTime now = DateUtil.date();
            params.put("beginDate", DateUtil.beginOfDay(now));
            params.put("endDate", DateUtil.endOfDay(now));
            todayData = baseMapper.selectTodayStats4Isv(params);
        }

        // 包含除今天外的其他日期
        if (mutablePair.right) {
            PayOrderCount otherData = baseMapper.selectStats4Isv(params);

            if (mutablePair.left) {
                // 包含今天，合并数据
                return addTotalStatsData(todayData, otherData);
            }

            return otherData;
        }

        return todayData;
    }

    /**
     * 服务商统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> selectIsvStatsList(JSONObject paramJSON) {
        List<PayOrderCount> resList = new ArrayList<>();
        Page<PayOrderCount> page = new Page<>(paramJSON.getIntValue("pageNumber"), paramJSON.getIntValue("pageSize"));

        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, null);
        if (params != null && params.get("orderType") != null) {
            String orderType = params.get("orderType") + ", createdAt DESC";
            params.put("orderType", orderType);
        }

        page.setTotal(baseMapper.selectIsvTradeStatsCount(params));

        // 包含今天，查询今天数据
        if (mutablePair.left) {
            DateTime now = DateUtil.date();
            params.put("beginDate", DateUtil.beginOfDay(now));
            params.put("endDate", DateUtil.endOfDay(now));

            resList = baseMapper.selectIsvTodayTradeStatsList(params);
        }

        // 包含除今天外的其他日期
        if (mutablePair.right) {
            // 包含今天，查询数据需去掉分页，加上今天数据中查询的商户号集合
            if (mutablePair.left) {
                params.remove("pageNumber");
                params.remove("pageSize");

                // 查询今天数据为空，那也不会有历史数据，直接返回
                if (CollUtil.isEmpty(resList)) {
                    page.setRecords(resList);
                    return page;
                }

                List<String> isvNoList = new ArrayList<>();
                resList.forEach(i -> isvNoList.add(i.getIsvNo()));
                params.put("isvNoList", isvNoList);
            }

            List<PayOrderCount> otherDateList = baseMapper.selectIsvStatsList(params);
            if (mutablePair.left) {
                // 包含今天，合并数据
                resList.forEach(todayData -> {
                    String isvNo = todayData.getIsvNo();
                    otherDateList.forEach(otherData -> {
                        if (isvNo.equals(otherData.getIsvNo())) {
                            addData(todayData, otherData);
                        }
                    });
                });
            }else {
                resList = otherDateList;
            }
        }

        page.setRecords(resList);
        return page;
    }

    /**
     * 首页 -- 交易统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public JSONObject payDayCount(String mchNo, List<String> agentSubList, JSONObject reqParamJSON) {
        String dateRange = reqParamJSON.getString("queryDateRange");
        String isQueryAll = (String) reqParamJSON.getOrDefault("isQueryAll", "");

        String createdStart = null;
        String createdEnd = null;

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

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

        Map<String, Object> params = new HashMap<>();
        if (createdStart != null) {
            params.put("createdStart", createdStart);
        }
        if (createdEnd != null) {
            params.put("createdEnd", createdEnd);
        }
        if (StrUtil.isNotBlank(mchNo)) {
            params.put("mchNo", mchNo);
        }
        if (CollUtil.isNotEmpty(agentSubList)) {
            params.put("agentSubList", agentSubList);
        }
        if (StrUtil.isNotBlank(reqParamJSON.getString("storeIdList"))) {
            String store = reqParamJSON.getString("storeIdList").replace("[", "[\"").replace("]", "\"]");
            List<String> storeIdList = JSON.parseObject(store, new TypeReference<List<String>>() {});
            params.put("storeIdList", storeIdList);
        }

        if ("today".equals(dateRange)) {
            return JsonKit.newJson("dayCount", baseMapper.selectTodayPayCount(params));
        }

        return JsonKit.newJson("dayCount", baseMapper.selectPayDayCount(params));
    }

    /**
     * 订单页 -- 数据统计，订单创建总笔数和总金额
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount selectSumStats(JSONObject paramJSON, List<String> subAgentList) {
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, subAgentList);
        Date[] queryDateRangeArray = DateKit.getQueryDateRange(paramJSON.getString("queryDateRange"));
        params.put("createdStart", queryDateRangeArray[0]);
        params.put("createdEnd", queryDateRangeArray[1]);

        return baseMapper.selectSumStats(params);
    }

    /**
     * 交易报表页 -- 数据统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount selectTotalByTransaction(JSONObject paramJSON, List<String> subAgentList) {
        return selectTotalByTransaction(paramJSON, subAgentList, true);
    }

    /**
     * 交易报表页 -- 数据统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount selectTotalByTransaction(JSONObject paramJSON, List<String> subAgentList, boolean containToday) {
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, subAgentList);

        // 处理默认日期
        setDefaultDate(paramJSON, params);

        // 交易报表  统计  不包含今天的数据，直接返回
        if (!containToday) {
            return baseMapper.selectStats4Transaction(params);
        }

        // 支付订单、退款订单  统计，包含今天数据
        PayOrderCount todayData = new PayOrderCount();
        // 包含今天，查询今天数据
        if (mutablePair.left) {
            DateTime now = DateUtil.date();
            params.put("beginDate", DateUtil.beginOfDay(now));
            params.put("endDate", DateUtil.endOfDay(now));
            todayData = baseMapper.selectTodayStats4Transaction(params);
        }

        // 包含除今天外的其他日期
        if (mutablePair.right) {
            PayOrderCount otherData = baseMapper.selectStats4Transaction(params);

            if (mutablePair.left) {
                // 包含今天，合并数据
                return addTotalStatsData(todayData, otherData);
            }

            return otherData;
        }

        return todayData;
    }

    /**
     * 交易报表
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> selectTransactionStatsList(PayOrder payOrder, JSONObject paramJSON, List<String> agentSubList) {
        Page<PayOrderCount> page = new Page<>();

        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, agentSubList);

        // 时间范围类型 日 月 年
        String queryDateType = paramJSON.getString("queryDateType");
        String dateFormat = "'%Y-%m-%d'";
        if ("month".equals(queryDateType)) {
            dateFormat = "'%Y-%m'";
        }else if ("year".equals(queryDateType)) {
            dateFormat = "'%Y'";
        }
        // 时间格式
        params.put("dateFormat", dateFormat);

        // 处理默认日期
        setDefaultDate(paramJSON, params);

        Long count = baseMapper.selectTransactionStatsCount(params);
        List<PayOrderCount> resList = new ArrayList<>();
        if (count != 0) {
            resList = baseMapper.selectTransactionStatsList(params);
        }
        //增加今日数据
        resList = setTodayDate(paramJSON, params, resList,queryDateType);
        page.setTotal(count);
        page.setRecords(resList);
        return page;
    }
    private  List<PayOrderCount> setTodayDate(JSONObject paramJSON, Map<String, Object> params,List<PayOrderCount> resList,String queryDateType ) {

        DateTime parse = new DateTime();
        DateTime now = DateUtil.date();
        Date beginDate = new Date();
        Date endDate = new Date();
        //解析时间
        if (StringUtils.isNotEmpty(paramJSON.getString("queryDateRange"))){
            beginDate = DateUtil.beginOfDay(now);
            endDate = DateUtil.endOfDay(now);
            params.put("beginDate", beginDate);
            params.put("endDate", endDate);
            String[] split = paramJSON.getString("queryDateRange").split("_");
            parse = DateUtil.parse(split[2], "yyyy-MM-dd HH:mm:ss");
        }
        if (StringUtils.isEmpty(queryDateType)) {
            //如果为空则默认带今日数据返回
            resList = addMap(params, resList);
        } else if ("day".equals(queryDateType)) {
            if (StringUtils.isNotEmpty(paramJSON.getString("queryDateRange"))) {
                //结束时间大于当前时间则包含当天
                if (DateUtil.compare(parse, DateUtil.beginOfDay(now)) >= 0) {
                    //把当天数据合并到返回列表
                    resList = addMap(params, resList);
                }
            } else {
                //如果为空则默认带今日数据返回
                resList = addMap(params, resList);
            }
        } else if ("month".equals(queryDateType)) {
            if (StringUtils.isNotEmpty(paramJSON.getString("queryDateRange"))){
                if (DateUtil.compare(parse, beginDate) >= 0) {
                    //结束时间大于当前时间则包含当月，则把今日数据合并到本月中
                    //获取当前年月份
                    String currentYearMonth = DateUtil.format(DateUtil.date(), "yyyy-MM");
                    addYearMonth(resList,params,currentYearMonth);
                }
            }else {
                //为空则默认把今天数据合并到本月中
                String currentYearMonth = DateUtil.format(DateUtil.date(), "yyyy-MM");
                addYearMonth(resList,params,currentYearMonth);
            }
        }else if ("year".equals(queryDateType)){
            if (StringUtils.isNotEmpty(paramJSON.getString("queryDateRange"))){
                if (DateUtil.compare(parse, beginDate) >= 0) {
                    //结束时间大于当前时间则包含当月，则把今日数据合并到本年中
                    //获取当前年月份
                    String currentYear = DateUtil.format(DateUtil.date(), "yyyy");
                    addYearMonth(resList,params,currentYear);
                }
            }else {
                //为空则默认把今天数据合并到本年中
                String currentYear = DateUtil.format(DateUtil.date(), "yyyy");
                addYearMonth(resList,params,currentYear);
            }
        }


        return resList;
    }

    public void addYearMonth(List<PayOrderCount> resList,Map<String, Object> params,String yeraOrMonth){
        resList = addMap(params, resList);
        //取出今日数据
        PayOrderCount thisToday = resList.get(0);
        //取出本月或者本年数据
        List<PayOrderCount> collect = resList.stream().filter(item -> item.getGroupDate().equals(yeraOrMonth)).collect(Collectors.toList());
        if (!collect.isEmpty()){
            PayOrderCount thisMonth = collect.get(0);
            thisMonth.setTotalSuccAmt(thisToday.getTotalSuccAmt() + thisMonth.getTotalSuccAmt());
            thisMonth.setTotalFinalAmt(thisToday.getTotalFinalAmt() + thisMonth.getTotalFinalAmt());
            thisMonth.setTotalFeeAmt(thisToday.getTotalFeeAmt() + thisMonth.getTotalFeeAmt());
            thisMonth.setTotalRefundFeeAmt(thisToday.getTotalRefundFeeAmt() + thisMonth.getTotalRefundFeeAmt());
            thisMonth.setTotalNum(thisToday.getTotalNum() + thisMonth.getTotalNum());
            thisMonth.setTotalSuccNum(thisToday.getTotalSuccNum() + thisMonth.getTotalSuccNum());
            thisMonth.setTotalRefundAmt(thisToday.getTotalRefundAmt() + thisMonth.getTotalRefundAmt());
            thisMonth.setTotalRefundNum(thisToday.getTotalRefundNum() + thisMonth.getTotalRefundNum());
            BigDecimal sumSuccessCount = BigDecimal.valueOf(thisToday.getTotalSuccNum() + thisMonth.getTotalSuccNum());
            BigDecimal sumTotalCount = BigDecimal.valueOf(thisToday.getTotalNum() + thisMonth.getTotalNum());
            if (sumTotalCount.compareTo(BigDecimal.ZERO) == 0){
                thisMonth.setSuccRate(BigDecimal.ZERO);
            }else {
                BigDecimal result = (sumSuccessCount.divide(sumTotalCount,2, RoundingMode.HALF_UP)).multiply(BigDecimal.valueOf(100L));
                thisMonth.setSuccRate(result);
            }
        }
        //合并结束后清除列表内今日数据
        resList.remove(0);
    }
    public List<PayOrderCount> addMap(Map<String, Object> params,List<PayOrderCount> resList){
        DateTime now = DateUtil.date();
        Date beginDate = DateUtil.beginOfDay(now);
        Date endDate = DateUtil.endOfDay(now);
        params.put("beginDate", beginDate);
        params.put("endDate", endDate);
        List<StatsTrade> statsTrades = baseMapper.selectTradeStats(params);
        PayOrderCount orderCount = new PayOrderCount();
        orderCount.setGroupDate(DateUtil.format(beginDate,"yyyy-MM-dd"));
        orderCount.setTotalSuccAmt(statsTrades.stream().mapToLong(StatsTrade::getSuccessAmount).sum());
        orderCount.setTotalFinalAmt(statsTrades.stream().mapToLong(StatsTrade::getFindAmt).sum());
        orderCount.setTotalEntryAmt(statsTrades.stream().mapToLong(StatsTrade::getRealAmount).sum());
        orderCount.setTotalFeeAmt(statsTrades.stream().mapToLong(StatsTrade::getFee).sum());
        orderCount.setTotalCashFee(statsTrades.stream().mapToLong(StatsTrade::getCashFee).sum());
        orderCount.setTotalRefundFeeAmt(statsTrades.stream().mapToLong(StatsTrade::getRefundFee).sum());
        orderCount.setTotalNum(statsTrades.stream().mapToLong(StatsTrade::getTotalCount).sum());
        orderCount.setTotalSuccNum(statsTrades.stream().mapToLong(StatsTrade::getSuccessCount).sum());
        orderCount.setTotalRefundAmt(statsTrades.stream().mapToLong(StatsTrade::getRefundAmount).sum());
        orderCount.setTotalRefundNum(statsTrades.stream().mapToLong(StatsTrade::getRefundCount).sum());
        BigDecimal sumSuccessCount = BigDecimal.valueOf(statsTrades.stream().mapToDouble(StatsTrade::getSuccessCount).sum());
        BigDecimal sumTotalCount = BigDecimal.valueOf(statsTrades.stream().mapToDouble(StatsTrade::getTotalCount).sum());
        if (sumTotalCount.compareTo(BigDecimal.ZERO) == 0){
            orderCount.setSuccRate(BigDecimal.ZERO);
        }else {
            BigDecimal result = (sumSuccessCount.divide(sumTotalCount,2, RoundingMode.HALF_UP)).multiply(BigDecimal.valueOf(100L));
            orderCount.setSuccRate(result);
        }
        resList.add(0,orderCount);
        return resList;
    }

    // 交易报表  设置默认时间（不包含今天），日报默认近30天，月报默认近6个月，年报默认一年
    private void setDefaultDate(JSONObject paramJSON, Map<String, Object> params) {

        // 时间为日报、月报、年报默认对应查30天数据、6个月、一年的数据
        if (StringUtils.isEmpty(paramJSON.getString("queryDateRange"))) {

            // 时间范围类型 日 月 年，day  month  year
            String queryDateType = paramJSON.getString("queryDateType");
            Date yesterday = DateUtil.yesterday();

            if ("day".equals(queryDateType)) {
                params.put("createdStart", DateUtil.format(DateUtil.offsetDay(yesterday, -29), DatePattern.NORM_DATE_PATTERN));
                params.put("createdEnd", DateUtil.format(yesterday, DatePattern.NORM_DATE_PATTERN));

            } else if ("month".equals(queryDateType)) {
                params.put("createdStart", DateUtil.format(DateUtil.offsetMonth(DateUtil.beginOfMonth(yesterday), -5), DatePattern.NORM_DATE_PATTERN));
                params.put("createdEnd", DateUtil.format(DateUtil.endOfMonth(yesterday), DatePattern.NORM_DATE_PATTERN));

            } else if ("year".equals(queryDateType)) {
                params.put("createdStart", DateUtil.format(DateUtil.beginOfYear(yesterday), DatePattern.NORM_DATE_PATTERN));
                params.put("createdEnd", DateUtil.format(DateUtil.endOfYear(yesterday), DatePattern.NORM_DATE_PATTERN));
            }
        }
    }


    /**
     * 查询参数map
     */
    public Map<String, Object> getParamsMap(JSONObject paramJSON, MutablePair<Boolean, Boolean> mutablePair, List<String> agentSubList) {
        Map<String, Object> paramsMap = new HashMap<>();

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

        // 获取除今天外的查询日期集合，作为查询数据表的参数
        if (StringUtils.isNotEmpty(dateRange)) {
            // 获取查询时间请求参数  [开始时间,  结束时间]
            Date[] queryDateRangeArray = DateKit.getQueryDateRange(dateRange);

            // 包含今天外的其他日期
            if (mutablePair.right) {
                // 今天数据排除
                if (mutablePair.left) {
                    queryDateRangeArray[1] = DateUtil.endOfDay(DateUtil.yesterday());
                }

                paramsMap.put("createdStart", queryDateRangeArray[0]);
                paramsMap.put("createdEnd", queryDateRangeArray[1]);
            }else {
                paramsMap.put("createdStart", queryDateRangeArray[0]);
                paramsMap.put("createdEnd", queryDateRangeArray[1]);
            }
        }

        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", "totalSuccAmt DESC");
        }else {
            paramsMap.put("orderType", sortInfo.right + (sortInfo.left?" ASC":" DESC"));
        }

        if (StrUtil.isNotBlank(paramJSON.getString("mchNo"))) {
            paramsMap.put("mchNo", paramJSON.getString("mchNo"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("mchName"))) {
            paramsMap.put("mchName", paramJSON.getString("mchName"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("agentNo"))) {
            paramsMap.put("agentNo", paramJSON.getString("agentNo"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("agentName"))) {
            paramsMap.put("agentName", paramJSON.getString("agentName"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("isvNo"))) {
            paramsMap.put("isvNo", paramJSON.getString("isvNo"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("isvName"))) {
            paramsMap.put("isvName", paramJSON.getString("isvName"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("storeId"))) {
            paramsMap.put("storeId", paramJSON.getString("storeId"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("storeName"))) {
            paramsMap.put("storeName", paramJSON.getString("storeName"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("mchFullName"))) {
            paramsMap.put("mchFullName", paramJSON.getString("mchFullName"));
        }
        if (CollUtil.isNotEmpty(agentSubList)) {
            paramsMap.put("agentSubList", agentSubList);
        }
        if (StrUtil.isNotBlank(paramJSON.getString("storeIdList"))) {
            List<String> storeIdList = JSONObject.parseObject(paramJSON.getString("storeIdList"), List.class);
            paramsMap.put("storeIdList", storeIdList);
        }
        return paramsMap;
    }

    /**
     * 获取排序字段 MutablePair<是否正序， 排序字段>
     */
    public 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);
    }

    /**
     * 解析日期，left: 是否包含今天  right: 是否包含除今天的其他日期
     */
    public MutablePair<Boolean, Boolean> parseQueryDate(String queryDateRange) {
        if (StringUtils.isBlank(queryDateRange)) {
            return MutablePair.of(true, true);
        }

        // 获取查询时间请求参数  [开始时间,  结束时间]
        Date[] queryDateRangeArray = DateKit.getQueryDateRange(queryDateRange);

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

        // 开始时间超过今天，无意义
        if (DateUtil.compare(queryDateRangeArray[0], DateUtil.endOfDay(now)) > 0) {
            throw new BizException("开始时间不应超过今天");
        }
        // 结束时间超过今天，默认为今天结束时间
        if (DateUtil.compare(queryDateRangeArray[1], DateUtil.endOfDay(now)) > 0) {
            queryDateRangeArray[1] = DateUtil.endOfDay(now);
        }

        // 结束时间 >= 今天开始时间，日期中包含今天
        if (DateUtil.compare(queryDateRangeArray[1], DateUtil.beginOfDay(now)) >= 0) {

            // 今天开始时间 <= 开始时间 <= 今天结束时间，只包含今天
            if (DateUtil.compare(queryDateRangeArray[0], DateUtil.endOfDay(now)) <= 0 && DateUtil.compare(queryDateRangeArray[0], DateUtil.beginOfDay(now)) >= 0) {
                return MutablePair.of(true, false);
            }

            return MutablePair.of(true, true);
        }

        return MutablePair.of(false, true);
    }

    /**
     * 数据累加
     */
    public void addData(PayOrderCount todayData, PayOrderCount otherData) {
        todayData.setTotalSuccNum((todayData.getTotalSuccNum() != null ? todayData.getTotalSuccNum():0L) + (otherData.getTotalSuccNum() != null ? otherData.getTotalSuccNum():0L));
        todayData.setTotalSuccAmt((todayData.getTotalSuccAmt() != null ? todayData.getTotalSuccAmt():0L) + (otherData.getTotalSuccAmt() != null ? otherData.getTotalSuccAmt():0L));
        todayData.setTotalFeeAmt((todayData.getTotalFeeAmt() != null ? todayData.getTotalFeeAmt():0L) + (otherData.getTotalFeeAmt() != null ? otherData.getTotalFeeAmt():0L));
        todayData.setTotalCashFee((todayData.getTotalCashFee() != null ? todayData.getTotalCashFee():0L) + (otherData.getTotalCashFee() != null ? otherData.getTotalCashFee():0L));
        todayData.setTotalRefundFeeAmt((todayData.getTotalRefundFeeAmt() != null ? todayData.getTotalRefundFeeAmt():0L) + (otherData.getTotalRefundFeeAmt() != null ? otherData.getTotalRefundFeeAmt():0L));
        todayData.setTotalNum((todayData.getTotalNum() != null ? todayData.getTotalNum():0L) + (otherData.getTotalNum() != null ? otherData.getTotalNum():0L));
        todayData.setTotalFinalAmt((todayData.getTotalFinalAmt() != null ? todayData.getTotalFinalAmt():0L) + (otherData.getTotalFinalAmt() != null ? otherData.getTotalFinalAmt():0L));
        todayData.setTotalEntryAmt((todayData.getTotalEntryAmt() != null ? todayData.getTotalEntryAmt():0L) + (otherData.getTotalEntryAmt() != null ? otherData.getTotalEntryAmt():0L));
        todayData.setTotalRefundNum((todayData.getTotalRefundNum() != null ? todayData.getTotalRefundNum():0L) + (otherData.getTotalRefundNum() != null ? otherData.getTotalRefundNum():0L));
        todayData.setTotalRefundAmt((todayData.getTotalRefundAmt() != null ? todayData.getTotalRefundAmt():0L) + (otherData.getTotalRefundAmt() != null ? otherData.getTotalRefundAmt():0L));
        if (todayData.getSuccRate().compareTo(BigDecimal.ZERO) == 0) {
            todayData.setSuccRate(otherData.getSuccRate());
        } else if (otherData.getSuccRate().compareTo(BigDecimal.ZERO) != 0) {
            todayData.setSuccRate(BigDecimal.valueOf(todayData.getTotalSuccNum()).divide(BigDecimal.valueOf(todayData.getTotalNum()),4,RoundingMode.HALF_EVEN).multiply(BigDecimal.valueOf(100)));
        }
        // 服务商佣金
        if (todayData.getAgentProfit() != null && otherData.getAgentProfit() != null) {
            todayData.setAgentProfit(BigDecimal.valueOf(todayData.getAgentProfit()).add(BigDecimal.valueOf(otherData.getAgentProfit())).longValue());
        }
    }

    /**
     * 统计总计  数据累加
     */
    public PayOrderCount addTotalStatsData(PayOrderCount todayData, PayOrderCount otherData) {

        todayData.setTotalAmt((todayData.getTotalAmt() != null ? todayData.getTotalAmt():0L) + (otherData.getTotalAmt() != null ? otherData.getTotalAmt():0L));
        todayData.setTotalNum((todayData.getTotalNum() != null ? todayData.getTotalNum():0L) + (otherData.getTotalNum() != null ? otherData.getTotalNum():0L));
        todayData.setTotalFeeAmt((todayData.getTotalFeeAmt() != null ? todayData.getTotalFeeAmt():0L) + (otherData.getTotalFeeAmt() != null ? otherData.getTotalFeeAmt():0L));
        todayData.setTotalSuccAmt((todayData.getTotalSuccAmt() != null ? todayData.getTotalSuccAmt():0L) + (otherData.getTotalSuccAmt() != null ? otherData.getTotalSuccAmt():0L));
        todayData.setTotalSuccNum((todayData.getTotalSuccNum() != null ? todayData.getTotalSuccNum():0L) + (otherData.getTotalSuccNum() != null ? otherData.getTotalSuccNum():0L));
        todayData.setTotalFailAmt((todayData.getTotalFailAmt() != null ? todayData.getTotalFailAmt():0L) + (otherData.getTotalFailAmt() != null ? otherData.getTotalFailAmt():0L));
        todayData.setTotalFailNum((todayData.getTotalFailNum() != null ? todayData.getTotalFailNum():0L) + (otherData.getTotalFailNum() != null ? otherData.getTotalFailNum():0L));
        todayData.setTotalEntryAmt((todayData.getTotalEntryAmt() != null ? todayData.getTotalEntryAmt():0L) + (otherData.getTotalEntryAmt() != null ? otherData.getTotalEntryAmt():0L));
        todayData.setTotalFinalAmt((todayData.getTotalFinalAmt() != null ? todayData.getTotalFinalAmt():0L) + (otherData.getTotalFinalAmt() != null ? otherData.getTotalFinalAmt():0L));
        todayData.setTotalDiscountAmt((todayData.getTotalDiscountAmt() != null ? todayData.getTotalDiscountAmt():0L) + (otherData.getTotalDiscountAmt() != null ? otherData.getTotalDiscountAmt():0L));
        todayData.setTotalMarketAmt((todayData.getTotalMarketAmt() != null ? todayData.getTotalMarketAmt():0L) + (otherData.getTotalMarketAmt() != null ? otherData.getTotalMarketAmt():0L));
        todayData.setTotalRefundAmt((todayData.getTotalRefundAmt() != null ? todayData.getTotalRefundAmt():0L) + (otherData.getTotalRefundAmt() != null ? otherData.getTotalRefundAmt():0L));
        todayData.setTotalRefundNum((todayData.getTotalRefundNum() != null ? todayData.getTotalRefundNum():0L) + (otherData.getTotalRefundNum() != null ? otherData.getTotalRefundNum():0L));
        todayData.setTotalExtDivAmt((todayData.getTotalExtDivAmt() != null ? todayData.getTotalExtDivAmt():0L) + (otherData.getTotalExtDivAmt() != null ? otherData.getTotalExtDivAmt():0L));
        todayData.setTotalRefundFeeAmt((todayData.getTotalRefundFeeAmt()!=null?todayData.getTotalRefundFeeAmt():0L) + (otherData.getTotalRefundFeeAmt()!=null?otherData.getTotalRefundFeeAmt():0L));
        todayData.setTotalCashFee((todayData.getTotalCashFee()!=null?todayData.getTotalCashFee():0L) + (otherData.getTotalCashFee()!=null?otherData.getTotalCashFee():0L));

        return todayData;
    }

    /**
     * 商户统计页 -- 数据统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> selectByMch(JSONObject paramJSON, List<String> agentSubList) {

        Page<PayOrderCount> page = new Page<>(paramJSON.getIntValue("pageNumber"), paramJSON.getIntValue("pageSize"));
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = parseQueryDate(paramJSON.getString("queryDateRange"));

        Map<String, Object> params = getParamsMap(paramJSON, mutablePair, agentSubList);
        //按时间查询
        Date[] queryDateRanges = DateKit.getQueryDateRange(paramJSON.getString("queryDateRange"));
        params.put("beginDate",queryDateRanges[0]);
        params.put("endDate", queryDateRanges[1]);
        List<PayOrderCount> resList = baseMapper.selectMachTradeStatsList(params);
        page.setRecords(resList);
        page.setTotal(resList.size());
        return page;
    }

    /**
     * 处理查询数据，null 返回0
     */
    private BigDecimal nullToZero(Object value) {
        if (null == value) {
            return BigDecimal.ZERO;
        }
        try {
            return (BigDecimal) value;
        }catch (Exception e) {
            return BigDecimal.ZERO;
        }
    }

}
