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.util.*;
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;
    }

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