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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.event.file.component.WaveFileComponent;
import com.njcn.event.file.pojo.dto.WaveDataDTO;
import com.njcn.event.file.pojo.enums.WaveFileResponseEnum;
import com.njcn.product.event.config.RedisUtil;
import com.njcn.product.event.devcie.mapper.PqLinedetailMapper;
import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.event.devcie.pojo.po.PqDevice;
import com.njcn.product.event.devcie.pojo.po.PqLine;
import com.njcn.product.event.devcie.pojo.po.PqLinedetail;
import com.njcn.product.event.devcie.pojo.po.PqsDeptsline;
import com.njcn.product.event.devcie.service.PqDeviceService;
import com.njcn.product.event.devcie.service.PqLineService;
import com.njcn.product.event.devcie.service.PqsDeptslineService;
import com.njcn.product.event.transientes.mapper.PqUserLedgerMapper;
import com.njcn.product.event.transientes.mapper.PqUserLineAssMapper;
import com.njcn.product.event.transientes.pojo.dto.MessaeDTO;
import com.njcn.product.event.transientes.pojo.param.MonitorTerminalParam;
import com.njcn.product.event.transientes.pojo.po.*;
import com.njcn.product.event.transientes.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: cdf
 * @CreateTime: 2025-06-30
 * @Description:
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class EventGateServiceImpl implements EventGateService {

    private final PqsEventdetailService pqsEventdetailService;
    private final PqDeviceService pqDeviceService;
    private final WaveFileComponent waveFileComponent;
    private final PqLineService pqLineService;
    private final PqLinedetailMapper pqLinedetailMapper;
    private final PqsDeptslineService pqsDeptslineService;
    private final PqsDeptsService pqsDeptsService;
    private final PqsUsersetService pqsUsersetService;
    private final PqsUserService pqsUserService;
    private final PqUserLineAssMapper pqUserLineAssMapper;
    private final PqUserLedgerMapper pqUserLedgerMapper;

    private final static String NAME_KEY = "LineCache:";
    private final RedisUtil redisUtil;
    @Value("${SYS_TYPE_ZT}")
    private String sysTypeZt;
    @Value("${business.wavePath}")
    private String WAVEPATH;


    /**
     * 波形分析
     * @param param
     * @return
     */
    @Override
    public WaveDataDTO getTransientAnalyseWave(MonitorTerminalParam param) {
        WaveDataDTO waveDataDTO;
        //获取暂降事件
        PqsEventdetail eventDetail = pqsEventdetailService.getById(param.getId());
        Integer lineid = eventDetail.getLineid();
        PqLine pqLine = pqLineService.getById(lineid);
        PqLinedetail pqLinedetail = pqLinedetailMapper.selectById(lineid);
        PqDevice device = pqDeviceService.getById(pqLine.getDevIndex());
        String waveName = eventDetail.getWavename();
        String cfgPath, datPath;
        if (StrUtil.isBlank(waveName)) {
            throw new BusinessException(WaveFileResponseEnum.ANALYSE_WAVE_NOT_FOUND);
        }
        cfgPath = WAVEPATH+"/"+device.getIp()+"/"+waveName+".CFG";
        datPath = WAVEPATH+"/"+device.getIp()+"/"+waveName+".DAT";
        log.info("本地磁盘波形文件路径----" + cfgPath);
        InputStream cfgStream = waveFileComponent.getFileInputStreamByFilePath(cfgPath);
        InputStream datStream = waveFileComponent.getFileInputStreamByFilePath(datPath);
        if (Objects.isNull(cfgStream) || Objects.isNull(datStream)) {
            throw new BusinessException(WaveFileResponseEnum.ANALYSE_WAVE_NOT_FOUND);
        }
        waveDataDTO = waveFileComponent.getComtrade(cfgStream, datStream, 1);

        waveDataDTO = waveFileComponent.getValidData(waveDataDTO);

        waveDataDTO.setPtType(pqLinedetail.getPttype());
        waveDataDTO.setPt(pqLine.getPt1()/ pqLine.getPt2());
        waveDataDTO.setCt(pqLine.getCt1()/ pqLine.getCt2());
        waveDataDTO.setMonitorName(pqLine.getName());
        return waveDataDTO;

    }

    @Override
    public MessaeDTO messageGenerate(String eventId) {
        MessaeDTO messaeDTO = new MessaeDTO();
//        messaeDTO.setEventId(eventId);
        PqsEventdetail eventDetail = pqsEventdetailService.getById(eventId);
        Double eventvalue = eventDetail.getEventvalue();
        BigDecimal eventvalueFormmat = new BigDecimal(eventvalue).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);

        Double persisttime = eventDetail.getPersisttime();
        BigDecimal persisttimeFormmat = new BigDecimal(persisttime).divide(new BigDecimal(1000)).setScale(3, RoundingMode.HALF_UP);

        List<PqUserLineAssPO> assList = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().eq(PqUserLineAssPO::getLineIndex, eventDetail.getLineid()));
        String str ;
        if (CollUtil.isNotEmpty(assList)) {
            List<String> userIds = assList.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());
            List<PqUserLedgerPO> poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper<PqUserLedgerPO>().select(PqUserLedgerPO::getId, PqUserLedgerPO::getCustomerName,PqUserLedgerPO::getIsShow).in(PqUserLedgerPO::getId, userIds));
            String sensitiveUser = poList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining(";"));

            str ="影响用户:"+sensitiveUser+";";

        } else {
            str = "";
        }

        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()));
        StringBuilder stringBuilder = new StringBuilder(LocalDateTimeUtil.format(eventDetail.getTimeid(), DatePattern.NORM_DATETIME_PATTERN));
        stringBuilder.append(".").append(eventDetail.getMs().toString()).append(",").append(LedgerBaseInfoDTOMap.get(eventDetail.getLineid()).getStationName())
                .append(LedgerBaseInfoDTOMap.get(eventDetail.getLineid()).getBusBarName())
//                            .append("_").append(jsonObject.get("pointname").toString())
                .append("发生电压暂降事件,事件残余电压:").append(eventvalueFormmat).append("%,持续时间:").append(persisttimeFormmat).append("S;");
        stringBuilder.append(str);

        messaeDTO.setMessage(stringBuilder.toString());
        List<PqsDeptsline> pqLineDept = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, eventDetail.getLineid()).eq(PqsDeptsline::getSystype, sysTypeZt).list();
        Set<String> deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet());
        Set<String> resultIds = getAllParentDeptIds(deptIds);
        List<PqsUserSet> pqsUserSetList = pqsUsersetService.lambdaQuery().eq(PqsUserSet::getIsNotice, 1).in(PqsUserSet::getDeptsIndex, resultIds).list();
        if (CollUtil.isEmpty(pqsUserSetList)) {
            //当前事件未找到用户信息，判断为不需要发送短信用户
            throw new BusinessException("当前事件暂无发送短信用户信息");
        }
        List<PqsUser> pqsUserList = pqsUserService.lambdaQuery().select(PqsUser::getUserIndex, PqsUser::getPhone, PqsUser::getName)
                .in(PqsUser::getUserIndex, pqsUserSetList.stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList())).list();
//        messaeDTO.setPqsUsers(pqsUserList);
        return messaeDTO;
    }

    @Override
    public MessaeDTO msgGenerateByMsg(String msg) {
        // 2. 解析为 LocalDateTime
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
//        LocalDateTime extractedTime = LocalDateTime.parse(dateTimeStr, formatter);
//
//        // 3. 计算前后各一分钟
//        LocalDateTime startTime = extractedTime.minusMinutes(1);
//        LocalDateTime endTime = extractedTime.plusMinutes(1);
//        //获取敏感用户直供变电站名称
//        List<PqUserLedgerPO> poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper<PqUserLedgerPO>().select(PqUserLedgerPO::getId, PqUserLedgerPO::getCustomerName,PqUserLedgerPO::getIsShow).eq(PqUserLedgerPO::getIsShow, 1));
//        List<String> userIds = poList.stream().map(PqUserLedgerPO::getId).collect(Collectors.toList());
//        List<PqUserLineAssPO> pqUserLineAssPOS = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().in(PqUserLineAssPO::getUserIndex, userIds));
//        List<Integer> lineIds = pqUserLineAssPOS.stream().map(PqUserLineAssPO::getLineIndex).distinct().collect(Collectors.toList());
//        LambdaQueryWrapper<PqsEventdetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.in(PqsEventdetail::getLineid,lineIds).between(PqsEventdetail::getTimeid,startTime,endTime);
//        List<PqsEventdetail> pqsEventdetails = pqsEventdetailService.list(lambdaQueryWrapper);
//
//        if (CollUtil.isEmpty(pqsUserSetList)) {
//            //当前事件未找到用户信息，判断为不需要发送短信用户
//            throw new BusinessException("当前事件暂无发送短信用户信息");
//        }
       return null;
    }

    @Override
    public MessaeDTO messageGenerateByIds(List<String> eventIds) {
        MessaeDTO messaeDTO = new MessaeDTO();

        List<PqsEventdetail> list = pqsEventdetailService.lambdaQuery().
                in(PqsEventdetail::getEventdetailIndex, eventIds).orderByAsc(PqsEventdetail::getTimeid).list();
        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.forEach(event->{
            event.setBusBarName(LedgerBaseInfoDTOMap.get(event.getLineid()).getBusBarName());
            event.setStationName(LedgerBaseInfoDTOMap.get(event.getLineid()).getStationName());
            List<PqUserLineAssPO> assList = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().eq(PqUserLineAssPO::getLineIndex, event.getLineid()));
            List<String> consumerNameList = new ArrayList<>();
            if (CollUtil.isNotEmpty(assList)) {
                List<String> userIds = assList.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());
                List<PqUserLedgerPO> poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper<PqUserLedgerPO>().select(PqUserLedgerPO::getId, PqUserLedgerPO::getCustomerName, PqUserLedgerPO::getIsShow).eq(PqUserLedgerPO::getIsShow,1).in(PqUserLedgerPO::getId, userIds));
                if(CollUtil.isNotEmpty(poList)){
                    consumerNameList= poList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.toList());
                }
            }
            event.setConsumerNameList(consumerNameList);
        });
        Map<String, List<PqsEventdetail>> groupFilterNull = list.stream()
                .filter(e -> e.getStationName() != null)
                .collect(Collectors.groupingBy(PqsEventdetail::getStationName));
//        AtomicInteger index = new AtomicInteger();

        String eventString = groupFilterNull.entrySet().stream().map(entry -> {
            String substationnName = entry.getKey();      // 例如 "110kV智芯变"
            List<PqsEventdetail> value = entry.getValue();
            StringBuilder sb = new StringBuilder();

            if (value.size() == 1) {

                BigDecimal eventvalue = new BigDecimal(value.get(0).getEventvalue()).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
                BigDecimal persisttime = new BigDecimal(value.get(0).getPersisttime()).divide(new BigDecimal(1000)).setScale(3, RoundingMode.HALF_UP);

                sb.append(substationnName).append(value.get(0).getBusBarName()).append("发生电压暂降,电压跌落至").append(eventvalue).append("%,持续时间:").append(persisttime).append("S");
                String ConsumerName = value.stream().map(PqsEventdetail::getConsumerNameList).flatMap(List::stream).distinct().collect(Collectors.joining(","));
                sb.append("，所带敏感用户为").append(ConsumerName);
            } else {
                Map<String, List<String>> BusNameMap = value.stream().map(PqsEventdetail::getBusBarName).distinct().collect(Collectors.groupingBy(EventGateServiceImpl::extractVoltage));
                String allBusName = BusNameMap.entrySet().stream()
                        .sorted(Map.Entry.comparingByKey()) // 按电压等级排序（110,220,500）
                        .map(tempEntry -> {
                            String voltage = tempEntry.getKey();      // 例如 "110kV"
                            List<String> busNameList = tempEntry.getValue();
                            // 构建组内字符串：第一个保留全名，后续的去掉电压前缀
                            StringBuilder busName = new StringBuilder();
                            for (int i = 0; i < busNameList.size(); i++) {
                                String fullName = busNameList.get(i).replace("母线","");
                                if (i == 0) {
                                    busName.append(fullName); // 第一个保留完整名称（含电压）
                                } else {
                                    // 去掉电压前缀（例如 "10kV3B#母线" -> "3B#"）
                                    String pureName = fullName.startsWith(voltage)
                                            ? fullName.substring(voltage.length())
                                            : fullName;
                                    busName.append("、").append(pureName.replace("母线",""));
                                }
                            }
                            return busName.toString();
                        })
                        .collect(Collectors.joining(","));
                BigDecimal eventvalueMin = new BigDecimal(value.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble())
                        .multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
                BigDecimal eventvalueMax = new BigDecimal(value.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble())
                        .multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);

                BigDecimal persisttimeMin = new BigDecimal(value.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble())
                        .divide(new BigDecimal(1000)).setScale(3, RoundingMode.HALF_UP);
                BigDecimal persisttimeMax = new BigDecimal(value.stream().mapToDouble(PqsEventdetail::getPersisttime).max().getAsDouble())
                        .divide(new BigDecimal(1000)).setScale(3, RoundingMode.HALF_UP);
                sb.append(substationnName).append(allBusName)
                        .append("母线电压跌落至").append(eventvalueMin).append("%—").append(eventvalueMax).append("%,持续时间:")
                        .append(persisttimeMin).append("S—").append(persisttimeMax).append("S");
                String ConsumerName = value.stream().map(PqsEventdetail::getConsumerNameList).flatMap(List::stream).distinct().collect(Collectors.joining(","));
                sb.append("，所带敏感用户为").append(ConsumerName);
            }

            return sb.toString();
        }).collect(Collectors.joining(";"));
        messaeDTO.setMessage(eventString);
        List<Integer> lineIds = list.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList());
        List<PqsDeptsline> pqLineDept = pqsDeptslineService.lambdaQuery().in(PqsDeptsline::getLineIndex, lineIds).eq(PqsDeptsline::getSystype, sysTypeZt).list();
        Set<String> deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet());
        Set<String> resultIds = getAllParentDeptIds(deptIds);
        List<PqsUserSet> pqsUserSetList = pqsUsersetService.lambdaQuery().eq(PqsUserSet::getIsNotice, 1).in(PqsUserSet::getDeptsIndex, resultIds).list();
        if (CollUtil.isEmpty(pqsUserSetList)) {
            //当前事件未找到用户信息，判断为不需要发送短信用户
            throw new BusinessException("当前事件暂无发送短信用户信息");
        }
        List<PqsUser> userMap = pqsUserService.lambdaQuery().select(PqsUser::getUserIndex, PqsUser::getPhone, PqsUser::getName)
                .in(PqsUser::getUserIndex, pqsUserSetList.stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList())).list();
        Map<String, List<PqsUserSet>> collect = pqsUserSetList.stream().collect(Collectors.groupingBy(PqsUserSet::getDeptsIndex));
        List<PqsDepts> allDeptList = pqsDeptsService.lambdaQuery().eq(PqsDepts::getState,1).list();
        Map<String, PqsDepts> collect1 = allDeptList.stream().collect(Collectors.toMap(PqsDepts::getDeptsIndex, Function.identity()));
        Map<String, List<PqsUser>> newMap = collect.entrySet().stream()
                .collect(Collectors.toMap(
                        entry -> collect1.get(entry.getKey()).getDeptsname() , // 重新设置key逻辑
                        entry ->{
                            return userMap.stream().filter(temp->entry.getValue().stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList()).contains(temp.getUserIndex())).collect(Collectors.toList());
                        }
                ));



        messaeDTO.setEventIds(eventIds);
        messaeDTO.setPqsUsers(newMap);
        return messaeDTO;
    }
    private static String extractVoltage(String name) {
        int kVIndex = name.indexOf("kV");
        if (kVIndex == -1) {
            log.info("存在台账"+name+"不符合命名规范");
            throw new IllegalArgumentException("无法解析电压等级: " + name);
        }
        // 返回从开头到 "kV" 结束的部分（包含 "kV"）
        return name.substring(0, kVIndex + 2);
    }
    private boolean shouldSendSMS( Double value , Double time ) {


        // 条件1: 电压降至50%以下，持续时间超过20ms
        if (value < 50 && time >= 20) {
            return true;
        }

        // 条件2: 电压降至50%—70%，持续时间超过200ms
        if (value >= 50 && value < 70 && time >= 200) {
            return true;
        }

        // 条件3: 电压降至70%—80%，持续时间超过500ms
        if (value >= 70 && value <= 80 && time >= 500) {
            return true;
        }

        return false;
    }

    public Set<String> getAllParentDeptIds(Set<String> deptIds) {
        // 首次获取直接父级
        List<PqsDepts> allDeptList = pqsDeptsService.lambdaQuery().list();
        // 递归获取所有父级
        Set<String> result = recursivelyGetParentIds(deptIds, allDeptList);
        return result;
    }

    /**
     * 递归获取所有父级ID
     *
     * @param currentParentIds 当前层级的父级ID集合
     * @return 所有层级的父级ID集合
     */
    private Set<String> recursivelyGetParentIds(Set<String> currentParentIds, List<PqsDepts> allDeptList) {
        Set<String> result = new HashSet<>(currentParentIds);
        Set<String> nextLevelParentIds = new HashSet<>();
        List<PqsDepts> parentDeptList = allDeptList.stream().filter(it -> currentParentIds.contains(it.getDeptsIndex())).collect(Collectors.toList());
        for (PqsDepts pqsDepts : parentDeptList) {
            if (!pqsDepts.getParentnodeid().equals("0")) {
                nextLevelParentIds.add(pqsDepts.getParentnodeid());
            }
        }
        // 如果有更高层级的父级，继续递归
        if (!nextLevelParentIds.isEmpty()) {
            Set<String> deeperParentIds = recursivelyGetParentIds(nextLevelParentIds, allDeptList);
            result.addAll(deeperParentIds);
        }
        return result;
    }
}
