package com.njcn.harmonic.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
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.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.pq.api.DeptLineFeignClient;
import com.njcn.device.pq.api.DeviceUnitClient;
import com.njcn.device.pq.pojo.po.DeptLine;
import com.njcn.device.biz.pojo.po.PqsDeviceUnit;
import com.njcn.harmonic.enums.HarmonicResponseEnum;
import com.njcn.harmonic.mapper.DeptTempMapper;
import com.njcn.harmonic.mapper.EleEpdMapper;
import com.njcn.harmonic.mapper.ExcelRptMapper;
import com.njcn.harmonic.mapper.ExcelRptTempMapper;
import com.njcn.harmonic.pojo.dto.ReportTemplateDTO;
import com.njcn.harmonic.pojo.param.ReportSearchParam;
import com.njcn.harmonic.pojo.param.ReportTemplateParam;
import com.njcn.influx.constant.InfluxDbSqlConstant;
import com.njcn.influx.pojo.constant.InfluxDBTableConstant;
import com.njcn.influx.pojo.dto.StatisticalDataDTO;
import com.njcn.influx.service.CommonService;
import com.njcn.influx.utils.InfluxDbUtils;
import com.njcn.oss.enums.OssResponseEnum;
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.harmonic.pojo.po.ExcelRpt;
import com.njcn.harmonic.pojo.po.ExcelRptTemp;
import com.njcn.harmonic.pojo.po.SysDeptTemp;
import com.njcn.harmonic.pojo.vo.ReportTemplateVO;
import com.njcn.harmonic.pojo.vo.ReportTreeVO;
import com.njcn.harmonic.pojo.vo.SysDeptTempVO;
import com.njcn.harmonic.service.CustomReportService;
import com.njcn.oss.constant.OssPath;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.user.api.DeptFeignClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import sun.reflect.generics.tree.Tree;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
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/15
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CustomReportServiceImpl implements CustomReportService {

    private final ExcelRptTempMapper excelRptTempMapper;

    private final EleEpdMapper eleEpdMapper;

    private final DeptTempMapper deptTempMapper;

    private final FileStorageUtil fileStorageUtil;

    private final CommonService commonService;

    private final DeviceUnitClient deviceUnitClient;

    private final DicDataFeignClient dicDataFeignClient;
    private final DeptFeignClient deptFeignClient;

    private final InfluxDbUtils influxDbUtils;

    private final CommTerminalGeneralClient commTerminalGeneralClient;

    @Override
    public boolean addCustomReportTemplate(ReportTemplateParam reportTemplateParam) {
        checkName(reportTemplateParam, false);
        MultipartFile fileContent = reportTemplateParam.getFileContent();
        //检验模板json数据规范
        try {
            String content = FileUtil.multipartFileToString(fileContent);
            new JSONArray(content);
        } catch (Exception e) {
            throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }
        reportTemplateParam.setContent(fileStorageUtil.uploadMultipart(fileContent, OssPath.HARMONIC_EXCEL_TEMPLATE));
        //新增模板表
        ExcelRptTemp excelRptTemp = new ExcelRptTemp();
        BeanUtils.copyProperties(reportTemplateParam, excelRptTemp);
        excelRptTemp.setState(DataStateEnum.ENABLE.getCode());
        excelRptTemp.setActivation(DataStateEnum.ENABLE.getCode());
        excelRptTempMapper.insert(excelRptTemp);

        //获取主键，并存入部门表
        String tempId = excelRptTemp.getId();
        for (String deptId : reportTemplateParam.getDeptId()) {
            SysDeptTemp sysDeptTemp = new SysDeptTemp();
            sysDeptTemp.setTempId(tempId);
            sysDeptTemp.setDeptId(deptId);
            //未激活状态
            sysDeptTemp.setActivation(DataStateEnum.DELETED.getCode());
            deptTempMapper.insert(sysDeptTemp);
        }

        return true;
    }

    @Override
    public boolean updateCustomReportTemplate(ReportTemplateParam.UpdateReportTemplateParam reportTemplateParam) {
        checkName(reportTemplateParam, true);
        MultipartFile fileContent = reportTemplateParam.getFileContent();
        //检验模板json数据规范
        try {
            String content = FileUtil.multipartFileToString(fileContent);
            new JSONArray(content);
        } catch (Exception e) {
            throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }

        //删除之前的文件
        ExcelRptTemp excelRptTempOld = excelRptTempMapper.selectById(reportTemplateParam.getId());
        fileStorageUtil.deleteFile(excelRptTempOld.getContent());
        reportTemplateParam.setContent(fileStorageUtil.uploadMultipart(fileContent, OssPath.HARMONIC_EXCEL_TEMPLATE));
        //修改模板数据
        ExcelRptTemp excelRptTemp = new ExcelRptTemp();
        BeanUtils.copyProperties(reportTemplateParam, excelRptTemp);
        excelRptTemp.setUpdateTime(LocalDateTime.now());
        excelRptTempMapper.updateById(excelRptTemp);

        return true;
    }

    @Override
    public boolean updateBindTemplate(List<ReportSearchParam> reportSearchParams) {
        //1、根据模板主键删除绑定的部门数据
        LambdaQueryWrapper<SysDeptTemp> lambdaQuery = new LambdaQueryWrapper<>();
        lambdaQuery.eq(SysDeptTemp::getTempId, reportSearchParams.get(0).getTempId());
        deptTempMapper.delete(lambdaQuery);
        //2、新增部门
        for (ReportSearchParam reportSearchParam : reportSearchParams) {
            SysDeptTemp sysDeptTemp = new SysDeptTemp();
            sysDeptTemp.setTempId(reportSearchParam.getTempId());
            sysDeptTemp.setDeptId(reportSearchParam.getDeptId());
            sysDeptTemp.setActivation(reportSearchParam.getActivation());
            deptTempMapper.insert(sysDeptTemp);
        }
        return true;
    }

    @Override
    public List<SysDeptTempVO> getDataByTempId(String id) {
        return deptTempMapper.getDeptTempByTempId(id);
    }

    @Override
    public List<ReportTemplateVO> getTemplateByDept(String id) {
        List<String> deptIds = deptFeignClient.getDepSonIdtByDeptId(id).getData();
        return excelRptTempMapper.getReportTemplateByDept(deptIds);
    }

    @Override
    public ExcelRptTemp getCustomReportTemplateById(String id) {
        ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(id);
        return excelRptTemp;
    }

    @Override
    public void viewCustomReportTemplateById(String id, HttpServletResponse response) {
        ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(id);
        try {
            fileStorageUtil.downloadStream(response, excelRptTemp.getContent());
        } catch (Exception exception) {
            throw new BusinessException(HarmonicResponseEnum.REPORT_TEMPLATE_DOWNLOAD_ERROR);
        }

    }

    @Override
    public List<ReportTemplateVO> getTemplateList(ReportSearchParam reportSearchParam) {
        return excelRptTempMapper.getReportTemplateList(reportSearchParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delTemplate(ReportSearchParam reportSearchParam) {
        //根据模板ID和部门ID删除绑定的数据
        LambdaQueryWrapper<SysDeptTemp> lambdaQuery = new LambdaQueryWrapper<>();
        lambdaQuery.eq(SysDeptTemp::getTempId, reportSearchParam.getTempId());
        deptTempMapper.delete(lambdaQuery);
        excelRptTempMapper.deleteById(reportSearchParam.getTempId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(ReportSearchParam reportSearchParam) {
        //先全体把激活的改为未激活，再改单个的激活值
        deptTempMapper.updateAllActivation(reportSearchParam.getDeptId());

        SysDeptTemp sysDeptTemp = new SysDeptTemp();
        BeanUtils.copyProperties(reportSearchParam, sysDeptTemp);
        deptTempMapper.updateActivation(sysDeptTemp);
        return true;
    }


    @Override
    public void getCustomReport(ReportSearchParam reportSearchParam, HttpServletResponse response) {
        ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(reportSearchParam.getTempId());
        if (Objects.isNull(excelRptTemp)) {
            throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_ACTIVE);
        }
        //先查询库里是否存在已解析的报表数据，存在直接返回/不存在解析数据
     /*   LambdaQueryWrapper<ExcelRpt> lambdaQuery = new LambdaQueryWrapper<>();
        lambdaQuery
                .eq(ExcelRpt::getLineId, reportSearchParam.getLineId())
                .eq(ExcelRpt::getTempId, reportSearchParam.getTempId())
                //年季月周日
                .eq(ExcelRpt::getType, reportSearchParam.getType())
                //报表日期
                .eq(ExcelRpt::getDataDate, reportSearchParam.getStartTime());*/
        try {
           /* List<ExcelRpt> excelRpts = excelRptMapper.selectList(lambdaQuery);
            if (CollUtil.isNotEmpty(excelRpts)) {
                fileStorageUtil.downloadStream(response, excelRpts.get(0).getContent());
            } else {*/
            analyzeReport(reportSearchParam, excelRptTemp, response);
            /*}*/
        } catch (Exception exception) {
            log.error(exception.getMessage());
            exception.printStackTrace();
            throw new BusinessException(HarmonicResponseEnum.REPORT_DOWNLOAD_ERROR);
        }

    }


    @Override
    public List<ReportTreeVO> reportChooseTree() {
        DictData dic = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.CS_DATA_TYPE.getName(), DicDataEnum.EPD.getName()).getData();
        LambdaQueryWrapper<EleEpdPqd> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(EleEpdPqd::getDataType, dic.getId()).orderByAsc(EleEpdPqd::getSort);
        List<EleEpdPqd> list = eleEpdMapper.selectList(lambdaQueryWrapper);
        Map<String, List<EleEpdPqd>> map = list.stream().collect(Collectors.groupingBy(EleEpdPqd::getName, LinkedHashMap::new, Collectors.toList()));

        List<ReportTreeVO> tree = new ArrayList<>();
        map.forEach((key, value) -> {

            ReportTreeVO reportTreeVO = new ReportTreeVO();
            reportTreeVO.setName(value.get(0).getOtherName());
            reportTreeVO.setShowName(value.get(0).getShowName());

            //存在1-50次 2-50次情况
            if (Objects.nonNull(value.get(0).getHarmStart()) && Objects.nonNull(value.get(0).getHarmEnd())) {
                List<ReportTreeVO> reHarm = new ArrayList<>();
                for (int i = value.get(0).getHarmStart(); i <= value.get(0).getHarmEnd(); i++) {
                    ReportTreeVO reportTreeCount = new ReportTreeVO();
                    reportTreeCount.setName(value.get(0).getOtherName() + "_" + i);
                    reportTreeCount.setShowName(i + "次" + value.get(0).getShowName());
                    reportTreeVO.setFlag(1);
                    assPhase(value, reportTreeCount, reportTreeCount.getName());
                    reHarm.add(reportTreeCount);
                }
                reportTreeVO.setChildren(reHarm);
            } else {
                assPhase(value, reportTreeVO, value.get(0).getOtherName());
            }
            tree.add(reportTreeVO);
        });
        return tree;
    }

    @Override
    public List<ReportTreeVO> targetLimitChooseTree() {
        List<ReportTreeVO> result = new ArrayList<>();
        DictData dic = dicDataFeignClient.getDicDataByCode(DicDataEnum.EPD.getCode()).getData();
        LambdaQueryWrapper<EleEpdPqd> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(EleEpdPqd::getDataType, dic.getId()).eq(EleEpdPqd::getLimitTable, "pq_overlimit").orderByAsc(EleEpdPqd::getSort);
        List<EleEpdPqd> list = eleEpdMapper.selectList(lambdaQueryWrapper);
        Map<String, List<EleEpdPqd>> map = list.stream().collect(Collectors.groupingBy(EleEpdPqd::getLimitName));
        map.forEach((key, val) -> {
            ReportTreeVO reportTreeVO = new ReportTreeVO();
            reportTreeVO.setShowName(val.get(0).getShowName());

            if (Objects.nonNull(val.get(0).getHarmStart()) && Objects.nonNull(val.get(0).getHarmEnd())) {
                String one = val.get(0).getLimitName();
                List<ReportTreeVO> temList = new ArrayList<>();
                for (int i = val.get(0).getHarmStart(); i <= val.get(0).getHarmEnd(); i++) {
                    double count;
                    ReportTreeVO reportTreeItem = new ReportTreeVO();

                    if (val.get(0).getHarmStart() == 1) {
                        count = i + 0.5;
                        reportTreeItem.setShowName(count + "次" + val.get(0).getShowName());
                        reportTreeItem.setName("%"+one + count + "#" + val.get(0).getFormula() + "#" + val.get(0).getLimitTable()+"%");
                    } else {
                        reportTreeItem.setShowName(i + "次" + val.get(0).getShowName());
                        reportTreeItem.setName("%"+one + i + "#" + val.get(0).getFormula()+ "#" + val.get(0).getLimitTable()+"%");
                    }

                    reportTreeItem.setFlag(1);
                    temList.add(reportTreeItem);
                }
                reportTreeVO.setChildren(temList);
            } else {
                reportTreeVO.setName("%"+val.get(0).getLimitName() + "#" + val.get(0).getLimitTable()+"%"+ val.get(0).getFormula()+"%");
                reportTreeVO.setFlag(1);
            }

            result.add(reportTreeVO);
        });
        return result;
    }

    @Override
    public List<ReportTreeVO> terminalChooseTree() {
        List<ReportTreeVO> result = new ArrayList<>();
        DictData dic = dicDataFeignClient.getDicDataByCode(DicDataEnum.TERMINAL_SORT.getCode()).getData();
        LambdaQueryWrapper<EleEpdPqd> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(EleEpdPqd::getDataType, dic.getId()).orderByAsc(EleEpdPqd::getSort);
        List<EleEpdPqd> list = eleEpdMapper.selectList(lambdaQueryWrapper);
        list.forEach(item -> {
            ReportTreeVO reportTreeVO = new ReportTreeVO();
            reportTreeVO.setId(item.getId());
            reportTreeVO.setName("&" + item.getName() + "&");
            reportTreeVO.setFlag(1);
            reportTreeVO.setShowName(item.getShowName());
            result.add(reportTreeVO);
        });
        return result;
    }

    /*组装相别*/
    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.getClassId().trim() + tem.trim() + "$");
                    } else {
                        reportTreeStat.setName("$" + oneKey + "#" + statItem + "#" + item.getClassId().trim() + tem.trim() + "$");
                    }

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


    /**
     * 检查名称是否已存在
     *
     * @param reportTemplateParam,isUpdate 参数
     * @return 结果
     */
    private void checkName(ReportTemplateParam reportTemplateParam, boolean isUpdate) {
        LambdaQueryWrapper<ExcelRptTemp> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //条件组合：where state = 1 and name = ?
        lambdaQueryWrapper.eq(ExcelRptTemp::getState, DataStateEnum.ENABLE.getCode()).eq(ExcelRptTemp::getName, reportTemplateParam.getName());

        //and id <> ?
        if (isUpdate) {
            if (reportTemplateParam instanceof ReportTemplateParam.UpdateReportTemplateParam) {
                lambdaQueryWrapper.ne(ExcelRptTemp::getId, ((ReportTemplateParam.UpdateReportTemplateParam) reportTemplateParam).getId());
            }
        }

        //若存在条件数据抛出异常
        int count = excelRptTempMapper.selectCount(lambdaQueryWrapper);
        if (count > 0) {
            throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_REPEAT);
        }

    }


    /**
     * 解析报表模板赋值数据
     */
/*    private void analyzeReport(ReportSearchParam reportSearchParam, ExcelRptTemp excelRptTemp,HttpServletResponse response) {
        //根据content，获取v值并进行处理
        List<ReportTemplateDTO> reportTemplateDTOList = new ArrayList<>();
        JSONArray jsonArray;
        try (InputStream fileStream = fileStorageUtil.getFileStream(excelRptTemp.getContent())) {
            //通过文件服务器获取
            jsonArray = new JSONArray(new JSONTokener(fileStream, new JSONConfig()));
            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 == 4) {
                                    //$HA[_25]#B#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0]);
                                    reportTemplateDTO.setPhase(vItem[1].substring(0, 1));
                                    reportTemplateDTO.setStatMethod(vItem[2].toUpperCase());
                                    reportTemplateDTO.setClassId(vItem[3]);
                                } else if (vItem.length == 3) {
                                    //$HA[_25]#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0]);
                                    reportTemplateDTO.setPhase("M");
                                    reportTemplateDTO.setStatMethod(vItem[1].toUpperCase());
                                    reportTemplateDTO.setClassId(vItem[2]);
                                }
                                reportTemplateDTOList.add(reportTemplateDTO);
                            }
                        }
                    }
                });
            });
        } catch (Exception e) {
            throw new BusinessException(HarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }

        List<ReportTemplateDTO> endList = new ArrayList<>();
        if (CollUtil.isNotEmpty(reportTemplateDTOList)) {
            //开始组织sql
            reportTemplateDTOList.stream().forEach(data -> {
                StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT);
                if (InfluxDbSqlConstant.MAX.equalsIgnoreCase(data.getStatMethod())) {
                    assSql(data, sql, endList, InfluxDbSqlConstant.MAX, reportSearchParam);
                } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(data.getStatMethod())) {
                    assSql(data, sql, endList, InfluxDbSqlConstant.MIN, reportSearchParam);
                } else if (InfluxDbSqlConstant.AVG_WEB.equalsIgnoreCase(data.getStatMethod())) {
                    assSql(data, sql, endList, InfluxDbSqlConstant.AVG, reportSearchParam);
                } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(data.getStatMethod())) {
                    assSql(data, sql, endList, InfluxDbSqlConstant.PERCENTILE, reportSearchParam);
                }
            });
        }

        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 = "";
                                if(Objects.nonNull(assMap.get(v.replace("$", "")))){
                                    str = assMap.get(v.replace("$", "")).get(0).getValue();
                                    //没有值，赋"/"
                                    if (StringUtils.isBlank(str)) {
                                        str = "/";
                                    }
                                    son.set("v", str);
                                }
                            }
                            //解决数据单位问题 @指标#类型@
                            if (v.charAt(0) == '@' && v.contains("#")) {
                                String replace = v.replace("@", "");
                                son.set("v", unit.getOrDefault(replace, "/"));

                            }
                        }
                    }
                });
            });
        }

        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);
        }

    }*/


    /**
     * 数据单位信息
     *
     * @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;
    }

    /**
     * 组装influxDB查询sql，查询value并封装endlist
     *
     * @return 结果
     */
    private void assSql(ReportTemplateDTO data, StringBuilder sql, List<ReportTemplateDTO> endList, String method, ReportSearchParam reportSearchParam) {
        //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)) {
            sql.append(method)
                    .append(InfluxDbSqlConstant.LBK)
                    .append(data.getTemplateName())
                    .append(InfluxDbSqlConstant.NUM_95)
                    .append(InfluxDbSqlConstant.RBK)
                    .append(InfluxDbSqlConstant.AS_VALUE);
        } else {
            sql.append(method)
                    .append(InfluxDbSqlConstant.LBK)
                    .append(data.getTemplateName())
                    .append(InfluxDbSqlConstant.RBK)
                    .append(InfluxDbSqlConstant.AS_VALUE);
        }

        if (reportSearchParam.getResourceType() == 1) {
            sql.append(InfluxDbSqlConstant.FROM)
                    .append(data.getClassId().replace("data", "day"));
        } else {
            sql.append(InfluxDbSqlConstant.FROM)
                    .append(data.getClassId());
        }

        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.getPhase())) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.PHASIC_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(data.getPhase())
                    .append(InfluxDbSqlConstant.QM);
        }


        //data_flicker、data_fluc、data_plt 无 value_type
        if (!InfluxDBTableConstant.DATA_FLICKER.equals(data.getClassId()) && !InfluxDBTableConstant.DATA_FLUC.equals(data.getClassId()) && !InfluxDBTableConstant.DATA_PLT.equals(data.getClassId())) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.VALUE_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(data.getStatMethod())
                    .append(InfluxDbSqlConstant.QM);
        }

        //频率和频率偏差仅统计T相
        if (data.getTemplateName().equals("freq_dev") || data.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.START_TIME).append(InfluxDbSqlConstant.QM)
                .append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getEndTime()).append(InfluxDbSqlConstant.END_TIME).append(InfluxDbSqlConstant.QM);

        System.out.println(sql);

        sql.append(InfluxDbSqlConstant.TZ);

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


        StatisticalDataDTO statisticalDataDTO = commonService.selectBySql(sql);
        //根据不同的库表赋值
        if (Objects.isNull(statisticalDataDTO)) {
            data.setValue("/");
        } else {
            data.setValue(String.format("%.3f", statisticalDataDTO.getValue()));
        }
        endList.add(data);
    }


    /**
     * @param data         同类型的cell模板
     * @param sql          单个cell模板
     * @param endList      用于返回最终组装好的数据，类似data
     * @param limitMap     指标是否合格模板
     * @param assNoPassMap 用于存储不合格的指标
     * @date 2023/10/20
     */
    private void assSqlNew(List<ReportTemplateDTO> data, StringBuilder sql, List<ReportTemplateDTO> endList, String method, ReportSearchParam reportSearchParam, Map<String, ReportTemplateDTO> limitMap, Map<String, Float> 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(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.NUM_95)
                            .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.NUM_95)
                            .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);
        if (reportSearchParam.getResourceType() == 1) {
            sql.append(InfluxDbSqlConstant.FROM)
                    .append(data.get(0).getClassId().replace("data", "day"));
        } else {
            sql.append(InfluxDbSqlConstant.FROM)
                    .append(data.get(0).getClassId());
        }

        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 (!InfluxDBTableConstant.DATA_FLICKER.equals(data.get(0).getClassId()) && !InfluxDBTableConstant.DATA_FLUC.equals(data.get(0).getClassId()) && !InfluxDBTableConstant.DATA_PLT.equals(data.get(0).getClassId())) {
            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.START_TIME).append(InfluxDbSqlConstant.QM)
                .append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getEndTime()).append(InfluxDbSqlConstant.END_TIME).append(InfluxDbSqlConstant.QM);

        System.out.println(sql);

        sql.append(InfluxDbSqlConstant.TZ);

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

        List<Map<String, Object>> mapList = influxDbUtils.getMapResult(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 (map.containsKey(item.getItemName())) {
                    double v = (Double) map.get(item.getItemName());
                    item.setValue(String.format("%.3f", v));

                    if (overLimitMap.containsKey(item.getLimitName())) {
                        Float tagVal = overLimitMap.get(item.getLimitName());
                        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, HttpServletResponse response) {

        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);
        }
        //处理查日表还是分钟表
        rangeDate(reportSearchParam);

        long temEnd = System.currentTimeMillis();


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

        Map<String, Float> 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::getClassId));
            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)) {
                            assSqlNew(phaseVal, sql, endList, InfluxDbSqlConstant.MAX, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                        } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(valueTypeKey)) {
                            assSqlNew(phaseVal, sql, endList, InfluxDbSqlConstant.MIN, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                        } else if (InfluxDbSqlConstant.AVG_WEB.equalsIgnoreCase(valueTypeKey)) {
                            assSqlNew(phaseVal, sql, endList, InfluxDbSqlConstant.AVG, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap);
                        } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(valueTypeKey)) {
                            assSqlNew(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.setClassId(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.setClassId(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.setClassId(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/20
     */
    private void rangeDate(ReportSearchParam reportSearchParam) {
        long a;
        DateFormat dft = new SimpleDateFormat("yyyy-MM-dd");
        try {
            //开始时间
            Date star = dft.parse(reportSearchParam.getStartTime());
            //结束时间
            Date endDay = dft.parse(reportSearchParam.getEndTime());
            Long starTimes = star.getTime();
            Long endTimes = endDay.getTime();
            long num = endTimes - starTimes;//时间戳相差的毫秒数
            a = num / 24 / 60 / 60 / 1000;
            if (a > 5) {
                //返回天表
                reportSearchParam.setResourceType(1);
            } else {
                //返回分钟
                reportSearchParam.setResourceType(0);
            }
        } catch (ParseException e) {
            throw new BusinessException("时间解析出错！" + e.getMessage());
        }
    }

    /**
     * @author cdf
     * @date 2023/10/23
     */
    private Map<String,Float> overLimitDeal(List<ReportTemplateDTO> reportLimitList, ReportSearchParam reportSearchParam) {
        Map<String, Float> 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).getClassId()).append(" where id ='").append(reportSearchParam.getLineId()).append("'");
            limitMap = excelRptTempMapper.dynamicSqlMap(sql.toString());

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

}


