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.MchQrcodeCard;
import com.jeequan.jeepay.db.entity.StatsDevice;
import com.jeequan.jeepay.service.mapper.StatsDeviceMapper;
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 StatsDeviceService extends ServiceImpl<StatsDeviceMapper, StatsDevice> {

    @Autowired private StatsTradeService statsTradeService;
    @Autowired private MchQrcodeCardService qrcodeCardService;

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

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

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

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

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

        return statsDevices;
    }

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

        this.remove(queryWrapper);
    }

    /**
     * 设备统计页 -- 总计
     */
    public PayOrderCount selectTotalByDeviceNo(JSONObject paramJSON, List<String> subAgentList) {
        // 解析日期
        MutablePair<Boolean, Boolean> mutablePair = statsTradeService.parseQueryDate(paramJSON.getString("queryDateRange"));

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

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

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

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

            return otherData;
        }

        return todayData;
    }

    /**
     * 设备统计
     */
    @DataSourceSwitch(DynamicDataSource.DataSourceTypeEnum.SLAVE)
    public Page<PayOrderCount> selectStatsList(JSONObject paramJSON, List<String> agentSubList) {
        List<PayOrderCount> resList = new ArrayList<>();
        Long count = 0L;
        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, agentSubList);

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

            count = baseMapper.selectStatsCount(params);
            if (count > 0) {
                resList = baseMapper.selectTodayStatsList(params);
            }
        }

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

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

            List<PayOrderCount> otherDateList = baseMapper.selectStatsList(params);

            if (mutablePair.left && CollUtil.isNotEmpty(resList)) {

                // 今天和除今天日期  数据累加
                if (CollUtil.isNotEmpty(otherDateList)) {

                    for (PayOrderCount todayData: resList) {
                        String deviceNo = todayData.getDeviceNo();
                        String deviceType = todayData.getDeviceType();
                        String provider = todayData.getProvider();

                        for (PayOrderCount otherData: otherDateList) {
                            if (deviceNo.equals(otherData.getDeviceNo()) && deviceType.equals(otherData.getDeviceType()) && provider.equals(otherData.getProvider())) {
                                statsTradeService.addData(todayData, otherData);
                            }
                        }
                    }
                }
            }else {
                count = baseMapper.selectOtherDayStatsCount(params);
                resList = otherDateList;
            }
        }
        //区分码牌的具体类型
        if (!resList.isEmpty()){
            for (PayOrderCount orderCount : resList) {
                //如果是码牌就进行赋值
                if ("qr_code".equals(orderCount.getDeviceType())){
                    MchQrcodeCard qrcodeCard = qrcodeCardService.getById(orderCount.getDeviceNo());
                    if (qrcodeCard != null){
                        orderCount.setQrcType(qrcodeCard.getQrcType());
                    }
                }
            }
        }

        page.setTotal(count);
        page.setRecords(resList);
        return page;
    }

    /**
     * 查询参数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]);
            }
        }

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

        if (StrUtil.isNotBlank(paramJSON.getString("deviceNo"))) {
            paramsMap.put("deviceNo", paramJSON.getString("deviceNo"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("deviceType"))) {
            paramsMap.put("deviceType", paramJSON.getString("deviceType"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("agentNo"))) {
            paramsMap.put("agentNo", paramJSON.getString("agentNo"));
        }
        if (StrUtil.isNotBlank(paramJSON.getString("mchNo"))) {
            paramsMap.put("mchNo", paramJSON.getString("mchNo"));
        }
        if (CollUtil.isNotEmpty(agentSubList)) {
            paramsMap.put("agentSubList", agentSubList);
        }
        if (StrUtil.isNotBlank(paramJSON.getString("storeIdList"))) {
            List<String> storeIdList = JSON.parseObject(paramJSON.getString("storeIdList"), List.class);
            paramsMap.put("storeIdList", storeIdList);
        }
        if (StrUtil.isNotBlank(paramJSON.getString("deviceName"))) {
            paramsMap.put("deviceName", paramJSON.getString("deviceName"));
        }
        return paramsMap;
    }


}
