package com.njcn.process.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.HttpResultUtil;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.biz.pojo.dto.CommMonitorInfoDTO;
import com.njcn.device.biz.pojo.param.MonitorGetParam;
import com.njcn.device.pms.api.MonitorClient;
import com.njcn.device.pms.pojo.dto.PmsMonitorDTO;
import com.njcn.device.pms.pojo.param.PmsMonitorParam;
import com.njcn.harmonic.api.RStatLimitRateDClient;
import com.njcn.harmonic.pojo.param.RStatLimitQueryParam;
import com.njcn.harmonic.pojo.po.day.RStatLimitRateDPO;
import com.njcn.harmonic.pojo.vo.ThsStrategyVo;
import com.njcn.oss.constant.OssPath;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.prepare.harmonic.pojo.dto.SuperviseDto;
import com.njcn.process.api.FlowableDefineFeignClient;
import com.njcn.process.pojo.dto.ThsStrategyBindDTO;
import com.njcn.process.pojo.param.SuperviseParam;
import com.njcn.process.pojo.po.ThsOverRunLog;
import com.njcn.process.pojo.po.ThsSupervise;
import com.njcn.process.pojo.vo.SuperviceRunLogVo;
import com.njcn.process.pojo.vo.SuperviseVo;
import com.njcn.process.pojo.vo.ThsSuperviseVo;
import com.njcn.harmonic.annotaion.HarCurrent;
import com.njcn.harmonic.annotaion.HarVoltage;
import com.njcn.harmonic.annotaion.InterharVoltage;
import com.njcn.process.enums.*;
import com.njcn.process.mapper.*;
import com.njcn.process.pojo.param.FileParam;
import com.njcn.process.pojo.param.ThsSuperviseParam;
import com.njcn.process.pojo.po.FlowableAss;
import com.njcn.process.pojo.po.ThsAlarmFormwork;
import com.njcn.process.pojo.po.ThsWarnStrategyAss;
import com.njcn.process.pojo.vo.flowable.FlowTaskVo;
import com.njcn.process.service.ThsOverRunLogService;
import com.njcn.process.service.ThsSuperviseService;
import com.njcn.process.service.flowable.IFlowDefinitionService;
import com.njcn.process.service.flowable.IFlowTaskService;
import com.njcn.process.utils.ReadPatientExcelUtil;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.api.UserFeignClient;
import com.njcn.user.pojo.po.Dept;
import com.njcn.user.pojo.po.User;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.RequestUtil;
import liquibase.pro.packaged.S;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.njcn.process.enums.SteadyIndicatorEnum.Negative_Voltage;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lxp
 * @since 2023-03-16
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ThsSuperviseServiceImpl extends ServiceImpl<ThsSuperviseMapper, ThsSupervise> implements ThsSuperviseService {


    private final ThsWarnStrategyMapper thsWarnStrategyMapper;

    private final ThsWarnStrategyAssMapper thsWarnStrategyAssMapper;

    private final MonitorClient monitorClient;

    private final DicDataFeignClient dicDataFeignClient;

    private final ThsSuperviseMapper thsSuperviseMapper;

    private final ThsOverRunLogService thsOverRunLogService;

    private final DeptFeignClient deptFeignClient;

    private final FileStorageUtil fileStorageUtil;

    private final ThsAlarmFormworkMapper thsAlarmFormworkMapper;

    private final IFlowDefinitionService iFlowDefinitionService;


    private final IFlowTaskService iFlowTaskService;


    private final FlowableAssMapper flowableAssMapper;

    private final IFlowDefinitionService flowDefinitionService;


    private final CommTerminalGeneralClient commTerminalGeneralClient;

    private final RStatLimitRateDClient rStatLimitRateDClient;

    private final UserFeignClient userFeignClient;


    /**
     * 构建技术监督名称
     *
     * @param thsSupervise
     * @param overRunLogList
     * @param dept
     */
    private void buildSuperviseName(ThsSupervise thsSupervise, List<ThsOverRunLog> overRunLogList, Dept dept) {
        if (CollectionUtil.isNotEmpty(overRunLogList)) {
            thsSupervise.setDescription(overRunLogList.get(0).getDescription());
            String str = Arrays.asList(overRunLogList.get(0).getDescription().split(",")).get(0);
            String overItem = str.substring(0, str.indexOf("次") - 1);
            thsSupervise.setName(DateUtil.today() + dept.getName() + overRunLogList.get(0).getName() + "等" + overRunLogList.size() + "个监测点" + overItem);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOverRunLog(SuperviceRunLogVo superviceRunLogVo) {
        if (CollectionUtil.isNotEmpty(superviceRunLogVo.getOverRunLog())) {
            ThsSupervise thsSupervise = superviceRunLogVo.getThsSupervise();
            HttpResult<Dept> deptById = deptFeignClient.getDeptById(thsSupervise.getDeptId());
            Dept dept = deptById.getData();
            Date date = new Date();
            thsSupervise.setCreateTime(date);
            thsSupervise.setCreateUser(RequestUtil.getUsername());
            //thsSupervise.setModifyUser(RequestUtil.getUsername());
            //thsSupervise.setModifyTime(date);
            thsSupervise.setSupIndex(IdUtil.simpleUUID());
            this.buildSuperviseName(thsSupervise, superviceRunLogVo.getOverRunLog(), dept);
            this.save(thsSupervise);
            //TODO 解决工作流写死问题
            flowableRun(thsSupervise);

            for (ThsOverRunLog thsOverRunLog : superviceRunLogVo.getOverRunLog()) {
                thsOverRunLog.setCreateTime(date);
                thsOverRunLog.setSupIndex(thsSupervise.getSupIndex());
                thsOverRunLogService.save(thsOverRunLog);
            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResult deleteSupervise(SuperviseDto superviseDto) {
        if (CollectionUtil.isNotEmpty(superviseDto.getDeleteIds())) {
            superviseDto.getDeleteIds().forEach(id -> {
                thsOverRunLogService.remove(new LambdaQueryWrapper<ThsOverRunLog>().eq(ThsOverRunLog::getSupIndex, id));
                thsSuperviseMapper.delete(new LambdaQueryWrapper<ThsSupervise>().eq(ThsSupervise::getSupIndex, id));

                //删除同时删除工作流程
                FlowableAss flowableAss = flowableAssMapper.selectById(id);
                if (Objects.nonNull(flowableAss)) {
                    iFlowDefinitionService.deleteInstance(flowableAss.getExecIndex(), "");
                    flowableAssMapper.deleteById(id);
                }

            });
        }

        return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, "删除技术监督");
    }


    @Override
    public Page<SuperviseVo> querySuperviseList(SuperviseDto superviseDto) {
        Integer pageNum = PageFactory.getPageNum(superviseDto);
        Integer pageSize = PageFactory.getPageSize(superviseDto);
        Page<SuperviseVo> superviseVoPage = new Page<>(pageNum, pageSize);
        Page<SuperviseVo> page = thsSuperviseMapper.querySupervisePage(superviseVoPage, superviseDto);
        List<SuperviseVo> pageRecords = page.getRecords();
        if (CollectionUtil.isNotEmpty(pageRecords)) {
            for (SuperviseVo superviseVo : pageRecords) {
                superviseVo.setCompanyName(deptFeignClient.getDeptById(superviseVo.getDeptId()).getData().getName());
                List<ThsOverRunLog> thsOverRunLogs = thsOverRunLogService.list(new LambdaQueryWrapper<ThsOverRunLog>().eq(ThsOverRunLog::getSupIndex, superviseVo.getSupIndex()));
                if (CollectionUtil.isNotEmpty(thsOverRunLogs)) {
                    List<String> alarmTickets = thsOverRunLogs.stream().filter(r -> StringUtils.isNotBlank(r.getAlarmTicket())).map(ThsOverRunLog::getAlarmTicket).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(alarmTickets)) {
                        superviseVo.setHaveAlarmticket(true);
                    }
                    List<String> feedbacks = thsOverRunLogs.stream().filter(r -> StringUtils.isNotBlank(r.getFeedback())).map(ThsOverRunLog::getFeedback).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(feedbacks)) {
                        superviseVo.setHaveFeedback(true);
                    }
                    List<String> testReports = thsOverRunLogs.stream().filter(r -> StringUtils.isNotBlank(r.getTestReport())).map(ThsOverRunLog::getTestReport).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(testReports)) {
                        superviseVo.setHaveTestReport(true);
                    }
                    List<String> reviseNotices = thsOverRunLogs.stream().filter(r -> StringUtils.isNotBlank(r.getReviseNotice())).map(ThsOverRunLog::getReviseNotice).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(reviseNotices)) {
                        superviseVo.setHaveReviseNotice(true);
                    }
                    List<String> reviseFeedbacks = thsOverRunLogs.stream().filter(r -> StringUtils.isNotBlank(r.getReviseFeedback())).map(ThsOverRunLog::getReviseFeedback).collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(reviseFeedbacks)) {
                        superviseVo.setHaveReviseFeedback(true);
                    }
                }
            }
        }
        page.setRecords(pageRecords);
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void uploadSuperviseTicket(String id, String supIndex, Integer ticketType, MultipartFile[] files, HttpServletResponse response) {
        ThsSupervise thsSupervise = new ThsSupervise();
        thsSupervise.setSupIndex(supIndex);
        ThsSupervise thsSuperObj = thsSuperviseMapper.selectById(supIndex);

        List<ThsOverRunLog> thsOverRunLogList = thsOverRunLogService.list(new LambdaQueryWrapper<ThsOverRunLog>().eq(ThsOverRunLog::getSupIndex, supIndex));

        if (files != null && files.length == 1) {
            ThsOverRunLog thsOverRunLog = thsOverRunLogService.getById(id);
            thsOverRunLog.setId(id);
            String path = fileStorageUtil.uploadMultipart(files[0], OssPath.ELECTRICITY_QUALITY);
            this.updateSuperviesData(path, thsOverRunLog, ticketType, thsSupervise);
        }
        if (files != null && files.length > 1) {
            if (files.length != thsOverRunLogList.size()) {
                throw new BusinessException("批量上传需保证报告数量与测点数量一致");
            }

            this.batchUploadFile(thsSupervise, thsOverRunLogList, files, ticketType);
        }
        this.updateProcess(thsSupervise, ticketType, thsSuperObj.getType(), thsOverRunLogList, files.length);


    }

    /**
     * 执行流程
     * @author cdf
     * @date 2024/3/19
     */
    private void flowableRun(ThsSupervise thsSupervise){
        Map<String, Object> mapParam = new HashMap<>();
        String proInId = "";
        if (thsSupervise.getType() == 0) {
            proInId = "flow_yzep99kb:1:a100b48b-da75-11ed-8335-b07b253cdad9";
        } else {
            proInId = "flow_yzep99kb:2:6358e099-dcba-11ed-8026-b07b253cdad9";
        }
        iFlowDefinitionService.startProcessInstanceById(proInId, thsSupervise.getSupIndex(),55, mapParam);
    }

    /**
     * 更新技术监督流程
     *
     * @param thsSupervise
     * @param ticketType
     * @param type
     */
    private void updateProcess(ThsSupervise thsSupervise, Integer ticketType, Integer type, List<ThsOverRunLog> thsOverRunLogList, Integer uploadCount) {
        TicketTypeEnum ticketTypeEnum = TicketTypeEnum.getTicketTypeEnumByCode(ticketType);
        if (ticketTypeEnum == null) {
            throw new BusinessException("上传单据参数类型错误！");
        }

        long count = 0;
        switch (ticketTypeEnum) {

            case FEEDBACK:
                count = thsOverRunLogList.stream().filter(item -> Objects.isNull(item.getFeedback())).count();
                if (uploadCount == count) {
                    thsSupervise.setProgress(ProgressEnum.TEST_REPORT.getCode());
                }
                break;
            case TEST_REPORT:
                if (AlarmTypeEnum.EARLY_WARN.getCode().equals(type)) {
                    thsSupervise.setProgress(ProgressEnum.END.getCode());
                } else {
                    thsSupervise.setProgress(ProgressEnum.REVISE_NOTICE_ISSUE.getCode());
                }
                break;
            case REVISE_FEEDBACK:
                thsSupervise.setProgress(ProgressEnum.END.getCode());
                break;
        }

        if (uploadCount == count) {
            //默认上传报告后当前流程结束
            FlowableAss flowableAss = flowableAssMapper.selectById(thsSupervise.getSupIndex());
            Task task = iFlowTaskService.getTask(flowableAss.getExecIndex());

            FlowTaskVo flowTaskVo = new FlowTaskVo();
            flowTaskVo.setAssignee(RequestUtil.getUserIndex());
            flowTaskVo.setTaskId(task.getId());

            iFlowTaskService.complete(flowTaskVo);
        }

        thsSupervise.setModifyTime(new Date());
        thsSuperviseMapper.update(thsSupervise, new LambdaQueryWrapper<ThsSupervise>().eq(ThsSupervise::getSupIndex, thsSupervise.getSupIndex()));
    }

    /**
     * 批量上传文件
     *
     * @param thsSupervise
     * @param thsOverRunLogs
     * @param files
     * @param ticketType
     */
    private void batchUploadFile(ThsSupervise thsSupervise, List<ThsOverRunLog> thsOverRunLogs, MultipartFile[] files, Integer ticketType) {
        if (files != null && files.length > 1) {
            List<ThsOverRunLog> excelData = new ArrayList<>();
            for (int i = 0; i < files.length; i++) {
                String originalFilename = files[i].getOriginalFilename();
                String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
                if (".xls".equalsIgnoreCase(fileType) || ".xlsx".equalsIgnoreCase(fileType)) {
                    excelData = ReadPatientExcelUtil.getExcelInfo(files[i]);
                }
            }
            if (CollectionUtil.isEmpty(excelData)) {
                throw new BusinessException("没有Excel文件,或Excel文件无数据！");
            }
            for (ThsOverRunLog thsOverRunLogDto : excelData) {
                for (ThsOverRunLog thsOverRunLog : thsOverRunLogs) {
                    if (StringUtils.equals(thsOverRunLog.getLineIndexName(), thsOverRunLogDto.getLineIndexName()) &&
                            StringUtils.equals(thsOverRunLog.getName(), thsOverRunLogDto.getName())) {
                        for (int i = 0; i < files.length; i++) {
                            String originalFilename = files[i].getOriginalFilename();
                            String filename = originalFilename.substring(0, originalFilename.lastIndexOf("."));
                            if (StringUtils.equals(filename, thsOverRunLogDto.getLineIndexName())) {
                                this.uploadFile(files[i], ticketType, thsOverRunLog, thsSupervise);
                            }
                        }
                    }
                }
            }
        }
    }

    private void uploadFile(MultipartFile file, Integer ticketType, ThsOverRunLog thsOverRunLog, ThsSupervise thsSupervise) {
        String path = fileStorageUtil.uploadMultipart(file, OssPath.ELECTRICITY_QUALITY);
        this.updateSuperviesData(path, thsOverRunLog, ticketType, thsSupervise);
    }

    /**
     * 更新技术监督监测点数据
     *
     * @param path
     * @param thsOverRunLog
     * @param ticketType
     * @param thsSupervise
     */
    private void updateSuperviesData(String path, ThsOverRunLog thsOverRunLog, Integer ticketType, ThsSupervise thsSupervise) {
        TicketTypeEnum ticketTypeEnum = TicketTypeEnum.getTicketTypeEnumByCode(ticketType);
        if (ticketTypeEnum == null) {
            throw new BusinessException("上传单据参数类型错误！");
        }
        switch (ticketTypeEnum) {
            case ALARM_TICKET:
                thsOverRunLog.setAlarmTicket(path);
                break;
            case FEEDBACK:
                thsOverRunLog.setFeedback(path);
                break;
            case TEST_REPORT:
                thsOverRunLog.setTestReport(path);
                break;
            case REVISE_NOTICE:
                thsOverRunLog.setTestReport(path);
                break;
            case REVISE_FEEDBACK:
                thsOverRunLog.setReviseFeedback(path);
                break;
        }
        thsOverRunLogService.updateById(thsOverRunLog);
    }


    @Override
    public List<Map<Integer, String>> queryProgressValues() {
        List<Map<Integer, String>> list = new ArrayList<>();
        Arrays.asList(ProgressEnum.values()).forEach(value -> {
            Map<Integer, String> progress = new HashMap<>();
            progress.put(value.getCode(), value.getMessage());
            list.add(progress);
        });
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void uploadAlarmFormwork(Integer type, Integer formworkType, MultipartFile file, HttpServletResponse response) {
        thsAlarmFormworkMapper.delete(new LambdaQueryWrapper<ThsAlarmFormwork>().eq(ThsAlarmFormwork::getFormworkType, formworkType)
                .eq(ThsAlarmFormwork::getType, type));
        String path = fileStorageUtil.uploadMultipart(file, OssPath.ELECTRICITY_QUALITY);
        ThsAlarmFormwork alarmFormwork = new ThsAlarmFormwork();
        alarmFormwork.setId(IdUtil.simpleUUID());
        alarmFormwork.setType(type);
        alarmFormwork.setFormworkType(formworkType);
        alarmFormwork.setPath(path);
        thsAlarmFormworkMapper.insert(alarmFormwork);


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String dowloadAlarmFormwork(Integer type, Integer formworkType, String supIndex, HttpServletResponse response) {
        ThsAlarmFormwork thsAlarmFormwork = thsAlarmFormworkMapper.selectOne(new LambdaQueryWrapper<ThsAlarmFormwork>().eq(ThsAlarmFormwork::getFormworkType, formworkType)
                .eq(ThsAlarmFormwork::getType, type).last("limit 1"));
        if (thsAlarmFormwork == null) {
            throw new BusinessException("请先上传下发单模板单据！");
        }
        String fileUrl = fileStorageUtil.getFileUrl(thsAlarmFormwork.getPath());


        ThsSupervise thsSupervise = new ThsSupervise();
        thsSupervise.setModifyTime(new Date());
        thsSupervise.setModifyUser(RequestUtil.getUserIndex());
        ThsOverRunLog thsOverRunLog = new ThsOverRunLog();
        thsOverRunLog.setSupIndex(supIndex);
        if (FormworkTypeEnum.ALARM_TICKET.getCode().equals(formworkType)) {
            thsSupervise.setProgress(ProgressEnum.FEEDBACK_UPLOAD.getCode());
            thsOverRunLog.setAlarmTicket(thsAlarmFormwork.getPath());
        }
        if (FormworkTypeEnum.RECTIFY_TICKET.getCode().equals(formworkType)) {
            thsSupervise.setProgress(ProgressEnum.REVISE_FEEDBACK.getCode());
            thsOverRunLog.setReviseNotice(thsAlarmFormwork.getPath());
        }
        thsOverRunLogService.update(thsOverRunLog, new LambdaQueryWrapper<ThsOverRunLog>().eq(ThsOverRunLog::getSupIndex, supIndex));
        thsSuperviseMapper.update(thsSupervise, new LambdaQueryWrapper<ThsSupervise>().eq(ThsSupervise::getSupIndex, supIndex));


        FlowableAss flowableAss = flowableAssMapper.selectById(supIndex);
        Task task = iFlowTaskService.getTask(flowableAss.getExecIndex());

        FlowTaskVo flowTaskVo = new FlowTaskVo();
        flowTaskVo.setAssignee(RequestUtil.getUserIndex());
        flowTaskVo.setTaskId(task.getId());

        iFlowTaskService.complete(flowTaskVo);
        return fileUrl;
    }

    @Override
    public ThsSuperviseVo superviseIndex(SuperviseDto superviseDto) {


        List<SuperviseVo> querySuperviseList = thsSuperviseMapper.querySuperviseList(superviseDto);


        ThsSuperviseVo thsSuperviseVo = new ThsSuperviseVo();
        if (CollectionUtil.isNotEmpty(querySuperviseList)) {

            List<String> userIds = querySuperviseList.stream().map(SuperviseVo::getModifyUser).filter(Objects::nonNull).distinct().collect(Collectors.toList());

            List<User> userList = userFeignClient.getUserByIdList(userIds).getData();
            Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));

            List<String> deptIds = querySuperviseList.stream().map(SuperviseVo::getDeptId).distinct().collect(Collectors.toList());

            List<Dept> deptList = deptFeignClient.getDeptInfoListByIds(deptIds).getData();
            Map<String, Dept> deptMap = deptList.stream().collect(Collectors.toMap(Dept::getId, Function.identity()));

            for (SuperviseVo superviseVo : querySuperviseList) {

                if(StrUtil.isNotBlank(superviseVo.getModifyUser())) {
                    superviseVo.setModifyUser(userMap.get(superviseVo.getModifyUser()).getName());
                }

                if(StrUtil.isNotBlank(superviseVo.getDeptId())) {
                    superviseVo.setCompanyName(deptMap.get(superviseVo.getDeptId()).getName());
                }
                //处理预警类型

                Date modifyTime = superviseVo.getModifyTime();
                if (Objects.nonNull(modifyTime)) {

                    Long progressTime = DateUtil.between(modifyTime, new Date(), DateUnit.DAY);
                    superviseVo.setProgressTime(progressTime.intValue());
                    switch (ProgressEnum.getProgressEnumByCode(superviseVo.getProgress())) {
                        case START:

                        case ALARM_TICKET_ISSUE:
                            if (progressTime >= 1) {
                                superviseVo.setAlertType(AlertTypeEnum.RED.getCode());
                            } else {
                                superviseVo.setAlertType(AlertTypeEnum.BLACK.getCode());
                            }
                            break;
                        default:
                            if (progressTime >= 10) {
                                superviseVo.setAlertType(AlertTypeEnum.RED.getCode());
                            } else if (progressTime >= 8) {
                                superviseVo.setAlertType(AlertTypeEnum.ORANGE.getCode());
                            } else if (progressTime >= 5) {
                                superviseVo.setAlertType(AlertTypeEnum.YELLOW.getCode());
                            } else {
                                superviseVo.setAlertType(AlertTypeEnum.BLACK.getCode());
                            }
                            break;
                    }
                }
            }
            thsSuperviseVo.setSuperviseVoList(querySuperviseList);
            //分组计算每种流程状态的数量
            Map<Integer, List<SuperviseVo>> map = querySuperviseList.stream().collect(Collectors.groupingBy(SuperviseVo::getProgress));
            for (Map.Entry<Integer, List<SuperviseVo>> entry : map.entrySet()) {
                Integer code = entry.getKey();
                switch (ProgressEnum.getProgressEnumByCode(code)) {
                    case START:
                        thsSuperviseVo.setStartNum(entry.getValue().size());
                        break;
                    case ALARM_TICKET_ISSUE:
                        thsSuperviseVo.setAlarmTicketIssueNum(entry.getValue().size());
                        break;
                    case FEEDBACK_UPLOAD:
                        thsSuperviseVo.setFeedbackUploadNum(entry.getValue().size());
                        break;
                    case TEST_REPORT:
                        thsSuperviseVo.setTestReportNum(entry.getValue().size());
                        break;
                    case REVISE_NOTICE_ISSUE:
                        thsSuperviseVo.setReviseFeedbackNum(entry.getValue().size());
                        break;
                    case REVISE_FEEDBACK:
                        thsSuperviseVo.setReviseFeedbackNum(entry.getValue().size());
                        break;
                    case END:
                        thsSuperviseVo.setEndNum(entry.getValue().size());
                        break;
                }
            }
            //分组计算预/告警单数量
            Map<Integer, List<SuperviseVo>> typeMap = querySuperviseList.stream().collect(Collectors.groupingBy(SuperviseVo::getType));
            for (Map.Entry<Integer, List<SuperviseVo>> entry : typeMap.entrySet()) {
                Integer code = entry.getKey();
                switch (AlarmTypeEnum.getAlarmTypeEnumByCode(code)) {
                    case EARLY_WARN:
                        thsSuperviseVo.setEarlyWarnNum(entry.getValue().size());
                        break;
                    case REPORT_WARN:
                        thsSuperviseVo.setReportWarnNum(entry.getValue().size());
                        break;
                }
            }
        }
        return thsSuperviseVo;
    }


    @Override
    public HttpServletResponse downloadFeedBackFile(FileParam fileParam, HttpServletRequest request, HttpServletResponse response) {
        TicketTypeEnum ticketTypeEnum = TicketTypeEnum.getTicketTypeEnumByCode(fileParam.getTicketType());
        if (ticketTypeEnum == null) {
            throw new BusinessException("上传单据参数类型错误！");
        }
        List<ThsOverRunLog> thsOverRunLogs = thsOverRunLogService.list(new LambdaQueryWrapper<ThsOverRunLog>().in(ThsOverRunLog::getId, fileParam.getIds()));
        if (CollectionUtil.isNotEmpty(thsOverRunLogs)) {
            Map<String, String> filePathMap = new HashedMap();
            switch (ticketTypeEnum) {
                case FEEDBACK:
                    filePathMap = thsOverRunLogs.stream().filter(r -> StringUtils.isNotBlank(r.getFeedback())).collect(Collectors.toMap(ThsOverRunLog::getId, ThsOverRunLog::getFeedback));
                    break;
                case TEST_REPORT:
                    filePathMap = thsOverRunLogs.stream().filter(r -> StringUtils.isNotBlank(r.getTestReport())).collect(Collectors.toMap(ThsOverRunLog::getId, ThsOverRunLog::getTestReport));

                    break;
                case REVISE_FEEDBACK:
                    filePathMap = thsOverRunLogs.stream().filter(r -> StringUtils.isNotBlank(r.getReviseFeedback())).collect(Collectors.toMap(ThsOverRunLog::getId, ThsOverRunLog::getReviseFeedback));

                    break;
            }
            response = this.dowloadZipFile(fileParam, filePathMap, request, response, ticketTypeEnum);
        }
        return response;
    }


    /**
     * 生成预警单告警单(自动)
     *
     * @author cdf
     * @date 2024/1/29
     */
    @Override
    public SuperviceRunLogVo initSupervise(SuperviseParam superviseParam) {
        SuperviceRunLogVo superviceRunLogVo = new SuperviceRunLogVo();

        List<ThsSupervise> thsSuperviseListPO = new ArrayList<>();
        List<ThsOverRunLog> allThsLogPO = new ArrayList<>();

        String yesterday = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN));
        List<DictData> dictTargetList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.STEADY_STATIS.getCode()).getData();

        List<ThsStrategyVo> thsStrategyList = this.thsWarnStrategyMapper.selectStrategyList(superviseParam);
        //按部门进行分组

        List<ThsStrategyBindDTO> thsStrategyBindDTOList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(thsStrategyList)) {

            List<ThsStrategyVo> threeLevel = thsStrategyList.stream().filter(r -> GradeEnum.THREE_LEVEL.getCode().equals(r.getGrade())).collect(Collectors.toList());//三级策略集合
            //获取排他策略集合
            if(CollectionUtil.isNotEmpty(threeLevel)){
                threeLevel.forEach(i->assBindList(i, thsStrategyBindDTOList));
            }
            Map<String, ThsStrategyBindDTO> deleteMap = thsStrategyBindDTOList.stream().collect(Collectors.toMap(ThsStrategyBindDTO::getKeyId, Function.identity()));

            List<ThsStrategyVo> oneLevel = thsStrategyList.stream().filter(r -> !GradeEnum.THREE_LEVEL.getCode().equals(r.getGrade())).collect(Collectors.toList());//一级或二级策略集合
            Map<String, List<ThsStrategyVo>> deptMap = oneLevel.stream().collect(Collectors.groupingBy(ThsStrategyVo::getDeptId));
            for (Map.Entry<String, List<ThsStrategyVo>> entry : deptMap.entrySet()) {
                String depId = entry.getKey();
                Dept dept = deptFeignClient.getDeptById(depId).getData();

                List<ThsOverRunLog> thsOverRunLogList = new ArrayList<>();
                ThsSupervise thsSupervise = null;
                List<ThsStrategyVo> deptStrategyList = entry.getValue();
                if (CollectionUtil.isNotEmpty(deptStrategyList)) {

                    //遍历当前部门下面的所有策略
                    for (ThsStrategyVo oneStrategyVo : deptStrategyList) {
                        List<ThsStrategyBindDTO> useBindDTOList = new ArrayList<>();
                        assBindList(oneStrategyVo,useBindDTOList);
                        //根据排他策略过滤12级策略
                        Iterator<ThsStrategyBindDTO> iterator = useBindDTOList.iterator();
                        while (iterator.hasNext()) {
                            ThsStrategyBindDTO item = iterator.next();
                            if (deleteMap.containsKey(item.getKeyId())) {
                                item.getTargetIds().removeAll(deleteMap.get(item.getKeyId()).getTargetIds());
                                if (CollectionUtil.isEmpty(item.getTargetIds())) {
                                    iterator.remove();
                                }
                            }
                        }

                        //过滤排他策略后开始组装信息
                        List<ThsStrategyBindDTO> tagObj = useBindDTOList.stream().filter(item -> item.getType() == 0).collect(Collectors.toList());
                        List<String> useTagIds = tagObj.stream().map(ThsStrategyBindDTO::getKeyId).collect(Collectors.toList());
                        Map<String, ThsStrategyBindDTO> tagMap = tagObj.stream().collect(Collectors.toMap(ThsStrategyBindDTO::getKeyId, Function.identity()));

                        List<ThsStrategyBindDTO> monitorObj = useBindDTOList.stream().filter(item -> item.getType() == 1).collect(Collectors.toList());
                        List<String> useMonitorIds = monitorObj.stream().map(ThsStrategyBindDTO::getKeyId).collect(Collectors.toList());
                        Map<String, ThsStrategyBindDTO> monitorMap = monitorObj.stream().collect(Collectors.toMap(ThsStrategyBindDTO::getKeyId, Function.identity()));

                        MonitorGetParam monitorGetParam = new MonitorGetParam();
                        monitorGetParam.setTagList(useTagIds);
                        monitorGetParam.setMonitorIds(useMonitorIds);
                        monitorGetParam.setDeptIds(Stream.of(dept.getId()).collect(Collectors.toList()));
                        //TODO 需要校验
                        List<CommMonitorInfoDTO> commMonitorInfoDTOList = commTerminalGeneralClient.tagOrIdGetMonitorList(monitorGetParam).getData();
                        Map<String, CommMonitorInfoDTO> monitorInfoDTOMap = commMonitorInfoDTOList.stream().collect(Collectors.toMap(CommMonitorInfoDTO::getId, Function.identity()));

                        List<String> temIds = commMonitorInfoDTOList.stream().map(CommMonitorInfoDTO::getId).distinct().collect(Collectors.toList());
                        List<RStatLimitRateDPO> rStatLimitRateDPOList = rStatLimitRateDClient.monitorIdsGetLimitInfo(RStatLimitQueryParam.builder().ids(temIds).date(yesterday).build()).getData();

                        //TODO 数据中心和pms这边稳态指标没用一个需要考虑兼容问题
                        //判断指标是否在策略中
                        if (CollectionUtil.isNotEmpty(rStatLimitRateDPOList)) {
                            for (RStatLimitRateDPO rStatLimitRateDPO : rStatLimitRateDPOList) {
                                List<String> descriptionList = new ArrayList<>();
                                Integer[] count = {0};

                                //先判断当前测点是否监测点策略
                                List<DictData> dictDataList;
                                if (monitorMap.containsKey(rStatLimitRateDPO.getLineId())) {
                                    List<String> lineTargetIds = monitorMap.get(rStatLimitRateDPO.getLineId()).getTargetIds();
                                    dictDataList = dictTargetList.stream().filter(item -> lineTargetIds.contains(item.getId())).collect(Collectors.toList());
                                } else {
                                    //不是监测点策略则去匹配对象标签策略
                                    String tagId = monitorInfoDTOMap.get(rStatLimitRateDPO.getLineId()).getObjTagId();
                                    List<String> tagTargetIds = tagMap.get(tagId).getTargetIds();
                                    dictDataList = dictTargetList.stream().filter(item -> tagTargetIds.contains(item.getId())).collect(Collectors.toList());
                                }

                                Map<String, Boolean> limitBoolMap = verifyLimit(rStatLimitRateDPO, dictDataList, descriptionList, count);
                                boolean shouldContinue;
                                if (oneStrategyVo.getOperation().equals(OperationEnum.AND.getCode())) {
                                    //与
                                    shouldContinue = limitBoolMap.containsValue(false);
                                } else {
                                    //或
                                    shouldContinue = !limitBoolMap.containsValue(true);
                                }
                                if (shouldContinue) {
                                    continue;
                                }

                                //到这一步说明符合策略保留该条数据，开始组装实体
                                if (Objects.isNull(thsSupervise)) {
                                    thsSupervise = new ThsSupervise();
                                    buildSuperviseData(yesterday, dept, superviseParam, oneStrategyVo, superviseParam.getInitType(), thsSupervise);

                                    thsSuperviseListPO.add(thsSupervise);
                                }
                                buildOverRunLog(thsSupervise, monitorInfoDTOMap.get(rStatLimitRateDPO.getLineId()), descriptionList, thsOverRunLogList, count);

                            }
                            allThsLogPO.addAll(thsOverRunLogList);
                        }
                    }

                    //返回体处理
                    if (CollectionUtil.isNotEmpty(thsSuperviseListPO)) {
                        if (superviseParam.getInitType().equals(InitTypeEnum.AUTO.getCode())) {
                            //处理flowable
                            for (ThsSupervise ths : thsSuperviseListPO) {
                               flowableRun(ths);
                            }
                            this.saveBatch(thsSuperviseListPO);
                            thsOverRunLogService.saveBatch(allThsLogPO);
                            return null;
                        } else {
                            superviceRunLogVo.setOverRunLog(allThsLogPO);
                            superviceRunLogVo.setThsSupervise(thsSuperviseListPO.get(0));
                            return superviceRunLogVo;
                        }
                    }

                }

            }
        }

        return superviceRunLogVo;
    }


    @Override
    public Page<ThsSupervise> queryPage(ThsSuperviseParam thsSuperviseParam) {
        return this.page(new Page<>(thsSuperviseParam.getPageNum(), thsSuperviseParam.getPageSize()), new LambdaQueryWrapper<ThsSupervise>()
                .between(ThsSupervise::getCreateTime, DateUtil.beginOfDay(DateUtil.parse(thsSuperviseParam.getStartTime())), DateUtil.endOfDay(DateUtil.parse(thsSuperviseParam.getEndTime())))
                .eq(ThsSupervise::getDeptId, thsSuperviseParam.getDeptId()));
    }

    public void buildSuperviseData(String yesterday, Dept dept, SuperviseParam superviseParam, ThsStrategyVo steady, Integer initType, ThsSupervise thsSupervise) {
        if (thsSupervise != null && StringUtils.isBlank(thsSupervise.getSupIndex())) {
            thsSupervise.setName(yesterday + dept.getName() + AlarmTypeEnum.getAlarmTypeEnumByCode(superviseParam.getType()).getMessage());
            thsSupervise.setSupIndex(IdUtil.simpleUUID());
            thsSupervise.setDeptId(steady.getDeptId());
            thsSupervise.setCreateTime(new Date());
            thsSupervise.setType(steady.getType());
            thsSupervise.setCreateUser(RequestUtil.getUsername());
            thsSupervise.setProgress(ProgressEnum.START.getCode());
            thsSupervise.setCreateType(initType);
        }
    }

    public void buildOverRunLog(ThsSupervise thsSupervise, CommMonitorInfoDTO monitor, List<String> descriptionList, List<ThsOverRunLog> thsOverRunLogs, Integer[] count) {
        ThsOverRunLog thsOverRunLog = new ThsOverRunLog();
        thsOverRunLog.setId(IdUtil.simpleUUID());
        thsOverRunLog.setSupIndex(thsSupervise.getSupIndex());
        thsOverRunLog.setLineIndex(monitor.getId());
        thsOverRunLog.setName(monitor.getPowerStationName() + "_" + monitor.getName() + "_" + DateUtil.today() + "_" + monitor.getId());
        thsOverRunLog.setUpdateTime(new Date());
        thsOverRunLog.setCreateTime(new Date());
        thsOverRunLog.setDescription(StringUtils.join(descriptionList, ","));
        thsOverRunLog.setCompanyName(monitor.getPowerStationName());
        thsOverRunLog.setLineIndexName(monitor.getName());
        thsOverRunLog.setOverTime(count[0]);
        thsOverRunLogs.add(thsOverRunLog);
    }


    private List<ThsWarnStrategyAss> queryWarnStrategyAss(String warnId, TypeEnum typeEnum) {
        return thsWarnStrategyAssMapper.selectList(new LambdaQueryWrapper<ThsWarnStrategyAss>()
                .eq(ThsWarnStrategyAss::getWarnId, warnId)
                .eq(ThsWarnStrategyAss::getType, typeEnum.getCode()));
    }


    /**
     * 根据策略组装对象
     *
     * @author cdf
     * @date 2024/3/19
     */
    private void assBindList(ThsStrategyVo thsStrategyVo, List<ThsStrategyBindDTO> thsStrategyBindDTOList) {

                List<ThsWarnStrategyAss> tagIdsAss = this.queryWarnStrategyAss(thsStrategyVo.getId(), TypeEnum.SOURCE_TYPE);//干扰源列表
                List<ThsWarnStrategyAss> targetIdsAss = this.queryWarnStrategyAss(thsStrategyVo.getId(), TypeEnum.INTERFERENCE_TYPE);//指标类型列表
                List<ThsWarnStrategyAss> monitorIdsAss = this.queryWarnStrategyAss(thsStrategyVo.getId(), TypeEnum.MONITOR_TYPE);//监测点列表

                List<String> tagIds = tagIdsAss.stream().map(ThsWarnStrategyAss::getAssId).distinct().collect(Collectors.toList());
                List<String> targetIds = targetIdsAss.stream().map(ThsWarnStrategyAss::getAssId).distinct().collect(Collectors.toList());
                List<String> monitorIds = monitorIdsAss.stream().map(ThsWarnStrategyAss::getAssId).collect(Collectors.toList());

                for (String tagId : tagIds) {
                    ThsStrategyBindDTO strategyBindDTO = ThsStrategyBindDTO.builder().keyId(tagId).targetIds(targetIds).operation(thsStrategyVo.getOperation()).build();
                    thsStrategyBindDTOList.add(strategyBindDTO);
                }
                for (String monitorId : monitorIds) {
                    ThsStrategyBindDTO strategyBindDTO = ThsStrategyBindDTO.builder().keyId(monitorId).targetIds(targetIds).operation(thsStrategyVo.getOperation()).build();
                    thsStrategyBindDTOList.add(strategyBindDTO);
                }

    }


    /**
     * 批量下载.zip文件
     *
     * @param fileParam
     * @param filePathMap
     * @param request
     * @param response
     * @return
     */
    private HttpServletResponse dowloadZipFile(FileParam fileParam, Map<String, String> filePathMap, HttpServletRequest request, HttpServletResponse response, TicketTypeEnum ticketTypeEnum) {
        try {
            if (CollectionUtil.isNotEmpty(filePathMap)) {
                ThsOverRunLog thsOverRunLog = thsOverRunLogService.getById(fileParam.getIds().get(0));
                ThsSupervise thsSupervise = thsSuperviseMapper.selectOne(new LambdaQueryWrapper<ThsSupervise>().eq(ThsSupervise::getSupIndex, thsOverRunLog.getSupIndex()).last("limit 1"));
                //改为自己的名称
                String fileName = thsSupervise.getName() + ".zip";
                // 创建临时文件
                File zipFile = File.createTempFile(thsSupervise.getName(), ".zip");
                FileOutputStream f = new FileOutputStream(zipFile);
                /**
                 * 作用是为任何OutputStream产生校验和
                 * 第一个参数是制定产生校验和的输出流，第二个参数是指定Checksum的类型 （Adler32（较快）和CRC32两种）
                 */
                CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());
                // 用于将数据压缩成Zip文件格式
                ZipOutputStream zos = new ZipOutputStream(csum);
                for (Map.Entry<String, String> entry : filePathMap.entrySet()) {
                    ThsOverRunLog runLog = thsOverRunLogService.getById(entry.getKey());
                    PmsMonitorParam pmsMonitorParam = new PmsMonitorParam();
                    pmsMonitorParam.setMonitorIds(Collections.singletonList(runLog.getLineIndex()));
                    HttpResult<List<PmsMonitorDTO>> monitorInfoListByCond = monitorClient.getMonitorInfoListByCond(pmsMonitorParam);
                    InputStream inputStream = fileStorageUtil.getFileStream(entry.getValue());
                    // 对于每一个要被存放到压缩包的文件，都必须调用ZipOutputStream对象的putNextEntry()方法，确保压缩包里面文件不同名
                    zos.putNextEntry(new ZipEntry(monitorInfoListByCond.getData().get(0).getName() + ticketTypeEnum.getMessage() + entry.getValue().substring(entry.getValue().lastIndexOf("."))));
                    int bytesRead = 0;
                    // 向压缩文件中输出数据
                    while ((bytesRead = inputStream.read()) != -1) {
                        zos.write(bytesRead);
                    }
                    inputStream.close();
                    zos.closeEntry(); // 当前文件写完，定位为写入下一条项目
                }
                zos.close();
                InputStream fis = new BufferedInputStream(new FileInputStream(zipFile));
                byte[] buffer = new byte[fis.available()];
                fis.read(buffer);
                fis.close();
                // 清空response
                response.reset();
                // 设置response的Header
                response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
                response.addHeader("Content-Length", "" + zipFile.length());
                OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
                response.setContentType("application/octet-stream");
                toClient.write(buffer);
                toClient.flush();
                toClient.close();
                zipFile.delete();
            }
        } catch (Exception e) {
            log.error("批量下载.zip文件异常：{}", e.toString());
        }
        return response;
    }


    /**
     * 判断监测数据是否超标
     *
     * @param rStatLimitRateDPO
     * @param dictTargetList
     */
    private Map<String, Boolean> verifyLimit(RStatLimitRateDPO rStatLimitRateDPO, List<DictData> dictTargetList, List<String> descriptionList, Integer[] count) {


        Map<String, Boolean> limitBoolMap = new HashMap<>();
        for (DictData dic : dictTargetList) {
            SteadyIndicatorEnum steadyIndicatorEnum = SteadyIndicatorEnum.getSteadyIndicatorEnumByCode(dic.getCode());
            switch (steadyIndicatorEnum) {
                case Negative_Voltage://负序电压不平衡度
                    if (rStatLimitRateDPO.getUbalanceOvertime() > 0) {
                        limitBoolMap.put(Negative_Voltage.getCode(), true);
                        descriptionList.add(Negative_Voltage.getMessage().concat(rStatLimitRateDPO.getUbalanceOvertime() + "次"));
                        count[0] = count[0] + rStatLimitRateDPO.getUbalanceOvertime();
                    } else {
                        limitBoolMap.put(Negative_Voltage.getCode(), false);
                    }
                    break;
                case Interhar_Voltage://间谐波电压
                    Integer interharVoltageOvertime = this.maxOverTime(rStatLimitRateDPO, InterharVoltage.class);
                    if (interharVoltageOvertime > 0) {
                        limitBoolMap.put(SteadyIndicatorEnum.Interhar_Voltage.getCode(), true);
                        descriptionList.add(SteadyIndicatorEnum.Interhar_Voltage.getMessage().concat(interharVoltageOvertime + "次"));
                        count[0] = count[0] + interharVoltageOvertime;
                    } else {
                        limitBoolMap.put(SteadyIndicatorEnum.Interhar_Voltage.getCode(), false);
                    }
                    break;
                case Neg_Current://负序电流
                    if (rStatLimitRateDPO.getINegOvertime() > 0) {
                        limitBoolMap.put(SteadyIndicatorEnum.Neg_Current.getCode(), true);
                        descriptionList.add(SteadyIndicatorEnum.Neg_Current.getMessage().concat(rStatLimitRateDPO.getINegOvertime() + "次"));
                        count[0] = count[0] + rStatLimitRateDPO.getINegOvertime();
                    } else {
                        limitBoolMap.put(SteadyIndicatorEnum.Neg_Current.getCode(), false);
                    }
                    break;
                case Fre_Deviation://频率偏差
                    if (rStatLimitRateDPO.getFreqDevOvertime() > 0) {
                        limitBoolMap.put(SteadyIndicatorEnum.Fre_Deviation.getCode(), true);
                        descriptionList.add(SteadyIndicatorEnum.Fre_Deviation.getMessage().concat(rStatLimitRateDPO.getFreqDevOvertime() + "次"));
                        count[0] = count[0] + rStatLimitRateDPO.getFreqDevOvertime();
                    } else {
                        limitBoolMap.put(SteadyIndicatorEnum.Fre_Deviation.getCode(), false);
                    }
                    break;
                case Voltage_Dev://电压偏差
                    if (rStatLimitRateDPO.getVoltageDevOvertime() > 0) {
                        limitBoolMap.put(SteadyIndicatorEnum.Voltage_Dev.getCode(), true);
                        descriptionList.add(SteadyIndicatorEnum.Voltage_Dev.getMessage().concat(rStatLimitRateDPO.getVoltageDevOvertime() + "次"));
                        count[0] = count[0] + rStatLimitRateDPO.getVoltageDevOvertime();
                    } else {
                        limitBoolMap.put(SteadyIndicatorEnum.Voltage_Dev.getCode(), false);
                    }
                    break;
                case Har_Current://谐波电流
                    Integer harCurrentOvertime = this.maxOverTime(rStatLimitRateDPO, HarCurrent.class);
                    if (harCurrentOvertime > 0) {
                        limitBoolMap.put(SteadyIndicatorEnum.Har_Current.getCode(), true);
                        descriptionList.add(SteadyIndicatorEnum.Har_Current.getMessage().concat(harCurrentOvertime + "次"));
                        count[0] = count[0] + harCurrentOvertime;


                    } else {
                        limitBoolMap.put(SteadyIndicatorEnum.Har_Current.getCode(), false);
                    }
                    break;
                case Voltage_Fluc://电压波动与闪变
                    if (rStatLimitRateDPO.getFlickerOvertime() > 0) {
                        limitBoolMap.put(SteadyIndicatorEnum.Voltage_Fluc.getCode(), true);
                        descriptionList.add(SteadyIndicatorEnum.Voltage_Fluc.getMessage().concat(rStatLimitRateDPO.getFlickerOvertime() + "次"));
                        count[0] = count[0] + rStatLimitRateDPO.getFlickerOvertime();
                    } else {
                        limitBoolMap.put(SteadyIndicatorEnum.Voltage_Fluc.getCode(), false);
                    }
                    break;
                case Har_Voltage://谐波电压
                    Integer harVoltageOvertime = this.maxOverTime(rStatLimitRateDPO, HarVoltage.class);
                    if (harVoltageOvertime > 0) {
                        limitBoolMap.put(SteadyIndicatorEnum.Har_Voltage.getCode(), true);
                        descriptionList.add(SteadyIndicatorEnum.Har_Voltage.getMessage().concat(harVoltageOvertime + "次"));
                        count[0] = count[0] + harVoltageOvertime;
                    } else {
                        limitBoolMap.put(SteadyIndicatorEnum.Har_Voltage.getCode(), false);
                    }
                    break;
                case Thd_V://畸变
                    if (rStatLimitRateDPO.getUaberranceOvertime() > 0) {
                        limitBoolMap.put(SteadyIndicatorEnum.Thd_V.getCode(), true);
                        descriptionList.add(SteadyIndicatorEnum.Thd_V.getMessage().concat(rStatLimitRateDPO.getUaberranceOvertime() + "次"));
                        count[0] = count[0] + rStatLimitRateDPO.getUaberranceOvertime();
                    } else {
                        limitBoolMap.put(SteadyIndicatorEnum.Thd_V.getCode(), false);
                    }
                    break;
            }
        }
        return limitBoolMap;
    }

    /***
     * 获取越限最大值
     * @param object
     * @param annotation
     * @return
     */
    private Integer maxOverTime(Object object, Class annotation) {
        Integer maxValue = 0;
        try {
            Class objClass = object.getClass();
            Field[] fields = objClass.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                boolean isAnon = field.isAnnotationPresent(annotation);
                if (isAnon) {
                    Object objValue = field.get(object);
                    if (objValue instanceof Integer) {
                        if ((Integer) objValue > maxValue) {
                            maxValue = (Integer) objValue;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取越限最大值异常：{}", e.toString());
        }
        return maxValue;
    }
}
