package com.jeequan.jeepay.service.impl;

import cn.hutool.core.collection.CollUtil;
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.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.db.config.dynamic.DataSourceSwitch;
import com.jeequan.jeepay.db.config.dynamic.DynamicDataSource;
import com.jeequan.jeepay.db.entity.StatsPayWay;
import com.jeequan.jeepay.service.mapper.StatsPayWayMapper;
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.util.*;

/**
 * <p>
 * 支付方式数据统计表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2022-12-20
 */
@Service
public class StatsPayWayService extends ServiceImpl<StatsPayWayMapper, StatsPayWay> {

    @Autowired private StatsTradeService statsTradeService;

    public void handleStats(Date beginDate, Date endDate) {
        handleStats(beginDate, endDate, null);
    }

    public void handleStats(Date beginDate, Date endDate, String mchNo) {
        // 统计beginDate数据
        List<StatsPayWay> statsPayWays = getStatsData(beginDate, endDate, mchNo);

        // 入库前清空数据，防止重复
        if (CollUtil.isNotEmpty(statsPayWays)) {
            delStats(beginDate, mchNo);

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

    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    private List<StatsPayWay> 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<StatsPayWay> statsPayWays = baseMapper.selectPayWayStats(params);
        statsPayWays.forEach(i -> {
            i.setState(CS.YES);
            i.setStatsDate(beginDate);
        });

        return statsPayWays;
    }

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

        this.remove(queryWrapper);
    }

    /**
     * 支付方式统计页 -- 数据统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount selectTotalByPayWay(JSONObject paramJSON) {
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = statsTradeService.parseQueryDate(paramJSON.getString("queryDateRange"));

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

        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.selectTodayStats4WayCode(params);
        }

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

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

            return otherData;
        }

        return todayData;
    }

    /**
     * 支付方式统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> selectPayWayStatsList(JSONObject paramJSON) {
        List<PayOrderCount> resList = new ArrayList<>();
        Page<PayOrderCount> page = new Page<>(paramJSON.getIntValue("pageNumber"), paramJSON.getIntValue("pageSize"));

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

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

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

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

            resList = baseMapper.selectTodayTradeStatsList(params);
        }

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

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

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

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

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

        page.setRecords(resList);
        return page;
    }

    /**
     * 支付方式类型统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> selectWayCodeTypeStatsList(JSONObject paramJSON) {
        List<PayOrderCount> resList = new ArrayList<>();
        Page<PayOrderCount> page = new Page<>(paramJSON.getIntValue("pageNumber"), paramJSON.getIntValue("pageSize"));
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = statsTradeService.parseQueryDate(paramJSON.getString("queryDateRange"));

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

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

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

            resList = baseMapper.selectWayCodeTypeTodayTradeStatsList(params);
        }

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

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

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

            List<PayOrderCount> otherDateList = baseMapper.selectWayCodeTypeStatsList(params);
            if (mutablePair.left) {
                // 包含今天，合并数据
                resList.forEach(todayData -> {
                    String wayType = todayData.getWayType();
                    otherDateList.forEach(otherData -> {
                        if (StringUtils.isNotEmpty(otherData.getWayType()) && wayType.equals(otherData.getWayType())) {
                            statsTradeService.addData(todayData, otherData);
                        }
                    });
                });
            }else {
                resList = otherDateList;
            }
        }

        // 写入支付类型名称
        for (PayOrderCount orderCount : resList) {
            orderCount.setName(CS.PAY_WAY_CODE_TYPE_MAP.get(orderCount.getWayType()));
        }

        page.setRecords(resList);
        return page;
    }

    /**
     * 支付方式统计页 -- 数据统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public PayOrderCount selectTotalByWayCodeType(JSONObject paramJSON) {
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = statsTradeService.parseQueryDate(paramJSON.getString("queryDateRange"));

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

        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.selectTodayStats4WayCodeType(params);
        }

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

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

            return otherData;
        }

        return todayData;
    }

    /**
     * 查询参数map
     */
    public Map<String, Object> getParamsMap(JSONObject paramJSON, MutablePair<Boolean, Boolean> mutablePair) {
        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]);
            }
        }

        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 = statsTradeService.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("wayCode"))) {
            paramsMap.put("wayCode", paramJSON.getString("wayCode"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("wayName"))) {
            paramsMap.put("wayName", paramJSON.getString("wayName"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("wayType"))) {
            paramsMap.put("wayType", paramJSON.getString("wayType"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("mchNo"))) {
            paramsMap.put("mchNo", paramJSON.getString("mchNo"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("storeIdList"))) {
            List<String> storeIdList = JSON.parseObject(paramJSON.getString("storeIdList"), List.class);
            paramsMap.put("storeIdList", storeIdList);
        }
        return paramsMap;
    }


}
