package com.ycwl.basic.service.mobile.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.ycwl.basic.clickhouse.service.StatsQueryService;
import com.ycwl.basic.utils.JacksonUtil;
import com.ycwl.basic.enums.StatisticEnum;
import com.ycwl.basic.mapper.StatisticsMapper;
import com.ycwl.basic.model.jwt.JwtInfo;
import com.ycwl.basic.model.mobile.statistic.req.CommonQueryReq;
import com.ycwl.basic.model.mobile.statistic.req.StatisticsRecordAddReq;
import com.ycwl.basic.model.mobile.statistic.resp.AppSta1VO;
import com.ycwl.basic.model.mobile.statistic.resp.AppSta2VO;
import com.ycwl.basic.model.mobile.statistic.resp.AppSta3VO;
import com.ycwl.basic.model.mobile.statistic.resp.AppStatisticsFunnelVO;
import com.ycwl.basic.model.pc.scenicDeviceStats.resp.ScenicDeviceStatsResp;
import com.ycwl.basic.service.mobile.AppStatisticsService;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author：longbinbin
 * @Date：2024/12/12 9:48
 */
@Service
public class AppStatisticsServiceImpl implements AppStatisticsService {

    @Autowired
    private StatisticsMapper statisticsMapper;

    @Autowired
    private StatsQueryService statsQueryService;


    /**
     * 支付订单金额、预览_支付转化率、扫码_付费用户转化率
     * @param query
     * @return
     */
    @Override
    public ApiResponse<AppSta1VO> oneStatistics(CommonQueryReq query) {
        AppSta1VO vo = new AppSta1VO();
        //订单金额格式
        DecimalFormat orderAmountDf = new DecimalFormat("0.0");
        //转化率格式
        DecimalFormat df = new DecimalFormat("0.00");
        if(query.getEndTime()==null && query.getStartTime()==null){
            // 没有传时间，则代表用户没有自定义查询时间，使用standard来判断查询时间范围
            Integer standard = query.getStandard();
            if(standard==null){
                query.setStandard(0);
            }
            //获取当前周期的具体时间范围
            standardToNewSpecificTime(query);
            //查询处理数据逻辑
            oneStatisticsHandler(1,query,vo);
            if (DateUtil.isIn(query.getStartTime(), DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(query.getEndTime(), DateUtil.tomorrow(), DateUtil.yesterday())) {
                //----------------------------------------------------
                //获取上一个周期的具体时间范围
                standardToPreviousSpecificTime(query);
                //查询处理数据逻辑
                oneStatisticsHandler(2,query,vo);
            }
        }else{
            //自定义时间查询，只有当前数据，没有往期对比数据
            //查询处理数据逻辑
            oneStatisticsHandler(1,query,vo);
        }
        return ApiResponse.success(vo);
    }

    @Override
    public ApiResponse<AppSta2VO> twoStatistics(CommonQueryReq query) {
        AppSta2VO vo = new AppSta2VO();
        if(query.getEndTime()==null && query.getStartTime()==null){
            // 没有传时间，则代表用户没有自定义查询时间，使用standard来判断查询时间范围
            Integer standard = query.getStandard();
            if(standard==null){
                query.setStandard(0);
            }
            //获取当前周期的具体时间范围
            standardToNewSpecificTime(query);
            //查询处理数据逻辑
            twoStatisticsHandler(1,query,vo);
            if (DateUtil.isIn(query.getStartTime(), DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(query.getEndTime(), DateUtil.tomorrow(), DateUtil.yesterday())) {
                //----------------------------------------------------
                //获取当前周期的具体时间范围
                standardToPreviousSpecificTime(query);
                //查询处理数据逻辑
                twoStatisticsHandler(2, query, vo);
            }
        }else{
            //自定义时间查询，只有当前数据，没有往期对比数据
            //查询处理数据逻辑
            twoStatisticsHandler(1,query,vo);
        }
        return ApiResponse.success(vo);
    }

    @Override
    public ApiResponse<AppSta3VO> freeStatistics(CommonQueryReq query) {
        AppSta3VO vo = new AppSta3VO();
        if(query.getEndTime()==null && query.getStartTime()==null){
            // 没有传时间，则代表用户没有自定义查询时间，使用standard来判断查询时间范围
            Integer standard = query.getStandard();
            if(standard==null){
                query.setStandard(0);
            }
            //获取当前周期的具体时间范围
            standardToNewSpecificTime(query);
            //查询处理数据逻辑
            freeStatisticsHandler(1,query,vo);
            if (DateUtil.isIn(query.getStartTime(), DateUtil.tomorrow(), DateUtil.yesterday()) && DateUtil.isIn(query.getEndTime(), DateUtil.tomorrow(), DateUtil.yesterday())) {
                //----------------------------------------------------
                //获取当前周期的具体时间范围
                standardToPreviousSpecificTime(query);
                //查询处理数据逻辑
                freeStatisticsHandler(2, query, vo);
            }
        }else{
            //自定义时间查询，只有当前数据，没有往期对比数据
            //查询处理数据逻辑
            freeStatisticsHandler(1,query,vo);
        }
        return ApiResponse.success(vo);
    }

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public ApiResponse<AppStatisticsFunnelVO> userConversionFunnel(CommonQueryReq query) {
        AppStatisticsFunnelVO vo = new AppStatisticsFunnelVO();
        if(query.getEndTime()==null && query.getStartTime()==null){
            // 没有传时间，则代表用户没有自定义查询时间，使用standard来判断查询时间范围
            Integer standard = query.getStandard();
            if(standard==null){
                query.setStandard(0);
            }
            //获取当前周期的具体时间范围
            standardToNewSpecificTime(query);
        }
        // 构建包含日期维度的 Redis 缓存 key
        String redisKey = String.format("statistics:tmp_cache:%s:%s",
                query.getScenicId(),
                query.getStartTime() != null ? DateUtil.formatDate(query.getStartTime()) : "null");
        if (!query.isRealtime()) {
            if (!(DateUtil.isIn(query.getStartTime(), DateUtil.yesterday(), DateUtil.tomorrow()) && DateUtil.isIn(query.getEndTime(), DateUtil.yesterday(), DateUtil.tomorrow()))) {
                // 判断是否为跨范围查询且包含今天
                Date today = DateUtil.beginOfDay(new Date());
                boolean containsToday = query.getEndTime() != null && !query.getEndTime().before(today);
                boolean isMultiDayQuery = query.getStartTime() != null && query.getStartTime().before(today);

                if (containsToday && isMultiDayQuery) {
                    // 跨范围查询且包含今天：需要分别查询历史数据和今天数据
                    AppStatisticsFunnelVO result = new AppStatisticsFunnelVO();

                    // 1. 查询历史数据（从 startDate 到昨天结束）
                    Date yesterday = DateUtil.endOfDay(DateUtil.yesterday());
                    List<AppStatisticsFunnelVO> historyList = statisticsMapper.listStatByScenic(
                        query.getScenicId(),
                        query.getStartTime(),
                        yesterday
                    );

                    // 累加历史数据
                    if (historyList != null && !historyList.isEmpty()) {
                        for (AppStatisticsFunnelVO item : historyList) {
                            result.setCameraShotOfMemberNum(addIntSafely(result.getCameraShotOfMemberNum(), item.getCameraShotOfMemberNum()));
                            result.setScanCodeVisitorOfMemberNum(addIntSafely(result.getScanCodeVisitorOfMemberNum(), item.getScanCodeVisitorOfMemberNum()));
                            result.setUploadFaceOfMemberNum(addIntSafely(result.getUploadFaceOfMemberNum(), item.getUploadFaceOfMemberNum()));
                            result.setPushOfMemberNum(addIntSafely(result.getPushOfMemberNum(), item.getPushOfMemberNum()));
                            result.setCompleteVideoOfMemberNum(addIntSafely(result.getCompleteVideoOfMemberNum(), item.getCompleteVideoOfMemberNum()));
                            result.setPreviewVideoOfMemberNum(addIntSafely(result.getPreviewVideoOfMemberNum(), item.getPreviewVideoOfMemberNum()));
                            result.setClickOnPayOfMemberNum(addIntSafely(result.getClickOnPayOfMemberNum(), item.getClickOnPayOfMemberNum()));
                            result.setPayOfMemberNum(addIntSafely(result.getPayOfMemberNum(), item.getPayOfMemberNum()));
                            result.setTotalVisitorOfMemberNum(addIntSafely(result.getTotalVisitorOfMemberNum(), item.getTotalVisitorOfMemberNum()));
                            result.setCompleteOfVideoNum(addIntSafely(result.getCompleteOfVideoNum(), item.getCompleteOfVideoNum()));
                            result.setPreviewOfVideoNum(addIntSafely(result.getPreviewOfVideoNum(), item.getPreviewOfVideoNum()));
                            result.setPayOfOrderNum(addIntSafely(result.getPayOfOrderNum(), item.getPayOfOrderNum()));
                            result.setRefundOfOrderNum(addIntSafely(result.getRefundOfOrderNum(), item.getRefundOfOrderNum()));
                            result.setPayOfOrderAmount(addBigDecimalSafely(result.payOfOrderAmount(), item.payOfOrderAmount()));
                            result.setRefundOfOrderAmount(addBigDecimalSafely(result.refundOfOrderAmount(), item.refundOfOrderAmount()));
                        }
                    }

                    // 2. 查询今天的实时数据
                    CommonQueryReq todayQuery = new CommonQueryReq();
                    todayQuery.setScenicId(query.getScenicId());
                    todayQuery.setStartTime(today);
                    todayQuery.setEndTime(query.getEndTime());

                    // 执行今天的实时查询
                    AppStatisticsFunnelVO todayData = queryRealtimeData(todayQuery);

                    // 3. 合并今天的数据到结果中
                    result.setCameraShotOfMemberNum(addIntSafely(result.getCameraShotOfMemberNum(), todayData.getCameraShotOfMemberNum()));
                    result.setScanCodeVisitorOfMemberNum(addIntSafely(result.getScanCodeVisitorOfMemberNum(), todayData.getScanCodeVisitorOfMemberNum()));
                    result.setUploadFaceOfMemberNum(addIntSafely(result.getUploadFaceOfMemberNum(), todayData.getUploadFaceOfMemberNum()));
                    result.setPushOfMemberNum(addIntSafely(result.getPushOfMemberNum(), todayData.getPushOfMemberNum()));
                    result.setCompleteVideoOfMemberNum(addIntSafely(result.getCompleteVideoOfMemberNum(), todayData.getCompleteVideoOfMemberNum()));
                    result.setPreviewVideoOfMemberNum(addIntSafely(result.getPreviewVideoOfMemberNum(), todayData.getPreviewVideoOfMemberNum()));
                    result.setClickOnPayOfMemberNum(addIntSafely(result.getClickOnPayOfMemberNum(), todayData.getClickOnPayOfMemberNum()));
                    result.setPayOfMemberNum(addIntSafely(result.getPayOfMemberNum(), todayData.getPayOfMemberNum()));
                    result.setTotalVisitorOfMemberNum(addIntSafely(result.getTotalVisitorOfMemberNum(), todayData.getTotalVisitorOfMemberNum()));
                    result.setCompleteOfVideoNum(addIntSafely(result.getCompleteOfVideoNum(), todayData.getCompleteOfVideoNum()));
                    result.setPreviewOfVideoNum(addIntSafely(result.getPreviewOfVideoNum(), todayData.getPreviewOfVideoNum()));
                    result.setPayOfOrderNum(addIntSafely(result.getPayOfOrderNum(), todayData.getPayOfOrderNum()));
                    result.setRefundOfOrderNum(addIntSafely(result.getRefundOfOrderNum(), todayData.getRefundOfOrderNum()));
                    result.setPayOfOrderAmount(addBigDecimalSafely(result.payOfOrderAmount(), todayData.payOfOrderAmount()));
                    result.setRefundOfOrderAmount(addBigDecimalSafely(result.refundOfOrderAmount(), todayData.refundOfOrderAmount()));

                    return ApiResponse.success(result);
                } else {
                    // 纯历史查询（不包含今天）
                    List<AppStatisticsFunnelVO> list = statisticsMapper.listStatByScenic(query.getScenicId(), query.getStartTime(), query.getEndTime());
                    AppStatisticsFunnelVO resp = new AppStatisticsFunnelVO();
                    if (list != null && !list.isEmpty()) {
                        for (AppStatisticsFunnelVO item : list) {
                            // Integer fields
                            resp.setCameraShotOfMemberNum(addIntSafely(resp.getCameraShotOfMemberNum(), item.getCameraShotOfMemberNum()));
                            resp.setScanCodeVisitorOfMemberNum(addIntSafely(resp.getScanCodeVisitorOfMemberNum(), item.getScanCodeVisitorOfMemberNum()));
                            resp.setUploadFaceOfMemberNum(addIntSafely(resp.getUploadFaceOfMemberNum(), item.getUploadFaceOfMemberNum()));
                            resp.setPushOfMemberNum(addIntSafely(resp.getPushOfMemberNum(), item.getPushOfMemberNum()));
                            resp.setCompleteVideoOfMemberNum(addIntSafely(resp.getCompleteVideoOfMemberNum(), item.getCompleteVideoOfMemberNum()));
                            resp.setPreviewVideoOfMemberNum(addIntSafely(resp.getPreviewVideoOfMemberNum(), item.getPreviewVideoOfMemberNum()));
                            resp.setClickOnPayOfMemberNum(addIntSafely(resp.getClickOnPayOfMemberNum(), item.getClickOnPayOfMemberNum()));
                            resp.setPayOfMemberNum(addIntSafely(resp.getPayOfMemberNum(), item.getPayOfMemberNum()));
                            resp.setTotalVisitorOfMemberNum(addIntSafely(resp.getTotalVisitorOfMemberNum(), item.getTotalVisitorOfMemberNum()));
                            resp.setCompleteOfVideoNum(addIntSafely(resp.getCompleteOfVideoNum(), item.getCompleteOfVideoNum()));
                            resp.setPreviewOfVideoNum(addIntSafely(resp.getPreviewOfVideoNum(), item.getPreviewOfVideoNum()));
                            resp.setPayOfOrderNum(addIntSafely(resp.getPayOfOrderNum(), item.getPayOfOrderNum()));
                            resp.setRefundOfOrderNum(addIntSafely(resp.getRefundOfOrderNum(), item.getRefundOfOrderNum()));

                            // BigDecimal fields
                            resp.setPayOfOrderAmount(addBigDecimalSafely(resp.payOfOrderAmount(), item.payOfOrderAmount()));
                            resp.setRefundOfOrderAmount(addBigDecimalSafely(resp.refundOfOrderAmount(), item.refundOfOrderAmount()));
                        }
                        return ApiResponse.success(resp);
                    } else {
                        query.setRealtime(true);
                    }
                }
            }
        }
        if (!query.isRealtime()) {
            if (DateUtil.isIn(query.getStartTime(), DateUtil.yesterday(), DateUtil.tomorrow()) && DateUtil.isIn(query.getEndTime(), DateUtil.yesterday(), DateUtil.tomorrow())) {
                // 缓存
                if (redisTemplate.hasKey(redisKey)) {
                    String s = redisTemplate.opsForValue().get(redisKey);
                    Map<String, Object> cacheObj = JacksonUtil.parseObject(s, Map.class);
                    return ApiResponse.success(JacksonUtil.toJavaObject(cacheObj, AppStatisticsFunnelVO.class));
                }
            }
        }

        lock.lock();
        try {
            // 缓存
            if (!query.isRealtime()) {
                if (DateUtil.isIn(query.getStartTime(), DateUtil.yesterday(), DateUtil.tomorrow()) && DateUtil.isIn(query.getEndTime(), DateUtil.yesterday(), DateUtil.tomorrow())) {
                    // 缓存
                    if (redisTemplate.hasKey(redisKey)) {
                        String s = redisTemplate.opsForValue().get(redisKey);
                        Map<String, Object> cacheObj = JacksonUtil.parseObject(s, Map.class);
                        return ApiResponse.success(JacksonUtil.toJavaObject(cacheObj, AppStatisticsFunnelVO.class));
                    }
                }
            }

            // 执行实时查询
            vo = queryRealtimeData(query);

            // 仅对当天数据启用 Redis 缓存（短期缓存，减少实时查询压力）
            // 历史数据已在 scenic_stats 表中持久化，不需要 Redis 缓存
            if (!query.isRealtime() && query.getStartTime() != null) {
                // 判断查询日期是否为今天
                if (DateUtil.isSameDay(query.getStartTime(), new Date())) {
                    redisTemplate.opsForValue().set(redisKey, JacksonUtil.toJSONString(vo), 60, TimeUnit.SECONDS);
                }
            }
            return ApiResponse.success(vo);
        } finally {
            lock.unlock();
        }
    }

    private BigDecimal addBigDecimalSafely(BigDecimal bd1, BigDecimal bd2) {
        if (bd1 == null) {
            bd1 = BigDecimal.ZERO;
        }
        if (bd2 == null) {
            bd2 = BigDecimal.ZERO;
        }
        return bd1.add(bd2).setScale(2, RoundingMode.HALF_UP);
    }

    private int addIntSafely(Integer int1, Integer int2) {
        return int1 == null ? 0 : int1 + (int2 == null ? 0 : int2);
    }

    /**
     * 执行实时数据查询（从 ClickHouse 和 MySQL 查询最新数据）
     * @param query 查询条件
     * @return 实时统计数据
     */
    private AppStatisticsFunnelVO queryRealtimeData(CommonQueryReq query) {
        AppStatisticsFunnelVO vo = new AppStatisticsFunnelVO();

        //扫码访问人数
        Integer scanCodeVisitorOfMemberNum = statsQueryService.countScanCodeOfMember(query);
        //上传头像（人脸）人数
        Integer uploadFaceOfMemberNum = statsQueryService.countUploadFaceOfMember(query);
        //推送订阅人数
        Integer pushOfMemberNum = statsQueryService.countPushOfMember(query);
        //生成视频人数
        Integer completeVideoOfMemberNum = statsQueryService.countCompleteVideoOfMember(query);
        //预览视频人数
        Integer previewVideoOfMemberNum = statsQueryService.countPreviewVideoOfMember(query);
        if (previewVideoOfMemberNum == null) {
            previewVideoOfMemberNum = 0;
        }
        //点击购买人数
        Integer clickOnPayOfMemberNum = statisticsMapper.countClickPayOfMember(query);
        //支付订单人数
        Integer payOfMemberNum = statisticsMapper.countPayOfMember(query);
        //总访问人数
        Integer totalVisitorOfMemberNum = statsQueryService.countTotalVisitorOfMember(query);
        //生成视频条数
        Integer completeOfVideoNum = statsQueryService.countCompleteOfVideo(query);
        //预览视频条数
        Integer previewOfVideoNum = statsQueryService.countPreviewOfVideo(query);
        //支付订单数
        Integer payOfOrderNum = statisticsMapper.countPayOfOrder(query);
        //支付订单金额
        BigDecimal payOfOrderAmount = statisticsMapper.countOrderAmount(query);
        //退款订单数
        Integer refundOfOrderNum = statisticsMapper.countRefundOfOrder(query);
        //退款订单金额
        BigDecimal refundOfOrderAmount = statisticsMapper.countRefundAmount(query);

        vo.setScanCodeVisitorOfMemberNum(scanCodeVisitorOfMemberNum);
        vo.setUploadFaceOfMemberNum(uploadFaceOfMemberNum);
        vo.setPushOfMemberNum(pushOfMemberNum);
        vo.setCompleteVideoOfMemberNum(completeVideoOfMemberNum);
        vo.setPreviewVideoOfMemberNum(previewVideoOfMemberNum);
        vo.setClickOnPayOfMemberNum(clickOnPayOfMemberNum);
        vo.setPayOfMemberNum(payOfMemberNum);
        vo.setTotalVisitorOfMemberNum(totalVisitorOfMemberNum);
        vo.setCompleteOfVideoNum(completeOfVideoNum);
        vo.setPreviewOfVideoNum(previewOfVideoNum);
        vo.setPayOfOrderNum(payOfOrderNum);
        vo.setPayOfOrderAmount(payOfOrderAmount != null ? payOfOrderAmount.setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO);
        vo.setRefundOfOrderNum(refundOfOrderNum);
        vo.setRefundOfOrderAmount(refundOfOrderAmount != null ? refundOfOrderAmount.setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO);

        return vo;
    }

    @Override
    public ApiResponse orderChart(CommonQueryReq query) {
        if(query.getEndTime()==null && query.getStartTime()==null){
            // 没有传时间，则代表用户没有自定义查询时间，使用standard来判断查询时间范围
            Integer standard = query.getStandard();
            if(standard==null){
                query.setStandard(0);
            }
            //获取当前周期的具体时间范围
            standardToNewSpecificTime(query);
        }
        if (DateUtil.between(query.getStartTime(), query.getEndTime(), DateUnit.DAY) <= 2) {
            // 如果是同一天
            List<HashMap<String, String>> hashMaps = statisticsMapper.orderChartByHour(query);
            return ApiResponse.success(hashMaps);
        } else {
            List<HashMap<String, String>> hashMaps = statisticsMapper.orderChartByDate(query);
            return ApiResponse.success(hashMaps);
        }
    }

    /**
     *
     * @param num1
     * @param num2
     * @return
     */
    private String calculateConversionRate(Integer num1,Integer num2){
        //转化率格式
        DecimalFormat df = new DecimalFormat("0.00");
        if(num2 == null || num2==0){
            return "0.00";
        }else {
            BigDecimal result = new BigDecimal(num1).divide(new BigDecimal(num2), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
            return df.format(result);
        }
    }



    /**
     *
     * @param cycle 周期 1当前 2往期
     * @param query
     * @param vo
     */
    private void freeStatisticsHandler(Integer cycle,CommonQueryReq query,AppSta3VO vo){
        ApiResponse<AppStatisticsFunnelVO> resp = userConversionFunnel(query);
        AppStatisticsFunnelVO data = resp.getData();
        if(cycle==1){
            //当前周期的扫码访问人数
            vo.setNowScanCodeOfPeopleNum(data.getScanCodeVisitorOfMemberNum());
            //当前周期的推送订阅人数
            vo.setNowPushOfPeopleNum(data.getPushOfMemberNum());
            //当前周期的预览视频人数
            vo.setNowPreviewVideoOfPeopleNum(data.getPreviewVideoOfMemberNum());
        }else if(cycle==2){
            //上一个周期的扫码访问人数
            vo.setPreviousScanCodeOfPeopleNum(data.getScanCodeVisitorOfMemberNum());
            //上一个周期的推送订阅人数
            vo.setPreviousPushOfPeopleNum(data.getPushOfMemberNum());
            //上一个周期的预览视频人数
            vo.setPreviousPreviewVideoOfPeopleNum(data.getPreviewVideoOfMemberNum());
        }
    }

    /**
     *
     * @param cycle 周期 1当前 2往期
     * @param query
     * @param vo
     */
    private void twoStatisticsHandler(Integer cycle,CommonQueryReq query,AppSta2VO vo){
        //查询现场支付订单数
        int sceneOrderNum=statisticsMapper.countSceneOrderNum(query);
        //查询推送支付订单数
        int pushOrderNum=statisticsMapper.countPushOrderNum(query);
        // 当前周期的总支付订单数
        Integer totalOrderNum=sceneOrderNum+pushOrderNum;

        if(cycle==1){
            //当前周期的总支付订单数
            vo.setNowPayOrderNum(totalOrderNum);
            //当前周期的现场支付订单数
            vo.setNowSceneOrderNum(sceneOrderNum);
            //当前周期的推送支付订单数
            vo.setNowPushOrderNum(pushOrderNum);
        }else if(cycle==2){
            //上一个周期的总支付订单数
            vo.setPreviousPayOrderNum(totalOrderNum);
            //上一个周期的现场支付订单数
            vo.setPreviousSceneOrderNum(sceneOrderNum);
            //上一个周期的推送支付订单数
            vo.setPreviousPushOrderNum(pushOrderNum);
        }
    }

    /**
     *
     * @param cycle 周期 1当前 2往期
     * @param query
     * @param vo
     */
    private void oneStatisticsHandler(Integer cycle,CommonQueryReq query,AppSta1VO vo){
        ApiResponse<AppStatisticsFunnelVO> resp = userConversionFunnel(query);
        AppStatisticsFunnelVO data = resp.getData();
        //订单金额格式
        DecimalFormat orderAmountDf = new DecimalFormat("0.0");
        //转化率格式
        DecimalFormat df = new DecimalFormat("0.00");
        // 计算当前周期的支付订单金额
        String orderAmount=data.getPayOfOrderAmount();
        //查询预览视频人数
        int preview=data.getPreviewVideoOfMemberNum();
        //查询扫码人数
        int scanCode=data.getScanCodeVisitorOfMemberNum();
        //查询付费人数
        int pay=data.getPayOfMemberNum();
        int payCount=data.getPayOfOrderNum();

        if(cycle==1){
            // 支付过订单的金额，包含已退款的金额。
            vo.setNowOrderAmount(orderAmount);
            // 订单数÷预览人数。假设一共5个人预览，产生了3个订单，其实是2个人支付的（其中1人购买2单），预览-支付转化率是3÷5，而不是2÷5。
            if(preview==0){
                vo.setNowPreviewPay("0.00");
            }else {
                BigDecimal previewPay = new BigDecimal(payCount).divide(new BigDecimal(preview), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
                vo.setNowPreviewPay(df.format(previewPay));
            }
            // 付费的用户人数÷扫码的用户人数。此处是人数除以人数，而且是除以扫码人数，而不是预览人数。
            if(scanCode==0){
                vo.setNowScanCodePay("0.00");
            }else {
                BigDecimal scanCodePay = new BigDecimal(pay).divide(new BigDecimal(scanCode), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
                vo.setNowScanCodePay(df.format(scanCodePay));
            }
        }else if(cycle==2){
            //上一个周期的支付订单金额
            // 支付过订单的金额，包含已退款的金额。
            vo.setPreviousOrderAmount(orderAmount);
            // 订单数÷预览人数。假设一共5个人预览，产生了3个订单，其实是2个人支付的（其中1人购买2单），预览-支付转化率是3÷5，而不是2÷5。
            if(preview==0){
                vo.setPreviousPreviewPay("0.00");
            }else {
                BigDecimal previewPay = new BigDecimal(payCount).divide(new BigDecimal(preview), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
                vo.setPreviousPreviewPay(df.format(previewPay));
            }
            // 付费的用户人数÷扫码的用户人数。此处是人数除以人数，而且是除以扫码人数，而不是预览人数。
            if(scanCode==0){
                vo.setPreviousScanCodePay("0.00");
            }else {
                BigDecimal scanCodePay = new BigDecimal(pay).divide(new BigDecimal(scanCode), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
                vo.setPreviousScanCodePay(df.format(scanCodePay));
            }
        }
    }





    /**
     * 根据standard来获取查询时间范围（当前周期）
     * @param query
     */
    private void standardToNewSpecificTime(CommonQueryReq query) {
        Integer standard = query.getStandard();
        Date newDate = DateUtil.beginOfDay(new Date());
        Date startDate = new Date();
        Date endDate = new Date();
        switch (standard) {
            case 4://年
                startDate = DateUtil.offset(newDate, DateField.YEAR, -1);
                break;
            case 3://月
                startDate = DateUtil.offset(newDate, DateField.MONTH, -1);
                break;
            case 2://周
                startDate = DateUtil.offsetWeek(newDate, -1);
                break;
            case 1://昨天
                startDate = DateUtil.offsetDay(newDate, -1);
                endDate = DateUtil.endOfDay(startDate);
                break;
            case 0://今天
                startDate = DateUtil.beginOfDay(newDate);
                break;
            case 9://历史累计
                startDate = null;
                endDate = null;
                break;
            default:
                break;
        }
        query.setStartTime(startDate);
        query.setEndTime(endDate);
    }

    /**
     * 根据standard来获取查询时间范围(上一个周期)
     * @param query
     */
    private void standardToPreviousSpecificTime(CommonQueryReq query) {
        Integer standard = query.getStandard();
        Date newDate = DateUtil.beginOfDay(new Date());
        Date startDate = new Date();
        Date endDate = new Date();
        switch (standard) {
            case 4://年，近一年的前一年
                startDate = DateUtil.offset(newDate, DateField.YEAR, -2);
                endDate = DateUtil.offset(newDate, DateField.YEAR, -1);
                break;
            case 3://月，近一月的前一个月
                startDate = DateUtil.offset(newDate, DateField.MONTH, -2);
                endDate = DateUtil.offset(newDate, DateField.MONTH, -1);
                break;
            case 2://周，近一周的前一周
                startDate = DateUtil.offsetWeek(newDate, -2);
                endDate = DateUtil.offsetWeek(newDate, -1);
                break;
            case 1://昨天，昨天的前一天
                startDate = DateUtil.offsetDay(newDate, -2);
                endDate = DateUtil.offsetDay(newDate, -1);
                break;
            case 0://今天，今天的前一天
                startDate = DateUtil.offsetDay(newDate, -1);
                endDate = DateUtil.endOfDay(startDate);
                break;
            case 9://历史累计
                startDate = null;
                endDate = null;
                break;
            default:
                break;
        }
        query.setStartTime(startDate);
        query.setEndTime(endDate);
    }
}
