package com.lutao.cloud.oil.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lutao.cloud.common.core.util.CollectionUtil;
import com.lutao.cloud.common.core.util.MessageInfo;
import com.lutao.cloud.common.core.util.StringUtil;
import com.lutao.cloud.oil.mapper.*;
import com.lutao.cloud.oil.pojo.param.*;
import com.lutao.cloud.oil.pojo.vo.*;
import com.lutao.cloud.oil.service.IBusinessPerceptionMonitorAlarmService;
import com.lutao.cloud.oil.service.PlatformInfoService;
import com.lutao.cloud.oil.service.TagAlarmClmService;
import com.lutao.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * impl业务感知监控报警服务
 *
 * @author yx
 * @date 2023/07/26
 */
@Service
@Slf4j
public class BusinessPerceptionMonitorAlarmServiceImpl implements IBusinessPerceptionMonitorAlarmService {

//    @Value("${lindorm.url}")
//    private String url;

    @Resource
    private PlatformInfoService platformInfoService;

    @Resource
    private TagAlarmClmService tagAlarmClmService;

    @Resource
    private PerceptionMonitorInfoMapper perceptionMonitorInfoMapper;

    @Resource
    private PerceptionMonitorAlarmInfoMapper perceptionMonitorAlarmInfoMapper;

    @Resource
    private ProcessParameterTagMapper processParameterTagMapper;

    @Resource
    private TagAlarmClmMapper tagAlarmClmMapper;

    @Resource
    private FireParametersTagMapper fireParametersTagMapper;

    @Resource
    private GasParametersTagMapper gasParametersTagMapper;

    @Resource
    private HazardousGasParametersTagMapper hazardousGasParametersTagMapper;


    private static Map<String, String> appMap;

    static {
        appMap = new HashMap<>();
        appMap.put("zhonghaiyou", "中海油");
        appMap.put("zhongshiyou", "中石油");
        appMap.put("zhongshihua", "中石化");

    }


    @Override
    public MessageInfo<IPage<DetectionAlarmVO>> queryFireDetectionAlarmList(FireAndGasAlarmParam param, Page page) {
        IPage<DetectionAlarmVO> detectionAlarmVOIPage = perceptionMonitorAlarmInfoMapper.selectDetectionAlarmList(
                page,
                param.getPlatformId(),
                param.getAppId(),
                6, param.getStartDate(),
                param.getEndDate(),
                param.getOilGasName(),
                param.getOperatingCompany()
        );

        return MessageInfo.ok(detectionAlarmVOIPage);
    }

    @Override
    public MessageInfo<IPage<DetectionAlarmVO>> queryGasDetectionAlarmList(FireAndGasAlarmParam param, Page page) {
        IPage<DetectionAlarmVO> detectionAlarmVOIPage = perceptionMonitorAlarmInfoMapper.selectDetectionAlarmList(
                page,
                param.getPlatformId(),
                param.getAppId(),
                7,
                param.getStartDate(),
                param.getEndDate(),
                param.getOilGasName(),
                param.getOperatingCompany()
        );

        return MessageInfo.ok(detectionAlarmVOIPage);
    }


    @Override
    public MessageInfo<IPage<DetectionAlarmVO>> queryHazardousGasDetectionAlarmList(FireAndGasAlarmParam param, Page page) {
        IPage<DetectionAlarmVO> detectionAlarmVOIPage = perceptionMonitorAlarmInfoMapper.selectDetectionAlarmList(
                page,
                param.getPlatformId(),
                param.getAppId(),
                8,
                param.getStartDate(),
                param.getEndDate(),
                param.getOilGasName(),
                param.getOperatingCompany()
        );

        return MessageInfo.ok(detectionAlarmVOIPage);
    }

    @Override
    public MessageInfo<ScreenDisplayDetectAlarmVO> queryScreenDisplayDetectAlarm(BaseParam param) {

        /**
         * <p>
         *     报警点位数  报警次数
         * </p>
         *
         */

        //火灾报警监测点数量 6
        Long fireAlarmPointNumber = 0L;
        //可燃气体报警监测点数量 7
        Long gasAlarmPointNumber = 0L;
        //有毒气体报警监测点数量 8
        Long hazardousGasPointNumber = 0L;
        //关键工艺参数报警点位数量
        Long keyProcessAlarmPointNumber = 0L;

        List<TagAlarmClmPointVO> tagAlarmClmPointVOS = tagAlarmClmMapper.selectTagAlarmClmPoint();

        if (tagAlarmClmPointVOS != null && !tagAlarmClmPointVOS.isEmpty()) {
            for (TagAlarmClmPointVO tagAlarmClmPointVO : tagAlarmClmPointVOS) {
                if (tagAlarmClmPointVO.getAlarmPointNumber() == null) {
                    tagAlarmClmPointVO.setAlarmPointNumber(0L);
                }

                if ("6".equals(tagAlarmClmPointVO.getTagType())) {
                    fireAlarmPointNumber = tagAlarmClmPointVO.getAlarmPointNumber();
                }
                if ("7".equals(tagAlarmClmPointVO.getTagType())) {
                    gasAlarmPointNumber = tagAlarmClmPointVO.getAlarmPointNumber();
                }
                if ("8".equals(tagAlarmClmPointVO.getTagType())) {
                    hazardousGasPointNumber = tagAlarmClmPointVO.getAlarmPointNumber();
                }
                // 关键工艺参数报警点位数量
                if (!"6".equals(tagAlarmClmPointVO.getTagType()) && !"7".equals(tagAlarmClmPointVO.getTagType()) && !"8".equals(tagAlarmClmPointVO.getTagType())) {
                    keyProcessAlarmPointNumber += tagAlarmClmPointVO.getAlarmPointNumber();
                }
            }
        }

        List<TagAlarmClmPointVO> tagAlarmClmNumber = tagAlarmClmMapper.selectTagAlarmClmNumber();

        Long fireAlarmNumber = 0L;
        Long gasAlarmNumber = 0L;
        Long hazardousGasNumber = 0L;
        //关键工艺参数报警数量
        Long keyProcessAlarmNumber = 0L;

        if (tagAlarmClmNumber != null && !tagAlarmClmNumber.isEmpty()) {
            for (TagAlarmClmPointVO tagAlarmClmPointVO : tagAlarmClmNumber) {

                if (tagAlarmClmPointVO.getAlarmPointNumber() == null) {
                    tagAlarmClmPointVO.setAlarmPointNumber(0L);
                }

                if ("6".equals(tagAlarmClmPointVO.getTagType())) {
                    fireAlarmNumber = tagAlarmClmPointVO.getAlarmPointNumber();
                }
                if ("7".equals(tagAlarmClmPointVO.getTagType())) {
                    gasAlarmNumber = tagAlarmClmPointVO.getAlarmPointNumber();
                }
                if ("8".equals(tagAlarmClmPointVO.getTagType())) {
                    hazardousGasNumber = tagAlarmClmPointVO.getAlarmPointNumber();
                }

                // 关键工艺参数报警数量
                if (!"6".equals(tagAlarmClmPointVO.getTagType()) && !"7".equals(tagAlarmClmPointVO.getTagType()) && !"8".equals(tagAlarmClmPointVO.getTagType())) {
                    keyProcessAlarmNumber += tagAlarmClmPointVO.getAlarmPointNumber();
                }
            }
        }

        //火灾监测点数量
        Long firePointNumber = 0L;

        firePointNumber = Long.valueOf(fireParametersTagMapper.selectCount(Wrappers.lambdaQuery(FireParametersTag.class).eq(FireParametersTag::getStatus, "0")));

        //可燃气体监测点数量
        Long gasPointNumber = 0L;
        gasPointNumber = Long.valueOf(gasParametersTagMapper.selectCount(Wrappers.lambdaQuery(GasParametersTag.class).eq(GasParametersTag::getStatus, "0")));

        //有毒气体监测点数量
        Long hazardousGasPointCount = 0L;
        hazardousGasPointCount = Long.valueOf(hazardousGasParametersTagMapper.selectCount(Wrappers.lambdaQuery(HazardousGasParametersTag.class).eq(HazardousGasParametersTag::getStatus, "0")));

        //关键工艺参数监测点数量
        Long keyProcessPointNumber = 0L;
        keyProcessPointNumber = Long.valueOf(processParameterTagMapper.selectCount(Wrappers.lambdaQuery(ProcessParameterTag.class).eq(ProcessParameterTag::getStatus, "0")));


        ScreenDisplayDetectAlarmVO screenDisplayDetectAlarmVO = new ScreenDisplayDetectAlarmVO()
                .setFireAlarmPointNumber(fireAlarmPointNumber)
                .setGasAlarmPointNumber(gasAlarmPointNumber)
                .setHazardousGasPointNumber(hazardousGasPointNumber)
                .setFireAlarmNumber(fireAlarmNumber)
                .setGasAlarmNumber(gasAlarmNumber)
                .setHazardousGasAlarmNumber(hazardousGasNumber)
                .setKeyProcessAlarmPointNumber(keyProcessAlarmPointNumber)
                .setKeyProcessAlarmNumber(keyProcessAlarmNumber)
                .setFirePointNumber(firePointNumber)
                .setGasPointNumber(gasPointNumber)
                .setHazardousGasPointCount(hazardousGasPointCount)
                .setKeyProcessPointNumber(keyProcessPointNumber);
        return MessageInfo.ok(screenDisplayDetectAlarmVO);
    }

    @Override
    public MessageInfo<IPage<EquipmentTagAlarmVO>> queryEquipmentTagAlarm(Page page, EquipmentTagParam param) {
        IPage<EquipmentTagAlarmVO> equipmentTagAlarm = perceptionMonitorAlarmInfoMapper.getEquipmentTagAlarm(page, param);


        return MessageInfo.ok(equipmentTagAlarm);
    }

    @Override
    public MessageInfo<List<ScreenTagAlarmVO>> queryScreenTagAlarm() {
        List<ScreenTagAlarmVO> screenTagAlarm = perceptionMonitorAlarmInfoMapper.getScreenTagAlarm();
        return MessageInfo.ok(screenTagAlarm);
    }

    @Override
    public MessageInfo<List<TagAlarmTrendVO>> getAlarmTrend(EquipmentTagParam param) {
        int trendDays = Optional.ofNullable(param.getTrendDays()).orElse(7);

        // 获取trendDays天前的时间
        LocalDate startDate = LocalDate.now().minusDays(trendDays);

        // 查询所有在给定时间范围内的报警数据
        List<TagAlarmClm> tagAlarmClms = tagAlarmClmService.list(
                Wrappers.lambdaQuery(TagAlarmClm.class)
                        .ge(TagAlarmClm::getAlarmTimestamp, Date.from(startDate.atStartOfDay(ZoneId.systemDefault()).toInstant()))
        );

        // 按日期分组并计算每天的报警次数
        Map<LocalDate, Long> alarmCounts = tagAlarmClms.stream()
                .collect(Collectors.groupingBy(
                        tagAlarmClm -> tagAlarmClm.getAlarmTimestamp().toLocalDate(),
                        Collectors.counting()
                ));

        // 创建TagAlarmTrendVO列表
        List<TagAlarmTrendVO> trendVOs = IntStream.rangeClosed(0, trendDays - 1)
                .mapToObj(i -> {
                    LocalDate date = LocalDate.now().minusDays(i);
                    long count = alarmCounts.getOrDefault(date, 0L);
                    return new TagAlarmTrendVO().setAlarmDate(date.format(DateTimeFormatter.ISO_LOCAL_DATE)).setAlarmCount(count);
                })
                .sorted(Comparator.comparing(TagAlarmTrendVO::getAlarmDate))
                .collect(Collectors.toList());

        return MessageInfo.ok(trendVOs);
    }


    @Override
    public MessageInfo<IPage<ProcessTagVO>> getProcessParamTagPage(Page page, EquipmentTagParam param) {
        IPage<ProcessTagVO> processParamTag = perceptionMonitorInfoMapper.getProcessParamTag(page, param);
        return MessageInfo.ok(processParamTag);
    }

    @Override
    public MessageInfo<List<ProcessTagVO>> getProcessParamTagList(EquipmentTagParam param, int current, int size) {
        //String url = "http://ld-m5e4qsgx0379a5huf-proxy-tsdb-pub.lindorm.rds.aliyuncs.com:8242";
        // LindormTSDBClient线程安全，可以重复使用，无需频繁创建和销毁

//        LindormTSDBClient lindormTSDBClient = LindormTSDBConnectionManager.getLindormTSDBClient(url);
//
//        int startIndex = (current - 1) * size; // 计算起始记录索引
//        String sql = "select * from perception_monitor_info where tag_type in ('2','3','5')";
//        if (param.getParamType() != null) {
//            sql += " and tag_type = '" + param.getParamType() + "'";
//        }
//        sql += " order by collect_time desc limit " + startIndex + "," + size;
//        log.info("sql:{}", sql);
//        //获取所有的平台信息
//        List<PlatformInfo> platformInfos = platformInfoService.list();
//        Map<String, PlatformInfo> platformMap = new HashMap<>();
//        //将平台信息以code为key 存到map中
//        for (PlatformInfo platformInfo : platformInfos) {
//            platformMap.put(platformInfo.getPlatformCode(), platformInfo);
//        }
//        ResultSet resultSet = lindormTSDBClient.query("OILTEST", sql);
//        List<ProcessTagVO> processTagVOS = new ArrayList<>();
//        try {
//            // 处理查询结果
//            QueryResult result = null;
//            // 查询结果使用分批的方式返回，默认每批1000行
//            // 当resultSet的next()方法返回为null，表示已经读取完所有的查询结果
//            while ((result = resultSet.next()) != null) {
//                List<List<Object>> rows = result.getRows();
//                for (List<Object> row : rows) {
//                    ProcessTagVO processTagVO = new ProcessTagVO();
//                    String platformCode = row.get(FieldConstants.PLATFORM_CODE).toString();
//                    processTagVO.setPlatformName(platformMap.get(platformCode).getPlatformName());
//                    processTagVO.setOilGasName(platformMap.get(platformCode).getOilGasName());
//                    processTagVO.setOperatingCompany(platformMap.get(platformCode).getOperatingCompany());
//                    processTagVO.setAppName(appMap.get(row.get(FieldConstants.APP_ID).toString()));
//                    processTagVO.setRtValue(row.get(FieldConstants.RT_VALUE).toString());
//                    processTagVO.setTagName(row.get(FieldConstants.TAG_NAME).toString());
//                    processTagVO.setCollectTime(LocalDateTime.parse(row.get(FieldConstants.COLLECT_TIME).toString()));
//                    processTagVO.setTagType(Integer.valueOf(row.get(FieldConstants.TAG_TYPE).toString()));
//                    processTagVO.setUnit(row.get(FieldConstants.UNIT).toString());
//                    processTagVO.setLimits(row.get(FieldConstants.LIMITS).toString());
//                    processTagVOS.add(processTagVO);
//                }
//            }
//        } finally {
//            // 查询结束后，需确保调用ResultSet的close方法，以释放IO资源
//            resultSet.close();
//        }
//        return MessageInfo.ok(processTagVOS);
        return null;
    }

    @Override
    public MessageInfo<IPage<ProcessParametersTagVO>> getProcessParamInfoPage(Page page, ProcessParametersTagVOParam param) {
        return MessageInfo.ok(processParameterTagMapper.getProcessParamInfoPage(page, param));
    }

    @Override
    public MessageInfo<IPage<ProcessParametersTagVO>> getPerceptionMonitorInfoByTagCode(Page page, EquipmentTagParam param) {
        IPage<ProcessParametersTagVO> perceptionMonitorInfoByTagCode = perceptionMonitorInfoMapper.getPerceptionMonitorInfoByTagCode(page, param);
        return MessageInfo.ok(perceptionMonitorInfoByTagCode);
    }

    @Override
    public MessageInfo<TagProcessAlarmVO> queryEquipmentTagAlarmChart(EquipmentTagParam param) {

        TagProcessAlarmVO tagProcessAlarmVO = new TagProcessAlarmVO();

        List<TagProcessAlarmByUnit> tagProcessAlarmByUnits = tagAlarmClmMapper.selectTagProcessAlarmByUnit(param.getAppId());

        tagProcessAlarmVO.setTagProcessAlarmByUnitList(tagProcessAlarmByUnits);

        //温度报警数量
        int count1 = tagAlarmClmService.count(
                Wrappers.lambdaQuery(TagAlarmClm.class)
                        .eq(TagAlarmClm::getTagType, 2)
                        .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
                        .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
        );

        //温度报警销警数量
        int count4 = tagAlarmClmService.count(
                Wrappers.lambdaQuery(TagAlarmClm.class)
                        .eq(TagAlarmClm::getTagType, 2)
                        .eq(TagAlarmClm::getState, "00")
                        .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
                        .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
        );

        //压力报警数量
        int count2 = tagAlarmClmService.count(
                Wrappers.lambdaQuery(TagAlarmClm.class)
                        .eq(TagAlarmClm::getTagType, 3)
                        .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
                        .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
        );

        //压力报警销警数量
        int count5 = tagAlarmClmService.count(
                Wrappers.lambdaQuery(TagAlarmClm.class)
                        .eq(TagAlarmClm::getTagType, 3)
                        .eq(TagAlarmClm::getState, "00")
                        .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
                        .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
        );

        //液位报警数量
        int count3 = tagAlarmClmService.count(
                Wrappers.lambdaQuery(TagAlarmClm.class)
                        .eq(TagAlarmClm::getTagType, 5)
                        .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
                        .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
        );

        //液位报警销警数量
        int count6 = tagAlarmClmService.count(
                Wrappers.lambdaQuery(TagAlarmClm.class)
                        .eq(TagAlarmClm::getTagType, 5)
                        .eq(TagAlarmClm::getState, "00")
                        .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
                        .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
        );

        tagProcessAlarmVO.setTemperatureAlarmNumber((long) count1);
        tagProcessAlarmVO.setPressureAlarmNumber((long) count2);
        tagProcessAlarmVO.setLiquidLevelAlarmNumber((long) count3);
        tagProcessAlarmVO.setTemperatureCancelAlarmNumber((long) count4);
        tagProcessAlarmVO.setPressureCancelAlarmNumber((long) count5);
        tagProcessAlarmVO.setLiquidLevelCancelAlarmNumber((long) count6);


        return MessageInfo.ok(tagProcessAlarmVO);
    }

    @Override
    public MessageInfo<List<DetectAlarmChartVO>> getFireAlarmChart(DetectAlarmChartVOParam param) {
        param.setTagType("6");
        List<DetectAlarmChartVO> detectAlarmChart = perceptionMonitorAlarmInfoMapper.getDetectAlarmChart(param);

        //获取当天的日期
        LocalDate now = LocalDate.now();

        // 遍历一个月的日期
        for (int i = 0; i < 30; i++) {
            LocalDate date = now.minusDays(i);
            boolean found = false;

            // 检查每个日期是否已经在列表中
            for (DetectAlarmChartVO chart : detectAlarmChart) {
                if (chart.getAlarmDate().equals(date)) {
                    found = true;
                    break;
                }
            }

            // 如果日期不在列表中，添加到missingDates列表
            if (!found) {
                DetectAlarmChartVO detectAlarmChartVO = new DetectAlarmChartVO().setAlarmDate(date).setAlarmCount(0);
                detectAlarmChart.add(detectAlarmChartVO);
            }
        }
        detectAlarmChart.sort(Comparator.comparing(DetectAlarmChartVO::getAlarmDate));
        return MessageInfo.ok(detectAlarmChart);
    }

    @Override
    public MessageInfo<List<DetectAlarmChartVO>> getGasAlarmChart(DetectAlarmChartVOParam param) {
        param.setTagType("7");
        List<DetectAlarmChartVO> detectAlarmChart = perceptionMonitorAlarmInfoMapper.getDetectAlarmChart(param);
        //获取当天的日期
        LocalDate now = LocalDate.now();

        // 遍历一个月的日期
        for (int i = 0; i < 30; i++) {
            LocalDate date = now.minusDays(i);
            boolean found = false;

            // 检查每个日期是否已经在列表中
            for (DetectAlarmChartVO chart : detectAlarmChart) {
                if (chart.getAlarmDate().equals(date)) {
                    found = true;
                    break;
                }
            }

            // 如果日期不在列表中，添加到missingDates列表
            if (!found) {
                DetectAlarmChartVO detectAlarmChartVO = new DetectAlarmChartVO().setAlarmDate(date).setAlarmCount(0);
                detectAlarmChart.add(detectAlarmChartVO);
            }
        }
        detectAlarmChart.sort(Comparator.comparing(DetectAlarmChartVO::getAlarmDate));
        return MessageInfo.ok(detectAlarmChart);
    }

    @Override
    public MessageInfo<List<DetectAlarmChartVO>> getHazardousAlarmChart(DetectAlarmChartVOParam param) {
        param.setTagType("8");
        List<DetectAlarmChartVO> detectAlarmChart = perceptionMonitorAlarmInfoMapper.getDetectAlarmChart(param);
        //获取当天的日期
        LocalDate now = LocalDate.now();

        // 遍历一个月的日期
        for (int i = 0; i < 30; i++) {
            LocalDate date = now.minusDays(i);
            boolean found = false;

            // 检查每个日期是否已经在列表中
            for (DetectAlarmChartVO chart : detectAlarmChart) {
                if (chart.getAlarmDate().equals(date)) {
                    found = true;
                    break;
                }
            }

            // 如果日期不在列表中，添加到missingDates列表
            if (!found) {
                DetectAlarmChartVO detectAlarmChartVO = new DetectAlarmChartVO().setAlarmDate(date).setAlarmCount(0);
                detectAlarmChart.add(detectAlarmChartVO);
            }
        }
        detectAlarmChart.sort(Comparator.comparing(DetectAlarmChartVO::getAlarmDate));
        return MessageInfo.ok(detectAlarmChart);
    }

    @Override
    public MessageInfo<List<MonitorPointVO>> earlyWarningMonitoringPointStatistic(BaseParam param) {
        List<MonitorPointVO> monitorPointVOS = new ArrayList<>();
        List<ProcessParameterTag> processParameterTags = processParameterTagMapper.selectList(Wrappers.lambdaQuery(ProcessParameterTag.class).eq(StringUtil.isNotBlank(param.getAppId()), ProcessParameterTag::getAppId, param.getAppId()));
        Map<String, List<ProcessParameterTag>> processParameterByAppId = processParameterTags.stream()
                .filter(processParameterTag -> processParameterTag.getTagType() != null)
                .filter(processParameterTag -> processParameterTag.getStatus() != null)
                .filter(processParameterTag -> !processParameterTag.getTagType().equals("6"))
                .filter(processParameterTag -> !processParameterTag.getTagType().equals("7"))
                .filter(processParameterTag -> !processParameterTag.getTagType().equals("8"))
                .filter(processParameterTag -> processParameterTag.getStatus().equals("0"))
                .collect(Collectors.groupingBy(ProcessParameterTag::getAppId));

        for (Map.Entry<String, List<ProcessParameterTag>> appId : processParameterByAppId.entrySet()) {

            switch (appId.getKey()) {
                case "zhongshiyou":
                    MonitorPointVO monitorPointVO = new MonitorPointVO().setAppName("中石油").setPointNum((long) appId.getValue().size());
                    monitorPointVOS.add(monitorPointVO);
                    break;
                case "zhonghaiyou":
                    MonitorPointVO monitorPointVO1 = new MonitorPointVO().setAppName("中海油").setPointNum((long) appId.getValue().size());
                    monitorPointVOS.add(monitorPointVO1);
                    break;
                case "zhongshihua":
                    MonitorPointVO monitorPointVO2 = new MonitorPointVO().setAppName("中石化").setPointNum((long) appId.getValue().size());
                    monitorPointVOS.add(monitorPointVO2);
                    break;
                default:
                    break;
            }

        }

        return MessageInfo.ok(monitorPointVOS);
    }

    @Override
    public MessageInfo<TagAlarmQoqVO> getTagAlarmQoq(TagAlarmQoqVOParam param) {

        String cycleType = param.getCycleType();

        if (StringUtil.isBlank(cycleType)){
            cycleType = "day";
        }

        LocalDate now = LocalDate.now();
        LocalDate startPeriod, endPeriod, previousStartPeriod, previousEndPeriod;

        switch (cycleType) {
            case "day":
                startPeriod = now;
                endPeriod = now.plusDays(1);
                previousStartPeriod = now.minusDays(1);
                previousEndPeriod = now;
                break;
            case "week":
                startPeriod = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
                endPeriod = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)).plusDays(1);
                previousStartPeriod = startPeriod.minusWeeks(1);
                previousEndPeriod = startPeriod;
                break;
            case "month":
                startPeriod = now.with(TemporalAdjusters.firstDayOfMonth());
                endPeriod = now.with(TemporalAdjusters.lastDayOfMonth()).plusDays(1);
                previousStartPeriod = startPeriod.minusMonths(1);
                previousEndPeriod = startPeriod;
                break;
            default:
                throw new IllegalArgumentException("Unsupported cycle type: " + cycleType);
        }

        log.info("startPeriod:{},endPeriod:{},previousStartPeriod:{},previousEndPeriod:{}", startPeriod, endPeriod, previousStartPeriod, previousEndPeriod);

        List<TagAlarmClm> currentPeriodAlarms = tagAlarmClmService.list(Wrappers.lambdaQuery(TagAlarmClm.class)
                .ge(TagAlarmClm::getAlarmTimestamp, Date.from(startPeriod.atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .le(TagAlarmClm::getAlarmTimestamp, Date.from(endPeriod.atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
                .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
                .in(TagAlarmClm::getTagType, Arrays.asList("2", "3", "5"))
        );

        List<TagAlarmClm> previousPeriodAlarms = tagAlarmClmService.list(Wrappers.lambdaQuery(TagAlarmClm.class)
                .ge(TagAlarmClm::getAlarmTimestamp, Date.from(previousStartPeriod.atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .le(TagAlarmClm::getAlarmTimestamp, Date.from(previousEndPeriod.atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
                .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
                .in(TagAlarmClm::getTagType, Arrays.asList("2", "3", "5"))
        );

        TagAlarmQoqVO tagAlarmQoqVO = new TagAlarmQoqVO();
        tagAlarmQoqVO.setTemperatureAlarmNumber(currentPeriodAlarms.stream().filter(tagAlarmClm -> tagAlarmClm.getTagType().equals("2")).count());
        tagAlarmQoqVO.setPressureAlarmNumber(currentPeriodAlarms.stream().filter(tagAlarmClm -> tagAlarmClm.getTagType().equals("3")).count());
        tagAlarmQoqVO.setLiquidLevelAlarmNumber(currentPeriodAlarms.stream().filter(tagAlarmClm -> tagAlarmClm.getTagType().equals("5")).count());


        long prevTemperatureCount = previousPeriodAlarms.stream()
                .filter(tagAlarmClm -> tagAlarmClm.getTagType().equals("2"))
                .count();
        long prevPressureCount = previousPeriodAlarms.stream()
                .filter(tagAlarmClm -> tagAlarmClm.getTagType().equals("3"))
                .count();
        long prevLiquidLevelCount = previousPeriodAlarms.stream()
                .filter(tagAlarmClm -> tagAlarmClm.getTagType().equals("5"))
                .count();

        if (prevTemperatureCount > 0) {
            tagAlarmQoqVO.setTemperatureQoq((tagAlarmQoqVO.getTemperatureAlarmNumber() - prevTemperatureCount) / (double) prevTemperatureCount * 100 + "%");
        } else {
            tagAlarmQoqVO.setTemperatureQoq(tagAlarmQoqVO.getTemperatureAlarmNumber() * 100 + "%");
        }

        if (prevPressureCount > 0) {
            tagAlarmQoqVO.setPressureQoq((tagAlarmQoqVO.getPressureAlarmNumber() - prevPressureCount) / (double) prevPressureCount * 100 + "%");
        } else {
            tagAlarmQoqVO.setPressureQoq(tagAlarmQoqVO.getPressureAlarmNumber() * 100 + "%");
        }

        if (prevLiquidLevelCount > 0) {
            tagAlarmQoqVO.setLiquidLevelQoq((tagAlarmQoqVO.getLiquidLevelAlarmNumber() - prevLiquidLevelCount) / (double) prevLiquidLevelCount * 100 + "%");
        } else {
            tagAlarmQoqVO.setLiquidLevelQoq(tagAlarmQoqVO.getLiquidLevelAlarmNumber() * 100 + "%");
        }

        int size = currentPeriodAlarms.size();
        if (size == 0){
            size = 1;
        }

        tagAlarmQoqVO.setTemperatureAlarmRatio(tagAlarmQoqVO.getTemperatureAlarmNumber() / (double) size * 100 + "%");
        tagAlarmQoqVO.setPressureAlarmRatio(tagAlarmQoqVO.getPressureAlarmNumber() / (double) size * 100 + "%");
        tagAlarmQoqVO.setLiquidLevelAlarmRatio(tagAlarmQoqVO.getLiquidLevelAlarmNumber() / (double) size * 100 + "%");


        return MessageInfo.ok(tagAlarmQoqVO);
    }

    @Override
    public MessageInfo<List<TagAlarmQoqListVO>> getTagAlarmQoqList(TagAlarmQoqVOParam param) {


        String cycleType = param.getCycleType();

        if (StringUtil.isBlank(cycleType)){
            cycleType = "week";
        }

        LocalDate now = LocalDate.now();
        LocalDate startPeriod, endPeriod, previousStartPeriod, previousEndPeriod;

        switch (cycleType) {
            case "day":
                startPeriod = now;
                endPeriod = now.plusDays(1);
                previousStartPeriod = now.minusDays(1);
                previousEndPeriod = now;
                break;
            case "week":
                startPeriod = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
                endPeriod = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)).plusDays(1);
                previousStartPeriod = startPeriod.minusWeeks(1);
                previousEndPeriod = startPeriod;
                break;
            case "month":
                startPeriod = now.with(TemporalAdjusters.firstDayOfMonth());
                endPeriod = now.with(TemporalAdjusters.lastDayOfMonth()).plusDays(1);
                previousStartPeriod = startPeriod.minusMonths(1);
                previousEndPeriod = startPeriod;
                break;
            default:
                throw new IllegalArgumentException("Unsupported cycle type: " + cycleType);
        }


        param.setStartDate(startPeriod.atStartOfDay());
        param.setEndDate(endPeriod.atStartOfDay());
        List<TagAlarmQoqListVO> tagAlarmQoqNow = tagAlarmClmMapper.getTagAlarmQoqList(param);

        Set<String> targetTypes = new HashSet<>(Arrays.asList("温度", "压力", "液位"));
        Map<String, TagAlarmQoqListVO> typeToInstance = new HashMap<>();

        for (TagAlarmQoqListVO item : tagAlarmQoqNow) {
            if (targetTypes.contains(item.getTagType())) {
                typeToInstance.put(item.getTagType(), item);
            }
        }

        for (String type : targetTypes) {
            if (!typeToInstance.containsKey(type)) {
                TagAlarmQoqListVO newItem = new TagAlarmQoqListVO()
                        .setTagType(type)
                        .setThisCycleAlarmNumber(0L)
                        .setLastCycleAlarmNumber(0L)
                        .setQoq("0%");
                tagAlarmQoqNow.add(newItem);
            }
        }
        log.info("tagAlarmQoqNow:{}", tagAlarmQoqNow);

        param.setStartDate(previousStartPeriod.atStartOfDay());
        param.setEndDate(previousEndPeriod.atStartOfDay());
        List<TagAlarmQoqListVO> tagAlarmQoqPrevious = tagAlarmClmMapper.getTagAlarmQoqList(param);
        log.info("tagAlarmQoqPrevious:{}", tagAlarmQoqPrevious);


        tagAlarmQoqNow.forEach(tagAlarmQoqListVO -> {
            Long count = tagAlarmQoqPrevious.stream()
                    .filter(tagAlarmQoqListVO1 -> tagAlarmQoqListVO1.getTagType().equals(tagAlarmQoqListVO.getTagType()))
                    .findFirst()
                    .map(TagAlarmQoqListVO::getThisCycleAlarmNumber)
                    .orElse(0L);
            if (count > 0) {
                tagAlarmQoqListVO.setLastCycleAlarmNumber(count);
                log.info("count:{},tagAlarmQoqListVO:{}", count, tagAlarmQoqListVO);
                tagAlarmQoqListVO.setQoq((tagAlarmQoqListVO.getThisCycleAlarmNumber() - count) /  count * 100 + "%");
            } else {
                tagAlarmQoqListVO.setLastCycleAlarmNumber(0L);
                tagAlarmQoqListVO.setQoq(tagAlarmQoqListVO.getThisCycleAlarmNumber() * 100 + "%");
            }
        });



        long sum = tagAlarmQoqNow.stream().mapToLong(TagAlarmQoqListVO::getThisCycleAlarmNumber).sum();
        long lastSum = tagAlarmQoqNow.stream().mapToLong(TagAlarmQoqListVO::getLastCycleAlarmNumber).sum();
        //总和
        TagAlarmQoqListVO allQoq = new TagAlarmQoqListVO();
        if (lastSum > 0) {
            allQoq = new TagAlarmQoqListVO()
                    .setTagType("全部")
                    .setThisCycleAlarmNumber(sum).setLastCycleAlarmNumber(lastSum).setQoq((sum - lastSum) / (double) lastSum * 100 + "%");
        } else {
            allQoq = new TagAlarmQoqListVO()
                    .setTagType("全部")
                    .setThisCycleAlarmNumber(sum).setLastCycleAlarmNumber(lastSum).setQoq(sum * 100 + "%");
        }

        tagAlarmQoqNow.add(allQoq);

        return MessageInfo.ok(tagAlarmQoqNow);
    }

    @Override
    public MessageInfo<AlarmStatisticsVO> alarmStatistics(AlarmStatisticsParam param) {

        AlarmStatisticsVO alarmStatisticsVO = new AlarmStatisticsVO();
        List<TagProcessAlarmByUnit> tagProcessAlarmByUnits = tagAlarmClmMapper.selectTagProcessAlarmByUnit(param.getAppId());
        alarmStatisticsVO.setTagProcessAlarmByUnitList(tagProcessAlarmByUnits);


        List<AlarmStatisticByAppName> alarmNumberList = new ArrayList<>();


        Set<String> appNames = new HashSet<>(Arrays.asList("中海油", "中石油", "中石化"));
        Set<String> targetTypes = new HashSet<>(Arrays.asList("温度", "压力", "液位"));

        List<AlarmStatisticByAppIdByTagType> alarmStatisticByAppIdByTagTypes = tagAlarmClmMapper.alarmStatisticByAppIdByTagType(param);
        log.info("alarmStatisticByAppIdByTagTypes:{}", alarmStatisticByAppIdByTagTypes);
        for (String appName : appNames) {
            AlarmStatisticByAppName alarmStatisticByAppName = new AlarmStatisticByAppName();
            alarmStatisticByAppName.setAppName(appName);
            for (String targetType : targetTypes) {
                long sum = alarmStatisticByAppIdByTagTypes.stream()
                        .filter(alarmStatisticByAppIdByTagType -> alarmStatisticByAppIdByTagType.getTagType().equals(targetType))
                        .filter(alarmStatisticByAppIdByTagType -> alarmStatisticByAppIdByTagType.getAppName().equals(appName))
                        .mapToLong(AlarmStatisticByAppIdByTagType::getAlarmNumber).findFirst().orElse(0L);

                log.info("sum:{},targetType:{},appName:{}", sum, targetType, appName);

                switch (targetType)
                    {
                        case "温度":
                            alarmStatisticByAppName.setTemperatureAlarmNumber(sum);
                            break;
                        case "压力":
                            alarmStatisticByAppName.setPressureAlarmNumber(sum);
                            break;
                        case "液位":
                            alarmStatisticByAppName.setLiquidLevelAlarmNumber(sum);
                            break;
                        default:
                            break;
                    }
            }
            alarmNumberList.add(alarmStatisticByAppName);
        }

        alarmStatisticsVO.setAlarmNumberList(alarmNumberList);
        return MessageInfo.ok(alarmStatisticsVO);
    }

    @Override
    public MessageInfo<FireGasHazardAlarmVO> fireGasHazardAlarmStatistics(FireGasHazardAlarmParam param) {

        //近30天 火灾 可燃 有毒 报警总数
        FireGasHazardAlarmVO fireGasHazardAlarmVO = new FireGasHazardAlarmVO();

        //近一个月的时间
        LocalDateTime startPeriod = LocalDateTime.now().minusMonths(1);

        int fireCount = tagAlarmClmService.count(Wrappers.lambdaQuery(TagAlarmClm.class)
                .eq(TagAlarmClm::getAlarmType, "6")
                .ge(TagAlarmClm::getAlarmTimestamp, startPeriod)
                .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
                .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
        );

        int gasCount = tagAlarmClmService.count(Wrappers.lambdaQuery(TagAlarmClm.class)
                .eq(TagAlarmClm::getAlarmType, "7")
                .ge(TagAlarmClm::getAlarmTimestamp, startPeriod)
                .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
                .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
        );

        int hazardCount = tagAlarmClmService.count(Wrappers.lambdaQuery(TagAlarmClm.class)
                .eq(TagAlarmClm::getAlarmType, "8")
                .ge(TagAlarmClm::getAlarmTimestamp, startPeriod)
                .eq(StringUtil.isNotBlank(param.getAppId()), TagAlarmClm::getAppId, param.getAppId())
                .eq(StringUtil.isNotBlank(param.getPlatformId()), TagAlarmClm::getPlatformCode, param.getPlatformId())
        );

        fireGasHazardAlarmVO.setAlarmNumber((long) (fireCount + gasCount + hazardCount))
                .setFireAlarmNumber((long) fireCount)
                .setGasAlarmNumber((long) gasCount)
                .setHazardousAlarmNumber((long) hazardCount);
        if (fireCount + gasCount + hazardCount != 0){
            fireGasHazardAlarmVO.setFireAlarmRate(String.format("%.2f", (double) fireCount / (fireCount + gasCount + hazardCount) * 100)+"%")
                    .setGasAlarmRate(String.format("%.2f", (double) gasCount / (fireCount + gasCount + hazardCount) * 100)+"%")
                    .setHazardousAlarmRate(String.format("%.2f", (double) hazardCount / (fireCount + gasCount + hazardCount) * 100)+"%");
        }else {
            fireGasHazardAlarmVO.setFireAlarmRate("0.00%")
                    .setGasAlarmRate("0.00%")
                    .setHazardousAlarmRate("0.00%");
        }



        return MessageInfo.ok(fireGasHazardAlarmVO);
    }


}
