package com.njcn.prepare.harmonic.service.mysql.Impl.line;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.njcn.common.pojo.constant.BizParamConstant;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.FileUtil;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.biz.pojo.dto.DeptGetChildrenMoreDTO;
import com.njcn.device.biz.pojo.param.DeptGetLineParam;
import com.njcn.device.pq.api.DeptLineFeignClient;
import com.njcn.device.pq.api.DeviceUnitClient;
import com.njcn.device.biz.pojo.po.PqsDeviceUnit;
import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO;
import com.njcn.harmonic.enums.HarmonicResponseEnum;
import com.njcn.harmonic.pojo.dto.ReportTemplateDTO;
import com.njcn.harmonic.pojo.param.ReportSearchParam;
import com.njcn.harmonic.pojo.po.ExcelRpt;
import com.njcn.harmonic.pojo.po.ExcelRptTemp;
import com.njcn.harmonic.pojo.po.SysDeptTemp;
import com.njcn.harmonic.pojo.po.upload.RUploadEvaluationDataD;
import com.njcn.harmonic.pojo.vo.ReportTreeVO;
import com.njcn.influx.constant.InfluxDbSqlConstant;
import com.njcn.influx.deprecated.InfluxDBSqlConstant;
import com.njcn.influx.pojo.constant.InfluxDBTableConstant;
import com.njcn.influx.utils.InfluxDbUtils;
import com.njcn.oss.constant.OssPath;
import com.njcn.oss.enums.OssResponseEnum;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.prepare.harmonic.constant.AlgorithmParam;
import com.njcn.prepare.harmonic.mapper.mysql.line.DeptTempMapper;
import com.njcn.prepare.harmonic.mapper.mysql.line.ExcelRptMapper;
import com.njcn.prepare.harmonic.mapper.mysql.line.ExcelRptTempMapper;
import com.njcn.prepare.harmonic.pojo.param.LineParam;
import com.njcn.prepare.harmonic.service.mysql.line.ReportService;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.system.pojo.po.EleEpdPqd;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.po.Dept;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.influxdb.dto.QueryResult;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.DateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 自定义报表
 *
 * @author qijian
 * @date 2022/10/20
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ReportServiceImpl implements ReportService {

    private final ExcelRptTempMapper excelRptTempMapper;
    private final ExcelRptMapper excelRptMapper;
    private final DeptTempMapper deptTempMapper;
    private final FileStorageUtil fileStorageUtil;
    private final DeviceUnitClient deviceUnitClient;
    private final DicDataFeignClient dicDataFeignClient;

    private final CommTerminalGeneralClient commTerminalGeneralClient;
    private final DeptFeignClient deptFeignClient;


    @Override
    @Async("asyncExecutor")
    public void batchReport(LineParam reportParam) {
        System.out.println("开始执行自定义报表预处理》》》》》》》》》》》》》》");
        TimeInterval timeInterval = new TimeInterval();
        String end = reportParam.getDataDate();
        DateTime dealDate = DateUtil.parse(end, DatePattern.NORM_DATE_PATTERN);
        //查询所有已激活模板
        List<ExcelRptTemp> reportTemplateList = excelRptTempMapper.getActiveTempList();


        if (CollUtil.isEmpty(reportTemplateList)) {
            throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_ACTIVE);
        }

        //有监测点，匹配监测点的数据进行处理
        Dept dept = deptFeignClient.getRootDept().getData();
        DeptGetLineParam deptGetLineParam = new DeptGetLineParam();
        deptGetLineParam.setDeptId(dept.getId());
        List<String> monlitorList = commTerminalGeneralClient.getRunMonitorIds().getData();
        //根据content进行处理
        JSONArray jsonArray;
        for (ExcelRptTemp excelRptTemp : reportTemplateList) {
            //指标
            List<ReportTemplateDTO> reportTemplateDTOList = new ArrayList<>();
            //限值
            List<ReportTemplateDTO> reportLimitList = new ArrayList<>();
            //台账
            List<ReportTemplateDTO> terminalList = new ArrayList<>();
            //获取已绑定的部门信息
            try (InputStream fileStream = fileStorageUtil.getFileStream(excelRptTemp.getContent())) {
                //获取content解析数据
                jsonArray = new JSONArray(new JSONTokener(fileStream, new JSONConfig()));

                parseTemplate(jsonArray, reportTemplateDTOList, reportLimitList, terminalList);


            } catch (Exception e) {
                throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_JSON);
            }

            //开始组织sql
            reportTemplateDTOList = reportTemplateDTOList.stream()
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(
                            () -> new TreeSet<>(Comparator.comparing(ReportTemplateDTO::getItemName))), ArrayList::new));

            Map<String, List<ReportTemplateDTO>> classMap = reportTemplateDTOList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getResourceId));


            //处理指标是否合格
            reportLimitList = reportLimitList.stream()
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ReportTemplateDTO::getItemName))), ArrayList::new));
            Map<String, ReportTemplateDTO> limitTargetMapX = reportLimitList.stream().collect(Collectors.toMap(ReportTemplateDTO::getItemName, Function.identity()));


            //查询influxDB数据

         /*   ReportSearchParam reportSearchParamDay = new ReportSearchParam();
            reportSearchParamDay.setStartTime(end);
            reportSearchParamDay.setEndTime(end);

            ReportSearchParam reportSearchParamMonth = new ReportSearchParam();
            DateTime beginMonth = DateUtil.beginOfMonth(dealDate);
            reportSearchParamMonth.setStartTime(DateUtil.format(beginMonth, DatePattern.NORM_DATE_PATTERN));
            reportSearchParamMonth.setEndTime(end);

            ReportSearchParam reportSearchParamQuarter = new ReportSearchParam();
            DateTime beginQuarter = DateUtil.beginOfQuarter(dealDate);
            reportSearchParamQuarter.setStartTime(DateUtil.format(beginQuarter, DatePattern.NORM_DATE_PATTERN));
            reportSearchParamQuarter.setEndTime(end);

            ReportSearchParam reportSearchParamYear = new ReportSearchParam();
            DateTime beginYear = DateUtil.beginOfYear(dealDate);
            reportSearchParamYear.setStartTime(DateUtil.format(beginYear, DatePattern.NORM_DATE_PATTERN));
            reportSearchParamYear.setEndTime(end);*/


            List<List<String>> partition = ListUtils.partition(monlitorList, 1);


            for(int i=0;i<2;i++){
            //for (List<String> splitList : partition) {


                //处理台账信息
                duoxiancheng(partition.get(i), terminalList, reportLimitList, classMap, limitTargetMapX, jsonArray,end,dealDate);

                //存入报表库
                //年：例如2022年，传入2022-01-01进行匹配，有则更新无则插入
                //季：例如2022第二季度，传入2022-04-01进行匹配，有则更新无则插入
                //月：例如2022十月份，传入2022-10-01进行匹配，有则更新无则插入
                //周：例如2022年第五周，传入2022-01-23（周一）进行匹配，有则更新无则插入
                //日：直接插入，无需配对
                //文件上传到文件服务器，存入文件名
           /*     if (BizParamConstant.STAT_BIZ_DAY.equals(reportParam.getType().toString())) {
                    rptInsert(reportParam, lineId, excelRptTemp, contentToOss(jsonArray.toString()));
                } else {
                    rptBiz(reportParam, lineId, excelRptTemp, contentToOss(jsonArray.toString()));
                }*/


           }


        }


        System.out.println("该方法一共执行了 "+timeInterval.intervalSecond()+" S...................................");
    }

    @Async("asyncExecutor")
    public void duoxiancheng(List<String> splitList, List<ReportTemplateDTO> terminalList, List<ReportTemplateDTO> reportLimitList,
                             Map<String, List<ReportTemplateDTO>> classMap,
                             Map<String, ReportTemplateDTO> limitTargetMapX, JSONArray jsonArray,String end,DateTime dealDate) {

               ReportSearchParam reportSearchParamDay = new ReportSearchParam();
            reportSearchParamDay.setStartTime(end);
            reportSearchParamDay.setEndTime(end);

            ReportSearchParam reportSearchParamMonth = new ReportSearchParam();
            DateTime beginMonth = DateUtil.beginOfMonth(dealDate);
            reportSearchParamMonth.setStartTime(DateUtil.format(beginMonth, DatePattern.NORM_DATE_PATTERN));
            reportSearchParamMonth.setEndTime(end);

            ReportSearchParam reportSearchParamQuarter = new ReportSearchParam();
            DateTime beginQuarter = DateUtil.beginOfQuarter(dealDate);
            reportSearchParamQuarter.setStartTime(DateUtil.format(beginQuarter, DatePattern.NORM_DATE_PATTERN));
            reportSearchParamQuarter.setEndTime(end);

            ReportSearchParam reportSearchParamYear = new ReportSearchParam();
            DateTime beginYear = DateUtil.beginOfYear(dealDate);
            reportSearchParamYear.setStartTime(DateUtil.format(beginYear, DatePattern.NORM_DATE_PATTERN));
            reportSearchParamYear.setEndTime(end);
        for (String lineId : splitList) {

            List<ReportTemplateDTO> endList = new ArrayList<>();

            TimeInterval neibu = new TimeInterval();
            //处理台账信息
            Map<String, String> terminalMap = new HashMap<>();
            if (CollUtil.isNotEmpty(terminalList)) {
                terminalMap = commTerminalGeneralClient.getCustomDetailByLineId(lineId).getData();
            }

            //执行日数据
            reportSearchParamDay.setLineId(lineId);
            dealReportData(reportLimitList, reportSearchParamDay, classMap, endList, limitTargetMapX, jsonArray, terminalMap);

            //执行月数据
            reportSearchParamMonth.setLineId(lineId);
            dealReportData(reportLimitList, reportSearchParamMonth, classMap, endList, limitTargetMapX, jsonArray, terminalMap);

            //执行季度数据
            reportSearchParamQuarter.setLineId(lineId);
            dealReportData(reportLimitList, reportSearchParamQuarter, classMap, endList, limitTargetMapX, jsonArray, terminalMap);

            //执行年数据
            reportSearchParamYear.setLineId(lineId);
            dealReportData(reportLimitList, reportSearchParamYear, classMap, endList, limitTargetMapX, jsonArray, terminalMap);


            System.out.println(Thread.currentThread().getName()+"线程————" + lineId+"------" + neibu.intervalSecond() + " s");


        }
    }


    /**
     * 处理数据
     */

    public void dealReportData(List<ReportTemplateDTO> reportLimitList, ReportSearchParam reportSearchParam,
                               Map<String, List<ReportTemplateDTO>> classMap, List<ReportTemplateDTO> endList,
                               Map<String, ReportTemplateDTO> limitTargetMapX, JSONArray jsonArray, Map<String, String> terminalMap) {
        Map<String, ReportTemplateDTO> assNoPassMap = new HashMap<>();
        Map<String, Object> limitMap = overLimitDeal(reportLimitList, reportSearchParam.getLineId());
        //存放限值指标的map

        classMap.forEach((classKey, templateValue) -> {
            Map<String, List<ReportTemplateDTO>> valueTypeMap = templateValue.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getStatMethod));
            //avg.max,min,cp95
            valueTypeMap.forEach((valueTypeKey, valueTypeVal) -> {
                //相别分组
                Map<String, List<ReportTemplateDTO>> phaseMap = valueTypeVal.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getPhase));
                phaseMap.forEach((phaseKey, phaseVal) -> {
                    StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT);
                    if (InfluxDbSqlConstant.MAX.equalsIgnoreCase(valueTypeKey)) {
                        assSql(phaseVal, sql, endList, InfluxDbSqlConstant.MAX, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                    } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(valueTypeKey)) {
                        assSql(phaseVal, sql, endList, InfluxDbSqlConstant.MIN, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                    } else if (InfluxDbSqlConstant.AVG_WEB.equalsIgnoreCase(valueTypeKey)) {
                        assSql(phaseVal, sql, endList, InfluxDbSqlConstant.AVG_WEB, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                    } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(valueTypeKey)) {
                        assSql(phaseVal, sql, endList, InfluxDbSqlConstant.PERCENTILE, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                    }
                });
            });

        });


        //处理合格率
        assNoPassMap.forEach((key, val) -> {
            limitTargetMapX.remove(key);
            if ("Voltage_Dev".equals(val.getTemplateName()) || "Freq_Dev".equals(val.getTemplateName())) {
                val.setValue("±" + val.getValue());
            }
            if (val.getOverLimitFlag() == 1) {
                val.setValue("不合格 (" + val.getValue() + ")");
            } else {
                val.setValue("合格 (" + val.getValue() + ")");
            }
            endList.add(val);
        });

        limitTargetMapX.forEach((key, val) -> {
            if (Objects.isNull(val.getOverLimitFlag())) {
                val.setValue("/");
            } else {
                val.setValue("合格");
            }
            endList.add(val);
        });

        if (CollUtil.isNotEmpty(endList)) {
            //数据单位信息
            Map<String, String> unit = unitMap(reportSearchParam.getLineId());
            //进行反向赋值到模板
            //1、根据itemName分组
            Map<String, List<ReportTemplateDTO>> assMap = endList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getItemName));


            //2、把itemName的value赋给v和m

            jsonArray.forEach(item -> {
                JSONObject jsonObject = (JSONObject) item;
                JSONArray itemArr = (JSONArray) jsonObject.get("celldata");
                itemArr.forEach((it) -> {
                    if (Objects.nonNull(it) && !"null".equals(it.toString())) {
                        //获取到1列
                        JSONObject data = (JSONObject) it;
                        JSONObject son = (JSONObject) data.get("v");
                        if (son.containsKey("v")) {
                            String v = son.getStr("v");
                            //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                            if (v.charAt(0) == '$' && v.contains("#")) {
                                String str = "";
                                List<ReportTemplateDTO> rDto = assMap.get(v.replace("$", ""));
                                if (Objects.nonNull(rDto)) {
                                    str = rDto.get(0).getValue();
                                    //没有值，赋"/"
                                    if (StringUtils.isBlank(str)) {
                                        str = "/";
                                    }
                                    son.set("v", str);
                                    if (Objects.nonNull(rDto.get(0).getOverLimitFlag()) && rDto.get(0).getOverLimitFlag() == 1) {
                                        son.set("fc", "#990000");
                                    }
                                }
                            } else if (v.charAt(0) == '%' && v.contains("#")) {
                                //指标合格情况
                                String str = "";
                                List<ReportTemplateDTO> rDto = assMap.get(v.replace("%", ""));
                                if (Objects.nonNull(rDto)) {
                                    str = rDto.get(0).getValue();
                                    //没有值，赋"/"
                                    if (StringUtils.isBlank(str)) {
                                        str = "/";
                                    }
                                    son.set("v", str);
                                    if ("不合格".equals(str)) {
                                        son.set("fc", "#990000");
                                    }
                                }
                            } else if (v.charAt(0) == '&') {
                                //结论
                                String tem = v.replace("&", "");
                                if (Objects.nonNull(terminalMap)) {
                                    if ("statis_time".equals(tem)) {
                                        son.set("v", reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + reportSearchParam.getEndTime() + InfluxDbSqlConstant.END_TIME);
                                    } else {
                                        //台账信息
                                        son.set("v", terminalMap.getOrDefault(tem, "/"));
                                    }
                                }
                            }
                            //解决数据单位问题 @指标#类型@
                            if (v.charAt(0) == '@' && v.contains("#")) {
                                String replace = v.replace("@", "");
                                son.set("v", unit.getOrDefault(replace, "/"));

                            }
                        }
                    }
                });
            });
        }
    }


    /**
     * rpt业务方法
     *
     * @param reportParam,lineId,excelRptTemp,afterContent 参数
     * @return 结果
     */
    private void rptBiz(LineParam reportParam, String lineId, ExcelRptTemp excelRptTemp, String afterContent) {
        LambdaQueryWrapper<ExcelRpt> lambdaQuery = new LambdaQueryWrapper<>();
        lambdaQuery.eq(ExcelRpt::getLineId, lineId)
                .eq(ExcelRpt::getTempId, excelRptTemp.getId())
                .eq(ExcelRpt::getType, reportParam.getType())
                .eq(ExcelRpt::getDataDate, reportParam.getDataDate());
        ExcelRpt excelRpt = excelRptMapper.selectOne(lambdaQuery);
        if (excelRpt != null) {
            excelRpt.setContent(afterContent);
            excelRptMapper.updateById(excelRpt);
        } else {
            rptInsert(reportParam, lineId, excelRptTemp, afterContent);
        }
    }

    /**
     * 新增rpt方法
     *
     * @param reportParam,lineId,excelRptTemp,afterContent 参数
     * @return 结果
     */
    private void rptInsert(LineParam reportParam, String lineId, ExcelRptTemp excelRptTemp, String afterContent) {
        ExcelRpt excelRpt = new ExcelRpt();
        excelRpt.setName(excelRptTemp.getName());
        excelRpt.setLineId(lineId);
        excelRpt.setDataDate(DateUtil.parse(reportParam.getDataDate()));
        excelRpt.setTempId(excelRptTemp.getId());
        excelRpt.setContent(afterContent);
        excelRpt.setType(reportParam.getType());
        excelRpt.setState(DataStateEnum.ENABLE.getCode());
        excelRpt.setCreateBy("jobAdmin");
        excelRpt.setUpdateBy("jobAdmin");
        excelRptMapper.insert(excelRpt);
    }

    /**
     * 根据数据填充content
     *
     * @param jsonArray 参数
     * @return 结果
     */
    private void contentChange(JSONArray jsonArray, List<ReportTemplateDTO> endList, String lineID) {
        //数据单位信息
        Map<String, String> unit = unitMap(lineID);
        //进行反向赋值到模板
        //1、根据itemName分组
        Map<String, List<ReportTemplateDTO>> assMap = endList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getItemName));
        //2、把itemName的value赋给v和m
        jsonArray.forEach(item -> {
            JSONObject jsonObject = (JSONObject) item;
            JSONArray itemArr = (JSONArray) jsonObject.get("celldata");
            itemArr.forEach((it) -> {
                if (Objects.nonNull(it) && !"null".equals(it.toString())) {
                    //获取到1列
                    JSONObject data = (JSONObject) it;
                    JSONObject son = (JSONObject) data.get("v");
                    if (son.containsKey("v")) {
                        String v = son.getStr("v");
                        //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                        if (v.charAt(0) == '$' && v.contains("#")) {
                            String str = assMap.get(v.replace("$", "")).get(0).getValue();
                            //没有值，赋"/"
                            if (StrUtil.isBlank(str)) {
                                str = "/";
                            }
                            son.set("v", str);
                        }
                        //解决数据单位问题 @指标#类型@
                        if (v.charAt(0) == '@' && v.contains("#")) {
                            String replace = v.replace("@", "");
                            if (unit.containsKey(replace)) {
                                son.set("v", unit.get(replace));
                            } else {
                                son.set("v", "/");
                            }

                        }
                    }
                }
            });
        });
    }

    /*组装相别*/
    private void assPhase(List<EleEpdPqd> value, ReportTreeVO reportTreeItem, String key) {
        List<ReportTreeVO> phaseTree = new ArrayList<>();
        value.forEach(item -> {
            if (Objects.nonNull(item.getPhase()) && !"M".equals(item.getPhase())) {
                List<ReportTreeVO> statTree = new ArrayList<>();
                ReportTreeVO reportTreePhase = new ReportTreeVO();
                reportTreePhase.setName(item.getPhase());
                reportTreePhase.setShowName(item.getPhase());

                assStatMethod(item, statTree, key, item.getPhase());
                reportTreePhase.setChildren(statTree);
                phaseTree.add(reportTreePhase);
                reportTreeItem.setChildren(phaseTree);

            } else {
                List<ReportTreeVO> statTree = new ArrayList<>();
                assStatMethod(item, statTree, key, "");
                reportTreeItem.setChildren(statTree);
            }
        });

    }


    private void assStatMethod(EleEpdPqd item, List<ReportTreeVO> statTree, String oneKey, String twoKey) {
        //存在向别为M但是Stat_Method不为空
        if (StrUtil.isNotBlank(item.getStatMethod())) {
            String[] arr = item.getStatMethod().split(",");
            List<String> stat = Stream.of(arr).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(stat)) {
                stat.forEach(statItem -> {
                    ReportTreeVO reportTreeStat = new ReportTreeVO();
                    String tem = "";
                    if (Objects.nonNull(item.getLimitName())) {
                        tem = "#" + item.getLimitName();
                    } else {
                        tem = "#NO";
                    }
                    if (StrUtil.isNotBlank(twoKey)) {
                        reportTreeStat.setName("$" + oneKey + "#" + twoKey + "#" + statItem + "#" + item.getResourcesId().trim() + tem.trim() + "$");
                    } else {
                        reportTreeStat.setName("$" + oneKey + "#" + statItem + "#" + item.getResourcesId().trim() + tem.trim() + "$");
                    }

                    reportTreeStat.setShowName(statItem);
                    statTree.add(reportTreeStat);
                });
            }
        }
    }

    /**
     * 数据单位信息
     *
     * @param lineID
     * @return
     */
    private Map<String, String> unitMap(String lineID) {
        PqsDeviceUnit deviceUnit = commTerminalGeneralClient.lineUnitDetail(lineID).getData();
        List<DictData> dictData = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEVICE_UNIT.getCode()).getData();
        Map<String, String> unit = new HashMap<>();
        List<String> list = dictData.stream().map(DictData::getCode).collect(Collectors.toList());
        for (String s : list) {
            //有效值
            if (s.equals(DicDataEnum.EFFECTIVE.getCode())) {
                unit.put(s + "#i", deviceUnit.getIeffective());
                unit.put(s + "#v", deviceUnit.getLineVoltage());
            }
            //功率
            if (s.equals(DicDataEnum.POWER.getCode())) {
                unit.put(s + "#p", deviceUnit.getTotalActiveP());
                unit.put(s + "#q", deviceUnit.getTotalNoP());
                unit.put(s + "#s", deviceUnit.getTotalViewP());
            }
            //畸变率
            if (s.equals(DicDataEnum.DISTORTION.getCode())) {
                unit.put(s + "#v", deviceUnit.getVdistortion());
            }
            //电压偏差
            if (s.equals(DicDataEnum.VOLTAGE.getCode())) {
                unit.put(s + "#v", deviceUnit.getVoltageDev());
            }
            //频率
            if (s.equals(DicDataEnum.UNIT_FREQUENCY.getCode())) {
                unit.put(s + "#freq", deviceUnit.getUnitFrequency());
                unit.put(s + "#freqDev", deviceUnit.getUnitFrequencyDev());
            }
            //三项不平衡度
            if (s.equals(DicDataEnum.UNBALANCE.getCode())) {
                unit.put(s + "#v", "%");
                unit.put(s + "#vPos", deviceUnit.getPositiveV());
                unit.put(s + "#vNeg", deviceUnit.getNoPositiveV());
                unit.put(s + "#vZero", deviceUnit.getNoPositiveV());
                unit.put(s + "#i", "%");
                unit.put(s + "#iPos", "A");
                unit.put(s + "#iNeg", "A");
                unit.put(s + "#iZero", "A");
            }
            //基波
            if (s.equals(DicDataEnum.FUND.getCode())) {
                unit.put(s + "#i", deviceUnit.getIfund());
                unit.put(s + "#v", deviceUnit.getVfundEffective());

            }
        }
        return unit;
    }


    /**
     * @param data         同类型的cell模板
     * @param sql          单个cell模板
     * @param endList      用于返回最终组装好的数据，类似data
     * @param limitMap     指标是否合格模板
     * @param assNoPassMap 用于存储不合格的指标
     * @date 2023/10/20
     */
    private void assSql(List<ReportTemplateDTO> data, StringBuilder sql, List<ReportTemplateDTO> endList, String method, ReportSearchParam reportSearchParam, Map<String, ReportTemplateDTO> limitMap, Map<String, Object> overLimitMap, Map<String, ReportTemplateDTO> assNoPassMap) {
        //sql拼接示例：select MAX(IHA2) as IHA2 from power_quality_data where Phase = 'A' and LineId='1324564568' and Stat_Method='max' tz('Asia/Shanghai')


        //cp95函数特殊处理 PERCENTILE(field_key, N)
        if (InfluxDbSqlConstant.PERCENTILE.equals(method)) {

            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append("MAX")
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM);
                } else {
                    sql.append("MAX")
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA);
                }
            }

        } else {

            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM);
                } else {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA);
                }
            }

        }

        sql.append(StrPool.C_SPACE)
                .append(InfluxDbSqlConstant.FROM)
                .append(data.get(0).getResourceId());


        sql.append(InfluxDbSqlConstant.WHERE)
                .append(InfluxDBTableConstant.LINE_ID)
                .append(InfluxDbSqlConstant.EQ)
                .append(InfluxDbSqlConstant.QM)
                .append(reportSearchParam.getLineId())
                .append(InfluxDbSqlConstant.QM);
        //相别特殊处理
        if (!InfluxDBTableConstant.NO_PHASE.equals(data.get(0).getPhase())) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.PHASIC_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(data.get(0).getPhase())
                    .append(InfluxDbSqlConstant.QM);
        }


        //data_flicker、data_fluc、data_plt 无 value_type
        //if (!"r_stat_data_flicker_d".equals(data.get(0).getResourceId()) && !"r_stat_data_fluc_d".equals(data.get(0).getResourceId()) && !"r_stat_data_plt_d".equals(data.get(0).getResourceId())) {
        sql.append(InfluxDbSqlConstant.AND)
                .append(InfluxDBTableConstant.VALUE_TYPE)
                .append(InfluxDbSqlConstant.EQ)
                .append(InfluxDbSqlConstant.QM)
                .append(data.get(0).getStatMethod())
                .append(InfluxDbSqlConstant.QM);
        //}


        //频率和频率偏差仅统计T相
        if (data.get(0).getTemplateName().equals("freq_dev") || data.get(0).getTemplateName().equals("freq")) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.PHASIC_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(InfluxDBTableConstant.PHASE_TYPE_T)
                    .append(InfluxDbSqlConstant.QM);
        }
        //时间范围处理
        sql.append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.GE).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getStartTime()).append(InfluxDbSqlConstant.QM)
                .append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getEndTime()).append(InfluxDbSqlConstant.QM);

        System.out.println(sql);


        if (data.get(0).getTemplateName().equals("freq_dev") || data.get(0).getTemplateName().equals("freq")) {
            System.out.println(sql);
        }

        List<Map<String, Object>> mapList = SqlRunner.db().selectList(sql.toString());
        if (CollUtil.isEmpty(mapList)) {
            data = data.stream().peek(item -> item.setValue("/")).collect(Collectors.toList());
        } else {
            Map<String, Object> map = mapList.get(0);


            for (ReportTemplateDTO item : data) {
                if (Objects.nonNull(map) && map.containsKey(item.getItemName())) {
                    double v = Double.parseDouble(map.get(item.getItemName()).toString());
                    item.setValue(String.format("%.3f", v));

                    if (overLimitMap.containsKey(item.getLimitName())) {
                        Float tagVal = Float.parseFloat(overLimitMap.get(item.getLimitName()).toString());
                        if (v > tagVal) {
                            item.setOverLimitFlag(1);
                        } else {
                            item.setOverLimitFlag(0);
                        }
                    }

                    //判断是否越限
                    if (limitMap.size() != 0) {
                        String key = item.getLimitName() + "#" + item.getStatMethod().toLowerCase() + "#pq_overlimit";
                        if (limitMap.containsKey(key)) {
                            ReportTemplateDTO tem = limitMap.get(key);
                            double limitVal = Double.parseDouble(tem.getValue());
                            if (v > limitVal) {
                                tem.setOverLimitFlag(1);

                                assNoPassMap.put(key, tem);
                            } else if (!assNoPassMap.containsKey(key)) {
                                tem.setOverLimitFlag(0);
                                assNoPassMap.put(key, tem);
                            }
                        }
                    }
                } else {
                    item.setValue("/");
                }
            }
        }
        endList.addAll(data);
    }

    /**
     * 处理
     *
     * @author cdf
     * @date 2023/10/8
     */

   /* private void analyzeReport(ReportSearchParam reportSearchParam, ExcelRptTemp excelRptTemp) {

        long begin = System.currentTimeMillis();

        //根据content，获取v值并进行处理
        //指标
        List<ReportTemplateDTO> reportTemplateDTOList = new ArrayList<>();
        //限值
        List<ReportTemplateDTO> reportLimitList = new ArrayList<>();
        //台账
        List<ReportTemplateDTO> terminalList = new ArrayList<>();
        JSONArray jsonArray;
        try (InputStream fileStream = fileStorageUtil.getFileStream(excelRptTemp.getContent())) {
            jsonArray = new JSONArray(new JSONTokener(fileStream, new JSONConfig()));
            parseTemplate(jsonArray, reportTemplateDTOList, reportLimitList, terminalList);
        } catch (Exception e) {
            throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }
        long temEnd = System.currentTimeMillis();


        //处理指标是否合格
        reportLimitList = reportLimitList.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ReportTemplateDTO::getItemName))), ArrayList::new));

        Map<String, Object> limitMap = overLimitDeal(reportLimitList, reportSearchParam);
        //存放限值指标的map
        Map<String, ReportTemplateDTO> limitTargetMapX = reportLimitList.stream().collect(Collectors.toMap(ReportTemplateDTO::getItemName, Function.identity()));

        List<ReportTemplateDTO> endList = new ArrayList<>();
        if (CollUtil.isNotEmpty(reportTemplateDTOList)) {
            long deal = System.currentTimeMillis();

            //开始组织sql
            reportTemplateDTOList = reportTemplateDTOList.stream()
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(
                            () -> new TreeSet<>(Comparator.comparing(ReportTemplateDTO::getItemName))), ArrayList::new));

            Map<String, List<ReportTemplateDTO>> classMap = reportTemplateDTOList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getResourceId));
            Map<String, ReportTemplateDTO> assNoPassMap = new HashMap<>();
            classMap.forEach((classKey, templateValue) -> {
                Map<String, List<ReportTemplateDTO>> valueTypeMap = templateValue.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getStatMethod));

                //avg.max,min,cp95
                valueTypeMap.forEach((valueTypeKey, valueTypeVal) -> {

                    //相别分组
                    Map<String, List<ReportTemplateDTO>> phaseMap = valueTypeVal.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getPhase));
                    phaseMap.forEach((phaseKey, phaseVal) -> {
                        StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT);
                        if (InfluxDbSqlConstant.MAX.equalsIgnoreCase(valueTypeKey)) {
                            assSql(phaseVal, sql, endList, InfluxDbSqlConstant.MAX, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                        } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(valueTypeKey)) {
                            assSql(phaseVal, sql, endList, InfluxDbSqlConstant.MIN, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                        } else if (InfluxDbSqlConstant.AVG_WEB.equalsIgnoreCase(valueTypeKey)) {
                            assSql(phaseVal, sql, endList, InfluxDbSqlConstant.AVG_WEB, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                        } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(valueTypeKey)) {
                            assSql(phaseVal, sql, endList, InfluxDbSqlConstant.PERCENTILE, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                        }
                    });
                });

            });

            //处理合格率
            assNoPassMap.forEach((key, val) -> {
                limitTargetMapX.remove(key);
                if ("Voltage_Dev".equals(val.getTemplateName()) || "Freq_Dev".equals(val.getTemplateName())) {
                    val.setValue("±" + val.getValue());
                }
                if (val.getOverLimitFlag() == 1) {
                    val.setValue("不合格 (" + val.getValue() + ")");
                } else {
                    val.setValue("合格 (" + val.getValue() + ")");
                }
                endList.add(val);
            });

            limitTargetMapX.forEach((key, val) -> {
                if (Objects.isNull(val.getOverLimitFlag())) {
                    val.setValue("/");
                } else {
                    val.setValue("合格");
                }
                endList.add(val);
            });

            long dealEnd = System.currentTimeMillis();
            System.out.println("模板解析时间：" + (temEnd - begin) / 1000 + "S");
            System.out.println("查询数据库花费时间" + (dealEnd - deal) / 1000 + "S");
        }


        if (CollUtil.isNotEmpty(endList)) {
            long jie = System.currentTimeMillis();
            //数据单位信息
            Map<String, String> unit = unitMap(reportSearchParam.getLineId());
            //进行反向赋值到模板
            //1、根据itemName分组
            Map<String, List<ReportTemplateDTO>> assMap = endList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getItemName));
            //处理台账信息
            Map<String, String> terminalMap = null;
            if (CollUtil.isNotEmpty(terminalList)) {
                terminalMap = commTerminalGeneralClient.getCustomDetailByLineId(reportSearchParam.getLineId()).getData();
            }
            Map<String, String> finalTerminalMap = terminalMap;


            //2、把itemName的value赋给v和m

            jsonArray.forEach(item -> {
                JSONObject jsonObject = (JSONObject) item;
                JSONArray itemArr = (JSONArray) jsonObject.get("celldata");
                itemArr.forEach((it) -> {
                    if (Objects.nonNull(it) && !"null".equals(it.toString())) {
                        //获取到1列
                        JSONObject data = (JSONObject) it;
                        JSONObject son = (JSONObject) data.get("v");
                        if (son.containsKey("v")) {
                            String v = son.getStr("v");
                            //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                            if (v.charAt(0) == '$' && v.contains("#")) {
                                String str = "";
                                List<ReportTemplateDTO> rDto = assMap.get(v.replace("$", ""));
                                if (Objects.nonNull(rDto)) {
                                    str = rDto.get(0).getValue();
                                    //没有值，赋"/"
                                    if (StringUtils.isBlank(str)) {
                                        str = "/";
                                    }
                                    son.set("v", str);
                                    if (Objects.nonNull(rDto.get(0).getOverLimitFlag()) && rDto.get(0).getOverLimitFlag() == 1) {
                                        son.set("fc", "#990000");
                                    }
                                }
                            } else if (v.charAt(0) == '%' && v.contains("#")) {
                                //指标合格情况
                                String str = "";
                                List<ReportTemplateDTO> rDto = assMap.get(v.replace("%", ""));
                                if (Objects.nonNull(rDto)) {
                                    str = rDto.get(0).getValue();
                                    //没有值，赋"/"
                                    if (StringUtils.isBlank(str)) {
                                        str = "/";
                                    }
                                    son.set("v", str);
                                    if ("不合格".equals(str)) {
                                        son.set("fc", "#990000");
                                    }
                                }
                            } else if (v.charAt(0) == '&') {
                                //结论
                                String tem = v.replace("&", "");
                                if (Objects.nonNull(finalTerminalMap)) {
                                    if ("statis_time".equals(tem)) {
                                        son.set("v", reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + reportSearchParam.getEndTime() + InfluxDbSqlConstant.END_TIME);
                                    } else {
                                        //台账信息
                                        son.set("v", finalTerminalMap.getOrDefault(tem, "/"));
                                    }
                                }
                            }
                            //解决数据单位问题 @指标#类型@
                            if (v.charAt(0) == '@' && v.contains("#")) {
                                String replace = v.replace("@", "");
                                son.set("v", unit.getOrDefault(replace, "/"));

                            }
                        }
                    }
                });
            });
            long jieEnd = System.currentTimeMillis();

            System.out.println("组装信息耗时 " + (jieEnd - jie) / 1000 + "S");
        }


        long daochu = System.currentTimeMillis();

        InputStream reportStream = IoUtil.toStream(jsonArray.toString(), CharsetUtil.UTF_8);
        //String newContent = fileStorageUtil.uploadStream(reportStream, OssPath.HARMONIC_EXCEL_REPORT, FileUtil.generateFileName("json"));

        //response.setContentType("application/octet-stream;charset=UTF-8");
        //response.setHeader("Content-Disposition", "attachment;filename=" + "aa");
        //入库前判断是否有了，有了就更新
       *//* ExcelRpt excelRpt = new ExcelRpt();
        excelRpt.setName(excelRptTemp.getName());
        excelRpt.setLineId(reportSearchParam.getLineId());
        excelRpt.setDataDate(DateUtil.parse(reportSearchParam.getStartTime()));
        excelRpt.setTempId(excelRptTemp.getId());
        excelRpt.setContent(newContent);
        excelRpt.setType(reportSearchParam.getType());
        excelRpt.setState(DataStateEnum.ENABLE.getCode());

        excelRptMapper.insert(excelRpt);*//*
     *//*      OutputStream toClient = null;
        try {
            toClient = new BufferedOutputStream(response.getOutputStream());
            //通过IOUtils对接输入输出流，实现文件下载
            IOUtils.copy(reportStream, toClient);
            toClient.flush();
        } catch (Exception e) {
            throw new BusinessException(OssResponseEnum.DOWNLOAD_FILE_STREAM_ERROR);
        } finally {
            IOUtils.closeQuietly(reportStream);
            IOUtils.closeQuietly(toClient);
            long daochuEnd = System.currentTimeMillis();

            System.out.println("导出耗时 " + (daochuEnd - daochu) / 1000 + "S");
        }*//*

    }*/

    /**
     * 解析模板
     *
     * @author cdf
     * @date 2023/10/20
     */
    private void parseTemplate(JSONArray jsonArray, List<ReportTemplateDTO> reportTemplateDTOList, List<ReportTemplateDTO> reportLimitList, List<ReportTemplateDTO> terminalList) {
        try {
            //通过文件服务器获取

            jsonArray.forEach(item -> {
                JSONObject jsonObject = (JSONObject) item;
                JSONArray itemArr = (JSONArray) jsonObject.get("celldata");
                itemArr.forEach((it) -> {
                    if (Objects.nonNull(it) && !"null".equals(it.toString())) {
                        //获取到1列
                        JSONObject data = (JSONObject) it;
                        JSONObject son = (JSONObject) data.get("v");
                        if (son.containsKey("v")) {
                            String v = son.getStr("v");
                            //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                            if (v.charAt(0) == '$' && v.contains("#")) {
                                //剔除前后$
                                v = v.replace("$", "");
                                //封装ReportTemplateDTO
                                ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO();
                                reportTemplateDTO.setItemName(v);
                                //根据#分割数据
                                String[] vItem = v.split("#");
                                if (vItem.length == 5) {
                                    //$HA[_25]#B#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0]);
                                    reportTemplateDTO.setPhase(vItem[1].substring(0, 1));
                                    reportTemplateDTO.setStatMethod(vItem[2].toUpperCase());
                                    reportTemplateDTO.setResourceId(vItem[3]);
                                    reportTemplateDTO.setLimitName(vItem[4]);
                                } else if (vItem.length == 4) {
                                    //$HA[_25]#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0]);
                                    reportTemplateDTO.setPhase("M");
                                    reportTemplateDTO.setStatMethod(vItem[1].toUpperCase());
                                    reportTemplateDTO.setResourceId(vItem[2]);
                                    reportTemplateDTO.setLimitName(vItem[3]);
                                }

                                reportTemplateDTOList.add(reportTemplateDTO);
                            } else if (v.charAt(0) == '%' && v.contains("#")) {
                                //封装ReportTemplateDTO
                                ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO();

                                v = v.replace("%", "");
                                reportTemplateDTO.setItemName(v);
                                //根据#分割数据
                                String[] vItem = v.split("#");
                                if (vItem.length == 3) {
                                    //$HA[_25]#B#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0]);
                                    reportTemplateDTO.setStatMethod(vItem[1].toUpperCase());
                                    reportTemplateDTO.setResourceId(vItem[2]);
                                }
                                reportLimitList.add(reportTemplateDTO);
                            } else if (v.charAt(0) == '&') {
                                //封装ReportTemplateDTO
                                ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO();
                                v = v.replace("&", "");
                                reportTemplateDTO.setItemName(v);
                                reportTemplateDTO.setTemplateName(v);
                                terminalList.add(reportTemplateDTO);
                            }
                        }
                    }
                });
            });
        } catch (Exception e) {
            throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }
    }


    /**
     * @author cdf
     * @date 2023/10/23
     */
    private Map<String, Object> overLimitDeal(List<ReportTemplateDTO> reportLimitList, String monitorId) {
        Map<String, Object> limitMap = new HashMap<>();
        if (CollUtil.isNotEmpty(reportLimitList)) {
            StringBuilder sql = new StringBuilder("select ");
            for (int i = 0; i < reportLimitList.size(); i++) {
                if (i == reportLimitList.size() - 1) {
                    sql.append(reportLimitList.get(i).getTemplateName());
                } else {
                    sql.append(reportLimitList.get(i).getTemplateName()).append(",");
                }
            }

            sql.append(" from ").append(reportLimitList.get(0).getResourceId()).append(" where id ='").append(monitorId).append("'");
            limitMap = SqlRunner.db().selectOne(sql.toString());

            for (ReportTemplateDTO item : reportLimitList) {
                if (limitMap.containsKey(item.getTemplateName())) {
                    item.setValue(limitMap.get(item.getTemplateName()).toString());
                }
            }
        }
        return limitMap;
    }


    /**
     * 上传文件到Oss
     *
     * @param content 文件
     * @return 成功标记
     */
    private String contentToOss(String content) {
        InputStream reportStream = IoUtil.toStream(content, CharsetUtil.UTF_8);
        return fileStorageUtil.uploadStream(reportStream, OssPath.HARMONIC_EXCEL_REPORT, FileUtil.generateFileName("json"));
    }


}
