package cn.cecep.talroad.service.impl;

import cn.cecep.talroad.common.core.utils.DateUtils;
import cn.cecep.talroad.domain.AmProblemFi;
import cn.cecep.talroad.mapper.AmProblemFiMapper;
import cn.cecep.talroad.mapper.PointIsOfflineMapper;
import cn.cecep.talroad.service.PointIsOfflineService;
import cn.cecep.talroad.vo.PointIsOfflineVO;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @className: PointIsOfflineServiceImpl
 * @description: TODO 类描述
 * @author: Mr.Yanghongtao
 * @date: 2023/04/15 5:16 PM
 * @Company: Copyright© [2023/04/15 5:16 PM] by [Mr.Yanghongtao]
 **/
@Service
public class PointIsOfflineServiceImpl implements PointIsOfflineService {

    @Autowired
    private PointIsOfflineMapper pointIsOfflineMapper;

    @Autowired
    private AmProblemFiMapper amProblemFiMapper;

    /**
     * @Author: Mr.Yanghongtao
     * @data: 2023/4/15 5:37 PM
     * @Deseription: 无组织点位，如果连续断了8个小时数据，就更新点位状态为离线
     * @Params: null
     * @Return:
     * @Throws:
     */
    @Override
    public void disorganizationPointIsOffline() {
        // 无组织监测点位数据是一个小时一条，根据规则我们要查询近8个小时内（包过本小时）是否存在数据
        String startTime = DateUtils.parseDateToStr("yyyy-MM-dd HH:00:00",DateUtils.addDateHours(new Date(),-7));
        String endTime = DateUtils.parseDateToStr("yyyy-MM-dd HH:00:00",new Date());
        // 获取上一个小时的时间
        String beforeTime = DateUtils.parseDateToStr("yyyy-MM-dd HH:00:00",DateUtils.addDateHours(new Date(),-1));

        List<PointIsOfflineVO> updatePoints = new ArrayList<>();

        List<PointIsOfflineVO> pointIsOfflineVOS = pointIsOfflineMapper.selectDisorganizationListByDateTime(Timestamp.valueOf(startTime), Timestamp.valueOf(endTime));
        // 根据点位进行分组，每个点位下必须要有一条数据
        Map<String, List<PointIsOfflineVO>> collect = pointIsOfflineVOS.stream().collect(Collectors.groupingBy(PointIsOfflineVO::getOutletId));
        collect.forEach((k,v)->{
            List<PointIsOfflineVO> list = v.stream().filter(x->x.getMonitoringTime()!=null).collect(Collectors.toList());
            String status = "离线";
            if (!CollectionUtil.isEmpty(list)) {
                AmProblemFi amProblemFi = new AmProblemFi();
                // 关联分析系统
                amProblemFi.setProblemSources("1");
                // 浓度超标报警
                amProblemFi.setProblemType("005001");
                amProblemFi.setAnalyseTime(DateUtils.parseDate(beforeTime));
                amProblemFi.setAnalyseTimeEnd(new Date());
                amProblemFi.setStationId(k);
                // 先去查询上一个小时截止当前时间，是否有报警，如果有报警，则不更新状态
                Integer ndcbbj = amProblemFiMapper.selectCountByParams(amProblemFi);
                // 浓度超标预警
                amProblemFi.setProblemType("005002");
                Integer ndcbyj = amProblemFiMapper.selectCountByParams(amProblemFi);
                if (ndcbyj == 0 && ndcbbj == 0) {
                    // 上个小时没有超标报警或超标预警，进行状态更新
                    status = "正常";
                }
            }
            PointIsOfflineVO tmpPoint = new PointIsOfflineVO();
            tmpPoint.setOutletId(k);
            tmpPoint.setWzzStatus(status);
            updatePoints.add(tmpPoint);

        });
        // 更新无组织监测点位
        List<List<PointIsOfflineVO>> dataList = subList(updatePoints, 1000);
        for (int i = 0; i < dataList.size(); i++) {
            pointIsOfflineMapper.updatePcOutletStatus(dataList.get(i));
        }
    }


    /**
     * @Author: Mr.Yanghongtao
     * @data: 2023/4/15 6:25 PM
     * @Deseription: 在线监测点位，如果连续断了30分钟的数据，就更新点位状态为离线
     * @Params: null
     * @Return:
     * @Throws:
     */
    @Override
    public void onLineMonitoringPointIsOffline() {
        // 在线监测点位数据是一分钟一条，根据规则我们要查询近30分钟内（包过本分钟）是否存在数据
        String startTime = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:00",DateUtils.addDateMinutes(new Date(),-29));
        String endTime = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:00",new Date());
        // 获取上一个小时的时间
        String beforeTime = DateUtils.parseDateToStr("yyyy-MM-dd HH:00:00",DateUtils.addDateHours(new Date(),-1));

        List<PointIsOfflineVO> updatePoints = new ArrayList<>();

        List<PointIsOfflineVO> pointIsOfflineVOS = pointIsOfflineMapper.selectOnLineMonitoringListByDateTime(Timestamp.valueOf(startTime), Timestamp.valueOf(endTime));
        // 根据点位进行分组，每个点位下必须要有一条数据
        Map<String, List<PointIsOfflineVO>> collect = pointIsOfflineVOS.stream().collect(Collectors.groupingBy(PointIsOfflineVO::getOutletId));
        collect.forEach((k,v)->{
            List<PointIsOfflineVO> list = v.stream().filter(x->x.getMonitoringTime()!=null).collect(Collectors.toList());
            String status = "掉线";
            if (!CollectionUtil.isEmpty(list)) {
                AmProblemFi amProblemFi = new AmProblemFi();
                // 关联分析系统
                amProblemFi.setProblemSources("1");
                // 浓度超标报警
                amProblemFi.setProblemType("003002");
                amProblemFi.setAnalyseTime(DateUtils.parseDate(beforeTime));
                amProblemFi.setAnalyseTimeEnd(new Date());
                amProblemFi.setStationId(k);
                // 先去查询上一个小时截止当前时间，是否有报警，如果有报警，则不更新状态
                Integer ndcbbj = amProblemFiMapper.selectCountByParams(amProblemFi);
                // 浓度超标预警
                amProblemFi.setProblemType("003003");
                Integer ndcbyj = amProblemFiMapper.selectCountByParams(amProblemFi);
                if ( ndcbbj == 0 && ndcbyj == 0) {
                    // 上个小时没有超标报警或超标预警，进行状态更新
                    status = "正常";
                }
            }
            PointIsOfflineVO tmpPoint = new PointIsOfflineVO();
            tmpPoint.setOutletId(k);
            tmpPoint.setOutletStatus(status);
            updatePoints.add(tmpPoint);
        });
        // 更新在线监测点位
        List<List<PointIsOfflineVO>> dataList = subList(updatePoints, 1000);
        for (int i = 0; i < dataList.size(); i++) {
            pointIsOfflineMapper.updatePcOutletStatus(dataList.get(i));
        }
    }


    /**
     * 截取List
     * @param tList
     * @param subNum
     * @param <T>
     * @return
     */
    public static<T>  List<List<T>> subList(List<T> tList, Integer subNum) {
        // 新的截取到的list集合
        List<List<T>> tNewList = new ArrayList<List<T>>();
        // 要截取的下标上限
        Integer priIndex = 0;
        // 要截取的下标下限
        Integer lastIndex = 0;
        // 每次插入list的数量
        // Integer subNum = 500;
        // 查询出来list的总数目
        Integer totalNum = tList.size();
        // 总共需要插入的次数
        Integer insertTimes = totalNum / subNum;
        List<T> subNewList = new ArrayList<T>();
        for (int i = 0; i <= insertTimes; i++) {
            // [0--20) [20 --40) [40---60) [60---80) [80---100)
            priIndex = subNum * i;
            lastIndex = priIndex + subNum;
            // 判断是否是最后一次
            if (i == insertTimes) {
                //logger.info("最后一次截取："+priIndex + "," + lastIndex);
                subNewList = tList.subList(priIndex, tList.size());
            } else {
                // 非最后一次
                subNewList = tList.subList(priIndex, lastIndex);
            }
            if (subNewList.size() > 0) {
                //logger.info("开始将截取的list放入新的list中");
                tNewList.add(subNewList);
            }
        }
        return tNewList;
    }
}
