package com.tofly.custom.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.custom.entity.dto.StartEndTimeDto;
import com.tofly.custom.entity.dto.WisdomDisplayDto;
import com.tofly.custom.entity.vo.*;
import com.tofly.custom.mapper.CustomDisplayMapper;
import com.tofly.custom.service.CustomDisplayService;
import com.tofly.scada.entity.DeviceArchiveManage;
import com.tofly.scada.entity.ScadaReport;
import com.tofly.scada.service.DeviceArchiveManageService;
import com.tofly.scada.service.ScadaReportService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Service
@AllArgsConstructor
public class CustomDisplayServiceImpl implements CustomDisplayService {

    private final CustomDisplayMapper customDisplayMapper;
    private final ScadaReportService scadaReportService;
    private final DeviceArchiveManageService deviceService;


    @Override
    public List<DeviceArchiveManage> viewDeviceIndex(WisdomDisplayDto wis) {
        Integer statisticsType = wis.getStatisticsType();
        List<DeviceByTypeVo> voList = customDisplayMapper.getDeviceType();
        Integer tableType = wis.getTableType();
        String isQueryAlarm = wis.getIsQueryAlarm();
        String isQueryIndex = wis.getIsQueryIndex();
        if (tableType == null) {
            wis.setTableType(1);
        }
        if (statisticsType == null) {
            wis.setStatisticsType(0);
        }
        if (StringUtils.isBlank(isQueryAlarm)) {
            isQueryAlarm = "0";
        }
        if (StringUtils.isBlank(isQueryIndex)) {
            isQueryIndex = "0";
        }


        // 获取所有设备列表
        LambdaQueryWrapper<DeviceArchiveManage> wrapper = Wrappers.<DeviceArchiveManage>lambdaQuery()
                .in(CollUtil.isNotEmpty(wis.getDeviceCodes()), DeviceArchiveManage::getCode, wis.getDeviceCodes())
                .in(CollUtil.isNotEmpty(wis.getDeviceStatusList()), DeviceArchiveManage::getStatus, wis.getDeviceStatusList())
                .in(CollUtil.isNotEmpty(wis.getTypes()), DeviceArchiveManage::getType, wis.getTypes())
                .in(CollUtil.isNotEmpty(wis.getDeviceTypes()), DeviceArchiveManage::getDeviceType, wis.getDeviceTypes())
                .in(CollUtil.isNotEmpty(wis.getDeviceIds()), DeviceArchiveManage::getId, wis.getDeviceIds())
                .in(CollUtil.isNotEmpty(wis.getWaterStationIds()), DeviceArchiveManage::getWaterId, wis.getWaterStationIds())
                .like(StringUtils.isNotBlank(wis.getDeviceName()), DeviceArchiveManage::getName, wis.getDeviceName());
        if (StringUtils.isNotBlank(wis.getLikeStr()) && wis.getSearchOption() == 1) {
            wrapper.nested(x -> x.like(DeviceArchiveManage::getName, wis.getLikeStr()).or().
                    like(DeviceArchiveManage::getManufacturer, wis.getLikeStr()).or().
                    like(DeviceArchiveManage::getPhone, wis.getLikeStr()).or().
                    like(DeviceArchiveManage::getModelSpecification, wis.getLikeStr()).or().
                    like(DeviceArchiveManage::getCode, wis.getLikeStr()).or().
                    like(DeviceArchiveManage::getAddress, wis.getLikeStr()).or().
                    like(DeviceArchiveManage::getDescribe, wis.getLikeStr()));
        }
        List<DeviceArchiveManage> deviceList = deviceService.list(wrapper);
        for (DeviceArchiveManage device : deviceList) {
            DeviceByTypeVo vo = voList.stream().filter(item -> item.getDeviceType().equals(device.getDeviceType())).findFirst().orElse(null);
            if (vo != null) {
                device.setDeviceTypeName(vo.getDeviceTypeName());
            }
        }
        if (isQueryIndex.equals("0")) {
            return deviceList;
        }


        List<ScadaIndexNewVo> indexListAll = customDisplayMapper.getScadaIndexData(wis);
        List<ScadaReport> scadaReportList = scadaReportService.list();
        for (DeviceArchiveManage device : deviceList) {
            // 获取当前设备的所有指标

            List<ScadaIndexNewVo> indexListFinal = indexListAll.stream().filter(e -> Objects.equals(e.getDeviceId(), device.getId())).collect(Collectors.toList());
            if (CollUtil.isEmpty(indexListFinal)) {
                continue;
            }
            if (isQueryAlarm.equals("0")) {
                device.setIndexList(indexListFinal);
                continue;
            }
            // 获取指标报警信息
            for (ScadaIndexNewVo index : indexListFinal) {
                index.setIsAlarm("0");
                if (StringUtils.isBlank(index.getReportIds())) {
                    continue;
                }
                List<Long> reportIdList = Arrays.stream(index.getReportIds().split(",")).map(Long::parseLong).collect(Collectors.toList());
                List<ScadaReport> reportList = scadaReportList.stream().filter(e -> reportIdList.contains(e.getId())).collect(Collectors.toList());
                if (CollUtil.isEmpty(reportList)) {
                    continue;
                }

                for (ScadaReport report : reportList) {
                    Double value = Double.parseDouble(index.getIndexValue());
                    Double lower = Double.parseDouble(report.getReportLower());
                    Double upper = Double.parseDouble(report.getReportUpper());
                    if (value.compareTo(upper) <= 0 && value.compareTo(lower) >= 0) {
                        index.setIsAlarm("1");
                        index.setReportLevel(report.getReportLevel());
                        index.setReportLower(report.getReportLower());
                        index.setReportUpper(report.getReportUpper());
                    }
                }
            }
            device.setIndexList(indexListFinal);
            if (CollUtil.isNotEmpty(wis.getReportLevels())) {
                List<ScadaIndexNewVo> searchIndexVo = new ArrayList<>();
                for (String reportLevels : wis.getReportLevels()) {
                    List<ScadaIndexNewVo> result = indexListFinal.stream().filter(item -> StringUtils.isNotEmpty(item.getReportLevel())
                            && item.getReportLevel().contains(reportLevels)).collect(Collectors.toList());
                    searchIndexVo.addAll(result);
                }
                device.setIndexList(searchIndexVo);
            }
            if (CollUtil.isNotEmpty(wis.getIndexAlarmStatus())) {
                indexListFinal = device.getIndexList();
                List<ScadaIndexNewVo> searchIndexVo = new ArrayList<>();
                for (String alarmStatus : wis.getIndexAlarmStatus()) {
                    List<ScadaIndexNewVo> result = indexListFinal.stream().filter(item -> StringUtils.isNotEmpty(item.getIsAlarm())
                            && item.getIsAlarm().equals(alarmStatus)).collect(Collectors.toList());
                    searchIndexVo.addAll(result);
                }
                device.setIndexList(searchIndexVo);
            }
        }
        return deviceList;
    }

    @Override
    public List<ScadaIndexNewVo> getScadaIndexData(WisdomDisplayDto dto) {
        Integer statisticsType = dto.getStatisticsType();
        Integer tableType = dto.getTableType();
        String isQueryAlarm = dto.getIsQueryAlarm();
        if (tableType == null) {
            dto.setTableType(1);
        }
        if (statisticsType == null) {
            dto.setStatisticsType(0);
        }
        if (StringUtils.isBlank(isQueryAlarm)) {
            isQueryAlarm = "0";
        }

        List<ScadaIndexNewVo> scadaIndexVoList = customDisplayMapper.getScadaIndexData(dto);
        if (isQueryAlarm.equals("0")) {
            return scadaIndexVoList;
        }
        for (ScadaIndexNewVo scadaIndexVo : scadaIndexVoList) {
            scadaIndexVo.setTimeRange(dto.getStartDate() + "-" + dto.getEndDate());
        }
        if (CollUtil.isNotEmpty(dto.getContrastTimes())) {
            List<StartEndTimeDto> startEndTimes = dto.getContrastTimes();
            for (StartEndTimeDto startEndTime : startEndTimes) {
                if (StringUtils.isBlank(startEndTime.getStartTime()) || StringUtils.isBlank(startEndTime.getEndTime())) {
                    continue;
                }
                dto.setStartDate(startEndTime.getStartTime());
                dto.setEndDate(startEndTime.getEndTime());
                List<ScadaIndexNewVo> scadaIndexVosFinal = customDisplayMapper.getScadaIndexData(dto);
                if (CollUtil.isNotEmpty(scadaIndexVosFinal)) {
                    for (ScadaIndexNewVo scadaIndexVo : scadaIndexVosFinal) {
                        scadaIndexVo.setTimeRange(dto.getStartDate() + "-" + dto.getEndDate());
                    }
                    scadaIndexVoList.addAll(scadaIndexVosFinal);
                }
            }
        }
        List<ScadaReport> scadaReportList = scadaReportService.list();

        List<ScadaIndexNewVo> res = new ArrayList<>();
        for (ScadaIndexNewVo scadaIndexVo : scadaIndexVoList) {
            scadaIndexVo.setIsAlarm("0");
            if (StringUtils.isBlank(scadaIndexVo.getReportIds())) {
                if (CollUtil.isEmpty(dto.getReportLevels())) {
                    res.add(scadaIndexVo);
                }
                continue;
            }
            List<Long> reportIdList = Arrays.stream(scadaIndexVo.getReportIds().split(",")).map(Long::parseLong).collect(Collectors.toList());
            List<ScadaReport> reportList = scadaReportList.stream().filter(e -> reportIdList.contains(e.getId())).collect(Collectors.toList());
            if (CollUtil.isEmpty(reportList)) {
                if (CollUtil.isEmpty(dto.getReportLevels())) {
                    res.add(scadaIndexVo);
                }
                continue;
            }
            for (ScadaReport report : reportList) {
                Double value = Double.parseDouble(scadaIndexVo.getIndexValue());
                if (value.compareTo(Double.parseDouble(report.getReportLower())) >= 0
                        && value.compareTo(Double.parseDouble(report.getReportUpper())) <= 0) {
                    scadaIndexVo.setIsAlarm("1");
                    scadaIndexVo.setReportLevel(report.getReportLevel());
                    scadaIndexVo.setReportLower(report.getReportLower());
                    scadaIndexVo.setReportUpper(report.getReportUpper());
                    break;
                }
            }
            // 筛选报警等级
            if (CollUtil.isNotEmpty(dto.getReportLevels()) && StringUtils.isBlank(scadaIndexVo.getReportLevel())) {
                continue;
            }
            if (CollUtil.isNotEmpty(dto.getReportLevels())
                    && StringUtils.isNotBlank(scadaIndexVo.getReportLevel())
                    && !dto.getReportLevels().contains(scadaIndexVo.getReportLevel())) {
                continue;
            }
            res.add(scadaIndexVo);
        }
        return res;
    }


    @Override
    public Page<ScadaIndexVo> getHistoryPageData(Page page, WisdomDisplayDto dto) {
        return customDisplayMapper.getHistoryPageData(page, dto);
    }

    /**
     * @param startDate  开始时间
     * @param endDate 结束时间
     * @param type 0小时 1天 2月 3年
     * @description 获取时间列表
     */
    List<String> getDates(String startDate, String endDate, String type) {
        List<String> dates = new ArrayList<>();
        Calendar cal = Calendar.getInstance();
        cal.setTime(DateUtil.parse(startDate, "yyyy-MM-dd HH:mm:ss"));
        while (DateUtil.format(cal.getTime(), "yyyy-MM-dd HH:mm:ss").compareTo(endDate) <= 0) {
            switch (type) {
                case "0":
                    dates.add(DateUtil.format(cal.getTime(), "yyyy-MM-dd HH"));
                    cal.add(Calendar.HOUR_OF_DAY, +1);
                    break;
                case "1":
                    dates.add(DateUtil.format(cal.getTime(), "yyyy-MM-dd"));
                    cal.add(Calendar.DAY_OF_MONTH, +1);
                    break;
                case "2":
                    dates.add(DateUtil.format(cal.getTime(), "yyyy-MM"));
                    cal.add(Calendar.MONTH, +1);
                    break;
                case "3":
                    dates.add(DateUtil.format(cal.getTime(), "yyyy"));
                    cal.add(Calendar.YEAR, +1);
                    break;
            }
        }
        return dates;
    }

}