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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.product.event.config.RedisUtil;
import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO;
import com.njcn.product.event.devcie.pojo.po.PqsDeptsline;
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.mapper.PqsEventdetailMapper;
import com.njcn.product.event.transientes.pojo.dto.SmsResponseDTO;
import com.njcn.product.event.transientes.pojo.dto.SmsSendDTO;
import com.njcn.product.event.transientes.pojo.po.*;
import com.njcn.product.event.transientes.service.*;
import com.njcn.product.event.transientes.utils.SmsUtils;
import com.njcn.product.event.transientes.websocket.WebSocketServer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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

/**
 * Description:
 * Date: 2026/05/29  上午 11:30【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SendMessageServiceImpl implements SendMessageService {
    private final PqUserLineAssMapper pqUserLineAssMapper;
    private final PqUserLedgerMapper pqUserLedgerMapper;
    private final PqsEventdetailMapper pqsEventdetailMapper;
    private final MsgEventInfoService msgEventInfoService;
    private final static String NAME_KEY = "LineCache:";
    private final RedisUtil redisUtil;
    private final ThreadPoolTaskExecutor smsTaskExecutor;
    private final PqsUsersetService pqsUsersetService;
    private final SmsUtils smsUtils;
    private final WebSocketServer webSocketServer;

    private final PqsDeptslineService pqsDeptslineService;
    @Value("${SYS_TYPE_ZT}")
    private String sysTypeZt;

    private final PqsDeptsService pqsDeptsService;

    private final PqsUserService pqsUserService;
    @Override
    public void sendMessage(LocalDateTime threeHourAgo, LocalDateTime now) {
        log.info("开始扫描暂态事件时间段："+threeHourAgo+"-"+now);

        //查询重要敏感客户
        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::getCreateTime,threeHourAgo,now);
        List<PqsEventdetail> pqsEventdetails = pqsEventdetailMapper.selectList(lambdaQueryWrapper);
        log.info("扫描到敏感客户暂态事件："+pqsEventdetails.size()+"条");

        if(!CollectionUtils.isEmpty(pqsEventdetails)){
            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<MsgEventInfo> msgEventInfos = msgEventInfoService.lambdaQuery().between(MsgEventInfo::getSendTime, threeHourAgo, now).eq(MsgEventInfo::getSendResult, 1).list();
            List<String> successSendEventIds = msgEventInfos.stream().map(MsgEventInfo::getEventIndex).distinct().collect(Collectors.toList());

            pqsEventdetails = pqsEventdetails.stream()
                    .filter(temp -> shouldSendSMS(temp.getEventvalue()*100, temp.getPersisttime(),temp.getWavetype()) && (!successSendEventIds.contains(temp.getEventdetailIndex())))
                    .collect(Collectors.toList());
            log.info("扫描到敏感客户暂态事件过滤后事件："+pqsEventdetails.size()+"条");

            if(!CollectionUtils.isEmpty(pqsEventdetails)){
                log.info("过滤后事件数："+pqsEventdetails.size());

                List<PqsEventdetail> finalPqsEventdetails = pqsEventdetails;
                poList.forEach(temp->{
                    List<Integer> tempLineIds = pqUserLineAssPOS.stream()
                            .filter(pqUserLineAssPO -> Objects.equals(pqUserLineAssPO.getUserIndex(), temp.getId()))
                            .map(PqUserLineAssPO::getLineIndex).collect(Collectors.toList());
                    if(CollectionUtils.isEmpty(tempLineIds)){
                        return;
                    }

                    List<PqsEventdetail> result = finalPqsEventdetails.stream().filter(pqsEventdetail -> tempLineIds.contains(pqsEventdetail.getLineid())).collect(Collectors.toList());
                    if(CollectionUtils.isEmpty(result)){
                        return;
                    }
                    //组装台账信息
                    List<LedgerBaseInfoDTO> tempLedger = ledgerBaseInfoDTOS.stream().filter(line -> tempLineIds.contains(line.getLineId())).collect(Collectors.toList());

                    Map<String, List<String>> busNameMap = tempLedger.stream().map(LedgerBaseInfoDTO::getBusBarName).collect(Collectors.groupingBy(SendMessageServiceImpl::extractVoltage));
                    String allBus = busNameMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(
                            entry -> {
                                return entry.getKey() + "母线" + entry.getValue().size() + "条";
                            }
                    ).collect(Collectors.joining("、"));
                    Map<String, List<String>> subStaionMap = tempLedger.stream().map(LedgerBaseInfoDTO::getStationName).distinct().collect(Collectors.groupingBy(SendMessageServiceImpl::extractVoltage));

                    String allsubStation = subStaionMap.entrySet().stream()
                            .sorted(Map.Entry.comparingByKey()) // 按电压等级排序（110,220,500）
                            .map(entry -> {
                                String voltage = entry.getKey();      // 例如 "110kV"
                                List<String> stations = entry.getValue();
                                // 构建组内字符串：第一个保留全名，后续的去掉电压前缀
                                StringBuilder sb = new StringBuilder();
                                for (int i = 0; i < stations.size(); i++) {
                                    String fullName = stations.get(i);
                                    if (i == 0) {
                                        sb.append(fullName); // 第一个保留完整名称（含电压）
                                    } else {
                                        // 去掉电压前缀（例如 "110kV标厂变" -> "标厂变"）
                                        String pureName = fullName.startsWith(voltage)
                                                ? fullName.substring(voltage.length())
                                                : fullName;
                                        sb.append("、").append(pureName);
                                    }
                                }
                                return sb.toString();
                            })
                            .collect(Collectors.joining(","));
                    result.forEach(event->{
                        event.setBusBarName(LedgerBaseInfoDTOMap.get(event.getLineid()).getBusBarName());
                        event.setStationName(LedgerBaseInfoDTOMap.get(event.getLineid()).getStationName());
                    });


                    Map<String, List<PqsEventdetail>> groupFilterNull = result.stream()
                            .filter(e -> e.getStationName() != null)
                            .collect(Collectors.groupingBy(PqsEventdetail::getStationName));
                    //组装暂降信息
                    StringBuilder stringBuilder = new StringBuilder(temp.getCustomerName());
                    stringBuilder.append("上级直供变电站共有相关"+allBus+",");
                    stringBuilder.append("涉及"+allsubStation+"。");
                    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 (index.getAndIncrement() == 0) {
                            sb.append(LocalDateTimeUtil.format(value.get(0).getTimeid(),DatePattern.NORM_DATETIME_MINUTE_PATTERN)).append(",");
                        }else {
                            sb.append(LocalDateTimeUtil.format(value.get(0).getTimeid(),"HH:mm")).append(",");

                        }
                        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");
                        } else {
//                            String minTime = LocalDateTimeUtil.format(value.stream()
//                                    .map(PqsEventdetail::getTimeid)
//                                    .min(LocalDateTime::compareTo).get(), DatePattern.NORM_DATETIME_MINUTE_PATTERN);
//                            String maxTime = LocalDateTimeUtil.format(value.stream()
//                                    .map(eventdetail -> {
//                                        return eventdetail.getTimeid().plus(Duration.ofMillis(eventdetail.getMs().longValue()));
//                                    })
//                                    .max(LocalDateTime::compareTo).get(), DatePattern.NORM_DATETIME_MS_FORMATTER);
//                            String BusNameList = value.stream().map(PqsEventdetail::getBusBarName).collect(Collectors.joining("、"));
                            Map<String, List<String>> BusNameMap = value.stream().map(PqsEventdetail::getBusBarName).distinct().collect(Collectors.groupingBy(SendMessageServiceImpl::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");
                        }

                        return sb.toString();
                    }).collect(Collectors.joining(";"));

                    stringBuilder.append(eventString).append("。");
                    List<Integer> eventLineIds = result.stream().map(PqsEventdetail::getLineid).collect(Collectors.toList());
                    List<String> eventdetailIndexs = result.stream().map(PqsEventdetail::getEventdetailIndex).collect(Collectors.toList());

                    List<PqsDeptsline> pqLineDept = pqsDeptslineService.lambdaQuery().in(PqsDeptsline::getLineIndex, eventLineIds).eq(PqsDeptsline::getSystype, sysTypeZt).list();
                    if(CollectionUtils.isEmpty(pqLineDept)){
                        return;
                    }
                    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)) {
                        //当前事件未找到用户信息，判断为不需要发送短信用户
                        return;
                    }
                    List<PqsUser> pqsUserList = pqsUserService.lambdaQuery().select(PqsUser::getUserIndex, PqsUser::getPhone, PqsUser::getName).in(PqsUser::getUserIndex, pqsUserSetList.stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList())).list();
//                    JSONObject jsonObject = new JSONObject();
//                    jsonObject.putOpt("messageContent", stringBuilder);
//                    jsonObject.putOpt("eventIds",result.stream().map(PqsEventdetail::getEventdetailIndex).collect(Collectors.toList()) );
//                    webSocketServer.sendMessageToAll(jsonObject.toString());

                    if(!CollectionUtils.isEmpty(pqsUserList)){
                        //开始发送短信
                        smsTaskExecutor.execute(() -> {
                            sendMessageforUser(stringBuilder.toString(), pqsUserList,eventdetailIndexs,resultIds);
                        });
                    }


                });


            }

        }


    }

    private void sendMessageforUser(String content, List<PqsUser> pqsUserList, List<String> eventdetailIndexs, Set<String> deptIds) {

        //发送短信
        List<MsgEventInfo> resultList = new ArrayList<>();
        List<SmsSendDTO.ItemInner> msgDTOList = new ArrayList<>();
        String message;
        if (content.length() > 500) {
            message = content.substring(0, 490).concat(";详情请登录电压暂降监测平台查看。");
        } else {
            message = content.toString();
        }
        for (PqsUser user : pqsUserList) {
            String msgId = IdUtil.simpleUUID();

            SmsSendDTO.ItemInner dto = new SmsSendDTO.ItemInner();
            dto.setContent(message);
            dto.setTo(user.getPhone());
            dto.setCustomMsgID(msgId);
            msgDTOList.add(dto);
            for (String eventdetailIndex : eventdetailIndexs) {
                MsgEventInfo msgEventInfo = new MsgEventInfo();
                msgEventInfo.setMsgIndex(msgId);
                msgEventInfo.setMsgContent(message);
                msgEventInfo.setPhone(user.getPhone());
                msgEventInfo.setUserId(user.getUserIndex());
                msgEventInfo.setUserName(user.getName());
                msgEventInfo.setIsHandle(0);
                msgEventInfo.setSendResult(0);
                msgEventInfo.setSendTime(LocalDateTime.now());
                msgEventInfo.setEventIndex(eventdetailIndex);
                resultList.add(msgEventInfo);
            }

        }

        List<SmsResponseDTO.SmsItem> result = smsUtils.sendSmSToUser(msgDTOList);
        Map<String, SmsResponseDTO.SmsItem> stringSmsItemMap = result.stream().collect(Collectors.toMap(SmsResponseDTO.SmsItem::getCustomMsgID, Function.identity()));

        resultList.forEach(item -> {
            if (stringSmsItemMap.containsKey(item.getMsgIndex())) {
                SmsResponseDTO.SmsItem smsItem = stringSmsItemMap.get(item.getMsgIndex());
                item.setSendResult(Objects.equals(smsItem.getCode(), "0") ? 1 : 0);
            }
        });
        JSONObject jsonObject = new JSONObject();
        jsonObject.putOpt("messageContent", content);
        jsonObject.putOpt("dept", String.join(StrUtil.COMMA, deptIds));

        jsonObject.putOpt("messageIds",resultList.stream().map(MsgEventInfo::getMsgIndex).collect(Collectors.toList()) );
        webSocketServer.sendMessageToAll(jsonObject.toString());
        msgEventInfoService.saveBatch(resultList);
    }

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


    private boolean shouldSendSMS(Double value , Double time, Integer wavetype) {
        if(wavetype==1){
            // 条件1: 电压降至50%以下，持续时间超过20ms
            if (value < 50 && value>=10&& 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;
            }
        } else if (wavetype==3) {
            if (value < 10&& time >= 20) {
                return true;
            }
        }


        return false;
    }

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

    public static void main(String[] args) {
//        Stream.of(1,2,3).collect(Collectors.toList()).forEach(
//                temp->{
//                    if(temp==2){
//                        return;
//                    }
//                    System.out.println(temp);
//                }
//        );
        List<String> substations = Arrays.asList(
                "110kV智芯变",
                "110kV标厂变",
                "110kV科创变",
                "220kV开发区变",
                "220kV高新变",
                "500kV枢纽换流站"
        );

        // 按电压等级字符串（含kV）分组
        Map<String, List<String>> grouped = substations.stream()
                .collect(Collectors.groupingBy(SendMessageServiceImpl::extractVoltage));
        String collect = grouped.entrySet().stream()
                .sorted(Map.Entry.comparingByKey()) // 按电压等级排序（110,220,500）
                .map(entry -> {
                    String voltage = entry.getKey();      // 例如 "110kV"
                    List<String> stations = entry.getValue();
                    // 构建组内字符串：第一个保留全名，后续的去掉电压前缀
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < stations.size(); i++) {
                        String fullName = stations.get(i);
                        if (i == 0) {
                            sb.append(fullName); // 第一个保留完整名称（含电压）
                        } else {
                            // 去掉电压前缀（例如 "110kV标厂变" -> "标厂变"）
                            String pureName = fullName.startsWith(voltage)
                                    ? fullName.substring(voltage.length())
                                    : fullName;
                            sb.append("、").append(pureName);
                        }
                    }
                    return sb.toString();
                })
                .collect(Collectors.joining(";"));
        System.out.println(collect);
    }
}
