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

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.service.mobile.AppStatisticsService;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.DateUtils;
import com.ycwl.basic.utils.JwtTokenUtil;
import com.ycwl.basic.utils.SnowFlakeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.Map;

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

    @Autowired
    private StatisticsMapper statisticsMapper;


    /**
     * 支付订单金额、预览_支付转化率、扫码_付费用户转化率
     * @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);
            //----------------------------------------------------
            //获取上一个周期的具体时间范围
            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);
            //----------------------------------------------------
            //获取当前周期的具体时间范围
            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);
            //----------------------------------------------------
            //获取当前周期的具体时间范围
            standardToPreviousSpecificTime(query);
            //查询处理数据逻辑
            freeStatisticsHandler(2,query,vo);
        }else{
            //自定义时间查询，只有当前数据，没有往期对比数据
            //查询处理数据逻辑
            freeStatisticsHandler(1,query,vo);
        }
        return ApiResponse.success(vo);
    }

    @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);
        }



        //镜头检测游客数
        Integer cameraShotOfMemberNum=statisticsMapper.countCameraShotOfMember(query);
        //扫码访问人数
        Integer scanCodeVisitorOfMemberNum=statisticsMapper.countScanCodeOfMember(query);
        //镜头检测游客数_扫码访问人数_转化率
//        vo.setCsom_scaom(calculateConversionRate(scanCodeVisitorOfMemberNum,cameraShotOfMemberNum));
        vo.setCsom_scaom("-");
        //上传头像（人脸）人数
        Integer uploadFaceOfMemberNum=statisticsMapper.countUploadFaceOfMember(query);
        //扫码访问人数_上传头像人数_转化率
        vo.setScaom_ufom(calculateConversionRate(uploadFaceOfMemberNum,scanCodeVisitorOfMemberNum));
        //推送订阅人数
        Integer pushOfMemberNum =statisticsMapper.countPushOfMember(query);
        //上传头像人数_推送订阅人数_转化率
        vo.setUfom_pom((calculateConversionRate(pushOfMemberNum,uploadFaceOfMemberNum)));
        //生成视频人数
        Integer completeVideoOfMemberNum =statisticsMapper.countCompleteVideoOfMember(query);
        //推送订阅人数_生成视频人数_转化率
        vo.setPom_cvom((calculateConversionRate(completeVideoOfMemberNum,pushOfMemberNum)));
        //预览视频人数
        Integer previewVideoOfMemberNum =statisticsMapper.countPreviewVideoOfMember(query);
        if (previewVideoOfMemberNum==null){
            previewVideoOfMemberNum=0;
        }
        //生成视频人数_预览视频人数_转化率
        vo.setCvom_pvom((calculateConversionRate(previewVideoOfMemberNum,completeVideoOfMemberNum)));
        //点击购买人数
        Integer clickOnPayOfMemberNum =statisticsMapper.countClickPayOfMember(query);
        //预览视频人数_点击购买人数_转化率
        vo.setPvom_cpom((calculateConversionRate(clickOnPayOfMemberNum,previewVideoOfMemberNum)));
        //支付订单人数
        Integer payOfMemberNum =statisticsMapper.countPayOfMember(query);
        //点击购买人数_支付订单人数_转化率
        vo.setCpom_pom((calculateConversionRate(payOfMemberNum,clickOnPayOfMemberNum)));
        //总访问人数
        Integer totalVisitorOfMemberNum =statisticsMapper.countTotalVisitorOfMember(query);
//        Integer totalVisitorOfMemberNum =scanCodeVisitorOfMemberNum;
        //生成视频条数
        Integer completeOfVideoNum =statisticsMapper.countCompleteOfVideo(query);
        //预览视频条数
        Integer previewOfVideoNum =statisticsMapper.countPreviewOfVideo(query);
        //支付订单数
        Integer payOfOrderNum =statisticsMapper.countPayOfOrder(query);
        //支付订单金额
        BigDecimal payOfOrderAmount =statisticsMapper.countOrderAmount(query);
        //退款订单数
        Integer refundOfOrderNum =statisticsMapper.countRefundOfOrder(query);
        //退款订单金额
        BigDecimal refundOfOrderAmount =statisticsMapper.countRefundAmount(query);

//        vo.setCameraShotOfMemberNum(cameraShotOfMemberNum);
        vo.setCameraShotOfMemberNum("-");
        vo.setScanCodeVisitorOfMemberNum(scanCodeVisitorOfMemberNum);
        vo.setUploadFaceOfMemberNum(uploadFaceOfMemberNum);
        vo.setPushOfMemberNum(pushOfMemberNum);
        vo.setCompleteVideoOfMemberNum(completeVideoOfMemberNum);
        vo.setPreviewVideoOfMemberNum(previewVideoOfMemberNum);
        vo.setClickOnPayOfMemberNum(clickOnPayOfMemberNum);
        vo.setPayOfMemberNum(payOfMemberNum);

        //转化率格式
        DecimalFormat df = new DecimalFormat("0.0");

        vo.setTotalVisitorOfMemberNum(totalVisitorOfMemberNum);
        vo.setCompleteOfVideoNum(completeOfVideoNum);
        vo.setPreviewOfVideoNum(previewOfVideoNum);
        vo.setPayOfOrderNum(payOfOrderNum);
        vo.setPayOfOrderAmount(df.format(payOfOrderAmount.setScale(2, RoundingMode.HALF_UP)));
        vo.setRefundOfOrderNum(refundOfOrderNum);
        vo.setRefundOfOrderAmount(df.format(refundOfOrderAmount.setScale(2, RoundingMode.HALF_UP)));

        return ApiResponse.success(vo);
    }

    @Override
    public ApiResponse addStatistics(StatisticsRecordAddReq req) {
//        req.setId(SnowFlakeUtil.getLongId());
        if (req.getMemberId() == null) {
            try {
                JwtInfo worker = JwtTokenUtil.getWorker();
                Long userId = worker.getUserId();
                req.setMemberId(userId);
            } catch (Exception ignored) {

            }
        }
        Integer type = req.getType();
        if(type==null){
            return ApiResponse.fail("类型不能为空");
        }
        Map<Integer, StatisticEnum> valueMap = StatisticEnum.cacheMap;
        if(!valueMap.containsKey(type)){
            return ApiResponse.fail("添加失败，类型不存在");
        }
        int i=statisticsMapper.addStatisticsRecord(req);
        if(i==0){
            return ApiResponse.fail("添加失败");
        }else{
            return ApiResponse.success("添加成功");
        }
    }

    /**
     *
     * @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){
        //查询扫码访问人数
        int sceneNum=statisticsMapper.countScanCodeOfMember(query);
        //查询推送订阅人数
        int pushNum=statisticsMapper.countPushOfMember(query);
        // 查询预览视频人数
        Integer previewNum=statisticsMapper.countPreviewVideoOfMember(query);

        if(cycle==1){
            //当前周期的扫码访问人数
            vo.setNowScanCodeOfPeopleNum(sceneNum);
            //当前周期的推送订阅人数
            vo.setNowPushOfPeopleNum(pushNum);
            //当前周期的预览视频人数
            vo.setNowPreviewVideoOfPeopleNum(previewNum);
        }else if(cycle==2){
            //上一个周期的扫码访问人数
            vo.setPreviousScanCodeOfPeopleNum(sceneNum);
            //上一个周期的推送订阅人数
            vo.setPreviousPushOfPeopleNum(pushNum);
            //上一个周期的预览视频人数
            vo.setPreviousPreviewVideoOfPeopleNum(previewNum);
        }
    }

    /**
     *
     * @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){
        //订单金额格式
        DecimalFormat orderAmountDf = new DecimalFormat("0.0");
        //转化率格式
        DecimalFormat df = new DecimalFormat("0.00");
        // 计算当前周期的支付订单金额
        BigDecimal orderAmount=statisticsMapper.countOrderAmount(query).setScale(2, RoundingMode.HALF_UP);
        //查询预览视频人数
        int preview=statisticsMapper.countPreviewVideoOfMember(query);
        //查询扫码人数
        int scanCode=statisticsMapper.countScanCodeOfMember(query);
        //查询付费人数
        int pay=statisticsMapper.countPayOfMember(query);
        int payCount=statisticsMapper.countPayOfOrder(query);

        if(cycle==1){
            //当前周期的支付订单金额
            vo.setNowOrderAmount(orderAmountDf.format(orderAmount));
            //当前周期预览_支付转化率、扫码_付费用户转化率
            if(preview==0){
                vo.setNowPreviewPay("0.00");
            }else {
                BigDecimal previewPay = new BigDecimal(pay).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(orderAmountDf.format(orderAmount));
            // 计算预览_支付转化率
            if(preview==0){
                vo.setPreviousPreviewPay("0.00");
            }else {
                BigDecimal previewPay = new BigDecimal(pay).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 = new Date();
        Date startDate = new Date();
        Date endDate = new Date();
        switch (standard) {
            case 4://年
                startDate = DateUtils.addDateYears(newDate, -1);
                break;
            case 3://月
                startDate = DateUtils.addDateMonths(newDate, -1);
                break;
            case 2://周
                startDate = DateUtils.addDateWeeks(newDate, -1);
                break;
            case 1://昨天
                Date yesterday = DateUtils.addDateDays(newDate, -1);
                startDate = DateUtils.getStartOfDay(yesterday);
                endDate = DateUtils.getEndOfDay(yesterday);
                break;
            case 0://今天
                startDate = DateUtils.getStartOfDay(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 = new Date();
        Date startDate = new Date();
        Date endDate = new Date();
        switch (standard) {
            case 4://年，近一年的前一年
                startDate = DateUtils.addDateYears(newDate, -2);
                break;
            case 3://月，近一月的前一个月
                startDate = DateUtils.addDateMonths(newDate, -2);
                endDate = DateUtils.addDateMonths(newDate, -1);
                break;
            case 2://周，近一周的前一周
                startDate = DateUtils.addDateWeeks(newDate, -2);
                endDate = DateUtils.addDateWeeks(newDate, -1);
                break;
            case 1://昨天，昨天的前一天
                Date theDayBeforeYesterday = DateUtils.addDateDays(newDate, -2);
                startDate = DateUtils.getStartOfDay(theDayBeforeYesterday);
                endDate = DateUtils.getEndOfDay(theDayBeforeYesterday);
                break;
            case 0://今天，今天的前一天
                Date yesterday = DateUtils.addDateDays(newDate, -1);
                startDate = DateUtils.getStartOfDay(yesterday);
                endDate = DateUtils.getEndOfDay(yesterday);
                break;
            case 9://历史累计
                startDate = null;
                endDate = null;
                break;
            default:
                break;
        }
        query.setStartTime(startDate);
        query.setEndTime(endDate);
    }
}
