package com.njcn.product.event.report.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.product.event.devcie.mapper.PqLineMapper;
import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.event.devcie.pojo.dto.PqsDeptDTO;
import com.njcn.product.event.report.pojo.dto.BjCustomReportDTO;
import com.njcn.product.event.report.pojo.dto.EventTemplate;
import com.njcn.product.event.report.pojo.param.ReportExportParam;
import com.njcn.product.event.report.service.EasyPoiWordExportService;
import com.njcn.product.event.report.utils.WordTemplate;
import com.njcn.product.event.transientes.mapper.*;
import com.njcn.product.event.transientes.pojo.enums.DicTypeEnum;
import com.njcn.product.event.transientes.pojo.param.LargeScreenCountParam;
import com.njcn.product.event.transientes.pojo.po.*;
import com.njcn.product.event.transientes.service.CommGeneralService;
import com.njcn.product.event.transientes.service.MsgEventConfigService;
import com.njcn.product.event.config.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
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.DoubleStream;
import java.util.stream.Stream;

/**
 * @Author: cdf
 * @CreateTime: 2025-09-23
 * @Description:
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService {

    private final CommGeneralService commGeneralService;

    private final PqLineMapper pqLineMapper;

    private final PqsDicDataMapper pqsDicDataMapper;

    private final PqsDicTypeMapper pqsDicTypeMapper;

    private final PqsDeptsMapper pqsDeptsMapper;

    private final PqsEventdetailMapper pqsEventdetailMapper;

    private final MsgEventConfigService msgEventConfigService;
    private final PqUserLineAssMapper pqUserLineAssMapper;
    private final PqUserLedgerMapper pqUserLedgerMapper;
    private final PqsDicTreeMapper pqsDicTreeMapper;
    private final ObjectMapper mapper = new ObjectMapper();
//    @Value("${business.wordTemplatePath}")
//    private String wordTemplatePath;
    private final RedisUtil redisUtil;
    private final static String NAME_KEY = "LineCache:";

    @Override
    public void exportWordReport(HttpServletResponse response, ReportExportParam param) {
        log.info(LocalDateTime.now()+"开始导出word报告");
        try {
            List<Integer> deptIds = commGeneralService.getLineIdsByRedis(param.getDeptId());
            if (CollUtil.isEmpty(deptIds)) {
                throw new BusinessException(CommonResponseEnum.FAIL, "当前部门未绑定监测点");
            }

            //字典信息
            PqsDicType pqsDicType = pqsDicTypeMapper.selectOne(new LambdaQueryWrapper<PqsDicType>().eq(PqsDicType::getDicTypeName, DicTypeEnum.VOLTAGE.getDicName()));
            List<PqsDicData> pqsDicDataList = pqsDicDataMapper.selectList(new LambdaQueryWrapper<PqsDicData>().eq(PqsDicData::getDicType, pqsDicType.getDicTypeIndex()));
            Map<String, PqsDicData> pqsDicDataMap = pqsDicDataList.stream().collect(Collectors.toMap(PqsDicData::getDicIndex, dic -> dic));

            List<PqsDicTreePO> pqsDicTreePOList = pqsDicTreeMapper.selectList(null);
            Map<String,PqsDicTreePO> treePOMap = pqsDicTreePOList.stream().collect(Collectors.toMap(PqsDicTreePO::getId,tree->tree));

            BjCustomReportDTO bjReportDTO = new BjCustomReportDTO();
            ledgerAssemble(bjReportDTO,param,deptIds,pqsDicDataMap);


            LambdaQueryWrapper<PqsEventdetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(PqsEventdetail::getWavetype,msgEventConfigService.getEventType())
                    .gt(PqsEventdetail::getPersisttime,msgEventConfigService.getEventDuration())
                    .le(PqsEventdetail::getEventvalue,msgEventConfigService.getEventValue())
                    .between(PqsEventdetail::getTimeid,DateUtil.parse(param.getSearchBeginTime(),DatePattern.NORM_DATETIME_PATTERN),DateUtil.parse(param.getSearchEndTime(),DatePattern.NORM_DATETIME_PATTERN));
            if (deptIds.size() > 1000) {
                List<List<Integer>> listList = CollUtil.split(deptIds, 1000);
                lambdaQueryWrapper.and(w->{
                    w.or(i->{
                        for(List<Integer> ids : listList){
                            i.in(PqsEventdetail::getLineid,ids);
                        }
                    });
                });
            } else {
                lambdaQueryWrapper.in(PqsEventdetail::getLineid,deptIds);
            }

            List<PqsEventdetail> pqsEventdetailList = pqsEventdetailMapper.selectList(lambdaQueryWrapper);
            if(CollUtil.isNotEmpty(pqsEventdetailList)) {
                List<LedgerBaseInfoDTO> ledgerBaseInfoDTOS = (List<LedgerBaseInfoDTO>)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO");
                Map<Integer, LedgerBaseInfoDTO> LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity()));

                List<Map<String, Object>> eventTemplateList = new ArrayList<>();
                for (int i = 0; i < pqsEventdetailList.size(); i++) {
                    PqsEventdetail pqsEventdetail = pqsEventdetailList.get(i);
                    EventTemplate eventTemplate = new EventTemplate();
                    eventTemplate.setSno(i + 1);
                    eventTemplate.setTimeId(pqsEventdetail.getTimeid().format(DatePattern.NORM_DATETIME_FORMATTER) + "." + pqsEventdetail.getMs());
                    LedgerBaseInfoDTO baseLineInfo =  LedgerBaseInfoDTOMap.get(pqsEventdetail.getLineid());
                    eventTemplate.setOrgName(baseLineInfo.getGdName());
                    eventTemplate.setSubName(baseLineInfo.getStationName());
                    eventTemplate.setBusName(baseLineInfo.getBusBarName());
                    eventTemplate.setScale(pqsDicDataMap.get(baseLineInfo.getScale()).getDicName());
                    eventTemplate.setDuration(String.format("%.3f", pqsEventdetail.getPersisttime() / 1000));
                    eventTemplate.setResidualVoltage(String.format("%.2f", pqsEventdetail.getEventvalue() * 100));
                    eventTemplate.setUserName(baseLineInfo.getObjName());
                    Map<String, Object> eventMap = mapper.convertValue(eventTemplate, Map.class);

                    eventTemplateList.add(eventMap);
                }
                bjReportDTO.setEvent(eventTemplateList);

                bjReportDTO.setBjTotalEvent(pqsEventdetailList.size());
                List<Integer> lineIds = pqsEventdetailList.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList());
                if (CollectionUtils.isEmpty(lineIds)) {
                    //如果lineIds为空添加一个不是监测点的监测点id避免后边查询错误
                    lineIds.add(99999999);
                }
                List<LedgerBaseInfoDTO> ledgerBaseInfoDTOList = pqLineMapper.getBaseLedger(lineIds, null);
                long stationCount = ledgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count();
                bjReportDTO.setTotalEventSubstation((int) stationCount);
                long busCount = ledgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count();
                bjReportDTO.setBjTotalBus((int) busCount);
                String busVoltageStr = busVoltageDeal(ledgerBaseInfoDTOList, pqsDicDataMap);
                bjReportDTO.setStationVoltage(busVoltageStr);
                //double容易精度缺失
                String min =String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()*100*100)*0.01) ;
                String max = String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()*100*100)*0.01) ;
                bjReportDTO.setResidualVoltageRange(min + "%-" + max + "%");

                double minPersisTime = pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble() / 1000;
                double maxPersisTime = pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getPersisttime).max().getAsDouble() / 1000;
                bjReportDTO.setDurationRange(minPersisTime + "s-" + maxPersisTime + "s");

                List<PqUserLineAssPO> pqUserLineAssPOS = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().in(PqUserLineAssPO::getLineIndex, lineIds));
                List<String> userIds = pqUserLineAssPOS.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());
                LambdaQueryWrapper<PqUserLedgerPO> queryWrapper = new LambdaQueryWrapper<>();
                if (userIds.size() > 1000) {
                    List<List<String>> listUserIds = CollUtil.split(userIds, 1000);
                    queryWrapper.and(w -> {
                        for (List<String> ids : listUserIds) {
                            w.or(wIn -> wIn.in(PqUserLedgerPO::getId, ids));
                        }
                    });
                } else {
                    queryWrapper.in(PqUserLedgerPO::getId, userIds);
                }
                List<PqUserLedgerPO> pqUserLedgerPOList = pqUserLedgerMapper.selectList(queryWrapper);
                Map<String, List<PqUserLedgerPO>> stringListMap = pqUserLedgerPOList.stream().collect(Collectors.groupingBy(PqUserLedgerPO::getSmallObjType));

                String treeStr = userToStr(stringListMap, treePOMap);

                bjReportDTO.setObjTypeList(treeStr);
                bjReportDTO.setAffectedUserCount(pqUserLedgerPOList.size());
                log.info(LocalDateTime.now()+"组装公共参数结束");

                areaAssemble(bjReportDTO, param, pqsDicDataMap);
                log.info(LocalDateTime.now()+"组装特别参数结束");

            }

            Map<String,Object> map = mapper.convertValue(bjReportDTO,Map.class);
            log.info(LocalDateTime.now()+"开始组装word模版");

            WordTemplate.generateWordDownload("template/bj_report.docx", response, bjReportDTO.getDateFormat()+"重要敏感用户电压暂降事件监测情况.docx", map);
            log.info(LocalDateTime.now()+"结束导出word报告");

        } catch (Exception e) {
            log.info(LocalDateTime.now()+"导出word报告出现异常:"+e.getMessage());

            e.printStackTrace();
        }
    }

    private void areaAssemble(BjCustomReportDTO bjReportDTO, ReportExportParam param, Map<String, PqsDicData> pqsDicDataMap) {
        log.info(LocalDateTime.now()+"组装word报告");

        List<PqsDeptDTO> pqsDeptsList = pqsDeptsMapper.getDeptList(param.getDeptList());
        Map<String,String> deptMap = pqsDeptsList.stream().collect(Collectors.toMap(PqsDeptDTO::getDeptsIndex,PqsDeptDTO::getDeptsname));
        List<String> areaContentList = new ArrayList<>();
        List<Map<String,Object>> eventTemplateList = new ArrayList<>();

        List<LedgerBaseInfoDTO> ledgerBaseInfoDTOS = (List<LedgerBaseInfoDTO>)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO");
        Map<Integer, LedgerBaseInfoDTO> LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity()));


        List<Map<String, Object>> finalEventTemplateList = eventTemplateList;
        param.getDeptList().forEach(deptId->{
            String deptName = deptMap.get(deptId);

            String areaContent ="";
            String userContext ="";
            List<Integer> deptLineIds = commGeneralService.getLineIdsByRedis(deptId);
            if(CollectionUtils.isEmpty(deptLineIds)){
                areaContent = deptName+"共监测到电压暂降事件0条";
            }else {
                LambdaQueryWrapper<PqsEventdetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.in(PqsEventdetail::getWavetype,msgEventConfigService.getEventType())
                        .gt(PqsEventdetail::getPersisttime,msgEventConfigService.getEventDuration())
                        .le(PqsEventdetail::getEventvalue,msgEventConfigService.getEventValue())
                        .between(PqsEventdetail::getTimeid,DateUtil.parse(param.getSearchBeginTime(),DatePattern.NORM_DATETIME_PATTERN),DateUtil.parse(param.getSearchEndTime(),DatePattern.NORM_DATETIME_PATTERN));
                if (deptLineIds.size() > 1000) {
                    List<List<Integer>> listList = CollUtil.split(deptLineIds, 1000);
                    lambdaQueryWrapper.and(w->{
                        w.or(i->{
                            for(List<Integer> ids : listList){
                                i.in(PqsEventdetail::getLineid,ids);
                            }
                        });
                    });
                } else {
                    lambdaQueryWrapper.in(PqsEventdetail::getLineid,deptLineIds);
                }
                List<PqsEventdetail> pqsEventdetailList = pqsEventdetailMapper.selectList(lambdaQueryWrapper);
                if(CollectionUtils.isEmpty(pqsEventdetailList)){
                    areaContent = deptName+"共监测到电压暂降事件0条。";
                }else {
                    Integer eveCount = pqsEventdetailList.size();

                    List<Integer> lineIds = pqsEventdetailList.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList());
                    List<LedgerBaseInfoDTO> ledgerBaseInfoDTOList = pqLineMapper.getBaseLedger(lineIds,null);
                    long stationCount = ledgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count();
                    long busCount = ledgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count();

                    String stationStr = stationVoltageDeal(ledgerBaseInfoDTOList,pqsDicDataMap);
                    String areabusVoltageDeal = areabusVoltageDeal(ledgerBaseInfoDTOList,pqsDicDataMap);

                    String min =String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()*100*100)*0.01) ;
                    String max = String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()*100*100)*0.01) ;
                    String residualVoltage = min+"%-"+max+"%";

                    double minPersisTime = pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble()/1000;
                    double maxPersisTime = pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getPersisttime).max().getAsDouble()/1000;
                    String duration = minPersisTime+"s-"+maxPersisTime+"s";
                    String temp ="%s共监测到电压暂降事件%s条，涉及%s座变电站，%s条母线，其中：%s，造成%s发生电压暂降，残余电压范围为%s，持续时间范围为%s。";
                    areaContent =String.format(temp,deptName,eveCount,stationCount,busCount,stationStr,areabusVoltageDeal,residualVoltage,duration);

                    if(!CollectionUtils.isEmpty(lineIds)){
                        List<PqUserLineAssPO> pqUserLineAssPOS = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().in(PqUserLineAssPO::getLineIndex,lineIds));
                        if(CollectionUtils.isEmpty(pqUserLineAssPOS)){
                            userContext ="不涉及半导体及重点关注用户。";
                        }else {
                            List<String> userIds = pqUserLineAssPOS.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());

                            LambdaQueryWrapper<PqUserLedgerPO> queryWrapper = new LambdaQueryWrapper<>();
                            if (userIds.size() > 1000) {
                                List<List<String>> listUserIds = CollUtil.split(userIds, 1000);
                                queryWrapper.eq(PqUserLedgerPO::getIsShow,1).and(w -> {
                                    for (List<String> ids : listUserIds) {
                                        w.or(wIn -> wIn.in(PqUserLedgerPO::getId, ids));
                                    }
                                });
                            } else {
                                queryWrapper.eq(PqUserLedgerPO::getIsShow,1).in(PqUserLedgerPO::getId, userIds);
                            }
                            List<PqUserLedgerPO> pqUserLedgerPOList = pqUserLedgerMapper.selectList(queryWrapper);
                            if(CollectionUtils.isEmpty(pqUserLedgerPOList)){
                                userContext ="不涉及半导体及重点关注用户。";
                            }else {
                                String companyName = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining("、", "（", "）"));
                                userContext="涉及"+pqUserLedgerPOList.size()+"家半导体及重点关注用户"+companyName+"，";
                                //逆推监测点，过滤发生暂降事件
                                List<String> companyId = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getId).collect(Collectors.toList());
                                List<PqUserLineAssPO> pqUserLineAssPOS1 = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().in(PqUserLineAssPO::getUserIndex, companyId));
                                List<String> companyNameList = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.toList());
                                List<Integer> companyLineId= pqUserLineAssPOS1.stream().map(PqUserLineAssPO::getLineIndex).collect(Collectors.toList());
                                List<PqsEventdetail> companyevent = pqsEventdetailList.stream().filter(pqsEventdetail -> companyLineId.contains(pqsEventdetail.getLineid())).collect(Collectors.toList());
                                if(CollectionUtils.isEmpty(companyevent)){
                                    userContext =userContext+"暂未发生暂态事件。";
                                }else {

                                    for (int i = 0; i < pqsEventdetailList.size(); i++) {
                                        PqsEventdetail pqsEventdetail = pqsEventdetailList.get(i);

                                        LedgerBaseInfoDTO baseLineInfo = LedgerBaseInfoDTOMap.get(pqsEventdetail.getLineid());
                                        if(Objects.isNull(baseLineInfo.getObjName())){
                                            continue;
                                        }
                                        String[] split = baseLineInfo.getObjName().split(";");
                                        for (int i1 = 0; i1 < split.length; i1++) {
                                            if(companyNameList.contains(split[i1])){
                                                EventTemplate eventTemplate = new EventTemplate();
                                                eventTemplate.setTimeId(pqsEventdetail.getTimeid().format(DatePattern.NORM_DATETIME_FORMATTER)+"."+pqsEventdetail.getMs());
                                                eventTemplate.setOrgName(baseLineInfo.getGdName());
                                                eventTemplate.setSubName(baseLineInfo.getStationName());
                                                eventTemplate.setBusName(baseLineInfo.getBusBarName());
                                                eventTemplate.setScale(pqsDicDataMap.get(baseLineInfo.getScale()).getDicName());
                                                eventTemplate.setDuration(String.format("%.3f",pqsEventdetail.getPersisttime()/1000));
                                                eventTemplate.setResidualVoltage(String.format("%.2f",pqsEventdetail.getEventvalue()*100));
                                                eventTemplate.setUserName(split[i1]);
                                                Map<String,Object> eventMap = mapper.convertValue(eventTemplate,Map.class);
                                                finalEventTemplateList.add(eventMap);
                                            }

                                        }



                                    }
                                    Integer companyEveCount = companyevent.size();

                                    List<Integer> companyLineIds = companyevent.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList());
                                    List<LedgerBaseInfoDTO> companyLedgerBaseInfoDTOList = pqLineMapper.getBaseLedger(companyLineIds,null);
                                    long companyStationCount = companyLedgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count();
                                    long companyBusCount = companyLedgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count();

                                    String companyStationStr = stationVoltageDeal(companyLedgerBaseInfoDTOList,pqsDicDataMap);
                                    String companyAreabusVoltageDeal = areabusVoltageDeal(companyLedgerBaseInfoDTOList,pqsDicDataMap);
                                    String companyMin =String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()*100*100)*0.01) ;
                                    String companyMax = String.format("%.2f",Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()*100*100)*0.01) ;

                                    String companyResidualVoltage = companyMin+"%-"+companyMax+"%";

                                    double companyMinPersisTime = companyevent.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble()/1000;
                                    double companyMaxPersisTime = companyevent.stream().mapToDouble(PqsEventdetail::getPersisttime).max().getAsDouble()/1000;
                                    String companyDuration = companyMinPersisTime+"s-"+companyMaxPersisTime+"s";
                                    String companyTemp ="电压暂降事件%s条，变电站%s座，母线%s条，其中：%s，造成%s发生电压暂降，残余电压范围为%s，持续时间范围为%s。";
                                    userContext = userContext+String.format(companyTemp,companyEveCount,companyStationCount,companyBusCount,companyStationStr,companyAreabusVoltageDeal,companyResidualVoltage,companyDuration);
                                }

                            }
                        }

                    }else {
                        userContext ="不涉及半导体及重点关注用户。";
                    }


                }

            }

            areaContent =areaContent+userContext;

            areaContentList.add(areaContent);
        });
        // 或者直接使用 \n
        String result2 = String.join("\r\n    ", areaContentList);
        bjReportDTO.setAreaContent(result2);
        eventTemplateList = eventTemplateList.stream().distinct().collect(Collectors.toList());
        eventTemplateList.sort(Comparator.comparing(map -> (String) map.get("userName")));

        bjReportDTO.setCompanyEvent(eventTemplateList);

    }

    private void addUserDataToTable(XWPFDocument document) {
        // 创建表格
        // 填充数据到表格（此处为示例代码框架，实际需完善表格创建和数据填充逻辑）
        // 例如：创建表头、添加数据行等
    }

    /**
     * 组装台账
     * @param bjReportDTO
     * @param param
     * @param deptIds
     */
    private void ledgerAssemble(BjCustomReportDTO bjReportDTO,ReportExportParam param,List<Integer> deptIds,Map<String, PqsDicData> pqsDicDataMap){
        bjReportDTO.setDateRange(param.getSearchBeginTime()+"至"+param.getSearchEndTime());

        //台账信息
        List<LedgerBaseInfoDTO> ledgerList = new ArrayList<>();
        if (deptIds.size() > 1000) {
            List<List<Integer>> listList = CollUtil.split(deptIds, 1000);
            for (List<Integer> ids : listList) {
                List<LedgerBaseInfoDTO> temList = pqLineMapper.getBaseLedger(ids, null);
                ledgerList.addAll(temList);
            }
        } else {
            ledgerList = pqLineMapper.getBaseLedger(deptIds, null);
        }


        long devCount = ledgerList.stream().map(LedgerBaseInfoDTO::getDevId).distinct().count();
        long stationCount = ledgerList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count();
        long busCount = ledgerList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count();

        Map<String, List<LedgerBaseInfoDTO>> scaleMap = ledgerList.stream().collect(Collectors.groupingBy(LedgerBaseInfoDTO::getScale));
        String result = scaleMap.entrySet().stream()
                .map(entry -> {
                    String scale = entry.getKey();
                    long busNum = entry.getValue().stream()
                            .map(LedgerBaseInfoDTO::getBusBarId)
                            .distinct()
                            .count();
                    return pqsDicDataMap.get(scale).getDicName() + "母线" + busNum + "条";
                }).sorted(Comparator
                        .comparing(EasyPoiWordExportServiceImpl::extractVoltageNumber).reversed())
                // 用分号连接
                .collect(Collectors.joining(StrUtil.COMMA));
        bjReportDTO.setBusVoltageList(result);

        StringBuilder temStr = new StringBuilder();
        List<PqsDeptDTO> pqsDeptsList = pqsDeptsMapper.getDeptList(param.getDeptList());
        Map<String,String> deptMap = pqsDeptsList.stream().collect(Collectors.toMap(PqsDeptDTO::getDeptsIndex,PqsDeptDTO::getDeptsname));
        for (String deptId : param.getDeptList()) {
            String deptName = deptMap.get(deptId);
            StrBuilder strBuilderInner = new StrBuilder(deptName+"涉及变电站");
            List<Integer> temIds = commGeneralService.getLineIdsByRedis(deptId);
            List<LedgerBaseInfoDTO> dtoList = pqLineMapper.getBaseLedger(temIds, null);

            long innerStation = dtoList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count();
            long innerBus = dtoList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count();

            strBuilderInner.append(String.valueOf(innerStation)).append("座，母线").append(String.valueOf(innerBus)).append("条,其中:");
            Map<String, List<LedgerBaseInfoDTO>> scaleInnerMap = dtoList.stream().collect(Collectors.groupingBy(LedgerBaseInfoDTO::getScale));
            String resultContent = scaleInnerMap.entrySet().stream()
                    .map(entry -> {
                        String scale = entry.getKey();
                        long busNum = entry.getValue().stream()
                                .map(LedgerBaseInfoDTO::getBusBarId)
                                .distinct()
                                .count();
                        return pqsDicDataMap.get(scale).getDicName() + "母线" + busNum + "条";
                    }).sorted(Comparator
                            .comparing(EasyPoiWordExportServiceImpl::extractVoltageNumber).reversed())
                    // 用分号连接
                    .collect(Collectors.joining(StrUtil.COMMA));
            strBuilderInner.append(resultContent).append(";");
            temStr.append(strBuilderInner);

        }
        bjReportDTO.setAreaInfo(temStr.toString().substring(0,temStr.length()-1));
        if(DateUtil.format(DateUtil.parse(param.getSearchBeginTime()), DatePattern.CHINESE_DATE_FORMATTER).equals(DateUtil.format(DateUtil.parse(param.getSearchEndTime()), DatePattern.CHINESE_DATE_FORMATTER))){
            bjReportDTO.setDateFormat(DateUtil.format(DateUtil.parse(param.getSearchBeginTime()), DatePattern.CHINESE_DATE_FORMATTER));
        }else {
            bjReportDTO.setDateFormat(DateUtil.format(DateUtil.parse(param.getSearchBeginTime()), DatePattern.CHINESE_DATE_FORMATTER)+"-"+DateUtil.format(DateUtil.parse(param.getSearchEndTime()), DatePattern.CHINESE_DATE_FORMATTER));

        }
        bjReportDTO.setTotalDevice((int) devCount);
        bjReportDTO.setTotalSubstation((int) stationCount);
        bjReportDTO.setTotalBus((int) busCount);
    }


    private String busVoltageDeal(List<LedgerBaseInfoDTO> ledgerList,Map<String,PqsDicData> pqsDicDataMap){
        Map<String, List<LedgerBaseInfoDTO>> scaleMap = ledgerList.stream().collect(Collectors.groupingBy(LedgerBaseInfoDTO::getScale));
        String result = scaleMap.entrySet().stream()
                .map(entry -> {
                    String scale = entry.getKey();
                    long busNum = entry.getValue().stream()
                            .map(LedgerBaseInfoDTO::getBusBarId)
                            .distinct()
                            .count();
                    return pqsDicDataMap.get(scale).getDicName() + "母线" + busNum + "条";
                }).sorted(Comparator
                .comparing(EasyPoiWordExportServiceImpl::extractVoltageNumber).reversed())
                // 用分号连接
                .collect(Collectors.joining(StrUtil.COMMA));
        return result;
    }

    private String areabusVoltageDeal(List<LedgerBaseInfoDTO> ledgerList,Map<String,PqsDicData> pqsDicDataMap){
        Map<String, List<LedgerBaseInfoDTO>> scaleMap = ledgerList.stream().collect(Collectors.groupingBy(LedgerBaseInfoDTO::getScale));
        String result = scaleMap.entrySet().stream()
                .map(entry -> {
                    String scale = entry.getKey();
                    long busNum = entry.getValue().stream()
                            .map(LedgerBaseInfoDTO::getBusBarId)
                            .distinct()
                            .count();
                    return busNum + "条"+pqsDicDataMap.get(scale).getDicName() + "母线" ;
                }).sorted(Comparator
                        .comparing(EasyPoiWordExportServiceImpl::extractVoltageNumber).reversed())
                // 用分号连接
                .collect(Collectors.joining(StrUtil.COMMA));
        return result;
    }
    /**
     * 提取kV前的数字（核心方法）
     */
    public static Integer extractVoltageNumber(String text) {
        if (text == null || text.isEmpty()) {
            return null;
        }

        // 使用正则表达式匹配数字+kV的模式
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("(\\d+)kV");
        java.util.regex.Matcher matcher = pattern.matcher(text);

        if (matcher.find()) {
            try {
                return Integer.parseInt(matcher.group(1));
            } catch (NumberFormatException e) {
                System.err.println("数字格式错误: " + matcher.group(1));
                return null;
            }
        }
        return null;
    }
    private String stationVoltageDeal(List<LedgerBaseInfoDTO> ledgerList,Map<String,PqsDicData> pqsDicDataMap){
        Map<String, List<LedgerBaseInfoDTO>> scaleMap = ledgerList.stream().collect(Collectors.groupingBy(LedgerBaseInfoDTO::getScale));
        String result = scaleMap.entrySet().stream()
                .map(entry -> {
                    String scale = entry.getKey();
                    long stationNum = entry.getValue().stream()
                            .map(LedgerBaseInfoDTO::getStationId)
                            .distinct()
                            .count();
                    return pqsDicDataMap.get(scale).getDicName() + "变电站" + stationNum + "座";
                })
                // 用分号连接
                .collect(Collectors.joining(StrUtil.COMMA));
        return result;
    }

    private String userToStr(Map<String,List<PqUserLedgerPO>> stringListMap,Map<String,PqsDicTreePO> treePOMap){
        String result = stringListMap.entrySet().stream()
                .map(entry -> {
                    String scale = entry.getKey();
                    long busNum = entry.getValue().stream()
                            .map(PqUserLedgerPO::getId)
                            .distinct()
                            .count();
                    return treePOMap.get(scale).getName();
                })
                // 用分号连接
                .collect(Collectors.joining(StrUtil.COMMA));
        return result;
    }



    public static void main(String[] args) {
        String temp ="共监测到电压暂降事件%s条，涉及%s座变电站";
        String format = String.format(temp, 111, 111);
        System.out.println(format);

    }
}
