package com.njcn.advance.event.service.impl;

import cn.hutool.core.util.StrUtil;
import com.njcn.advance.enums.EnumEvt;
import com.njcn.advance.event.cause.jna.QvvrCauseDLL;
import com.njcn.advance.event.cause.model.DataFeature;
import com.njcn.advance.event.type.jna.*;
import com.njcn.advance.pojo.dto.EventAnalysisDTO;
import com.njcn.advance.event.service.IEventAdvanceService;
import com.njcn.advance.utils.Utils;
import com.njcn.common.config.GeneralInfo;
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.oss.constant.GeneralConstant;
import com.njcn.oss.constant.OssPath;
import com.njcn.oss.utils.FileStorageUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author hongawen
 * @version 1.0
 * @data 2025/7/30 10:51
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EventAdvanceServiceImpl implements IEventAdvanceService {

    private final GeneralInfo generalInfo;

    private final WaveFileComponent waveFileComponent;

    private final FileStorageUtil fileStorageUtil;

    private final Lock lock = new ReentrantLock();

    @Override
    public EventAnalysisDTO analysisCauseAndType(EventAnalysisDTO eventAnalysis) {
        //由于计算原因是异步操作，这里需要加锁不然JNI调用ddl文件会存在内存Invalid memory access
        lock.lock();
        try {
            WaveDataDTO waveDataDTO;
        String waveName = eventAnalysis.getWaveName();
        String wlFilePath = eventAnalysis.getWlFilePath();
        String cfgPath, datPath, cfgPath2, datPath2;
        String ip = eventAnalysis.getIp();
        if (generalInfo.getBusinessWaveFileStorage() == GeneralConstant.LOCAL_DISK) {
            cfgPath = Objects.isNull(wlFilePath) ? generalInfo.getBusinessWavePath() + File.separator + ip + File.separator + waveName + GeneralConstant.CFG : wlFilePath + GeneralConstant.CFG;
            datPath = Objects.isNull(wlFilePath) ? generalInfo.getBusinessWavePath() + File.separator + ip + File.separator + waveName + GeneralConstant.DAT : wlFilePath + GeneralConstant.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, 0);
        } else {
            cfgPath = Objects.isNull(wlFilePath) ? OssPath.WAVE_DIR + ip + StrUtil.SLASH + waveName + GeneralConstant.CFG : wlFilePath + GeneralConstant.CFG;
            datPath = Objects.isNull(wlFilePath) ? OssPath.WAVE_DIR + ip + StrUtil.SLASH + waveName + GeneralConstant.DAT : wlFilePath + GeneralConstant.DAT;
            //适配文件后缀小写
            cfgPath2 = Objects.isNull(wlFilePath) ? OssPath.WAVE_DIR + ip + StrUtil.SLASH + waveName + GeneralConstant.CFG.toLowerCase() : wlFilePath + GeneralConstant.CFG.toLowerCase();
            datPath2 = Objects.isNull(wlFilePath) ? OssPath.WAVE_DIR + ip + StrUtil.SLASH + waveName + GeneralConstant.DAT.toLowerCase() : wlFilePath + GeneralConstant.DAT.toLowerCase();
            log.info("文件服务器波形文件路径----" + cfgPath);
            try (
                    InputStream cfgStream = fileStorageUtil.getFileStream(cfgPath);
                    InputStream datStream = fileStorageUtil.getFileStream(datPath)
            ) {
                if (Objects.isNull(cfgStream) || Objects.isNull(datStream)) {
                    throw new BusinessException(WaveFileResponseEnum.ANALYSE_WAVE_NOT_FOUND);
                }
                waveDataDTO = waveFileComponent.getComtradeNoAddPoints(cfgStream, datStream, 0);
            } catch (Exception e) {
                try {
                    InputStream cfgStream = fileStorageUtil.getFileStream(cfgPath2);
                    InputStream datStream = fileStorageUtil.getFileStream(datPath2);
                    if (Objects.isNull(cfgStream) || Objects.isNull(datStream)) {
                        throw new BusinessException(WaveFileResponseEnum.ANALYSE_WAVE_NOT_FOUND);
                    }
                    waveDataDTO = waveFileComponent.getComtrade(cfgStream, datStream, 0);
                } catch (Exception e1) {
                    throw new BusinessException(WaveFileResponseEnum.WAVE_DATA_INVALID);
                }

            }
        }
        List<List<Float>> listWaveData = waveDataDTO.getListWaveData();
        // 暂降类型
        // 创建数据结构
        QvvrDLL.QvvrDataStruct typeDataStruct = new QvvrDLL.QvvrDataStruct();
        System.out.println("初始化qvvrdll成功-----------");
        typeDataStruct.smp_rate = waveDataDTO.getComtradeCfgDTO().getFinalSampleRate();
        System.out.println("采样率-----------" + typeDataStruct.smp_rate);
        typeDataStruct.smp_len = listWaveData.size();
        System.out.println("波形长度-----------" + listWaveData.size());

        // 获取ABC三相的瞬时数据
        for (int i = 0; i < listWaveData.size(); i++) {
            typeDataStruct.smp_va[i] = listWaveData.get(i).get(1);
            typeDataStruct.smp_vb[i] = listWaveData.get(i).get(2);
            typeDataStruct.smp_vc[i] = listWaveData.get(i).get(3);
        }


        // 执行算法分析 - 直接调用C DLL
        try {
            QvvrDLL.INSTANCE.qvvr_fun(typeDataStruct);
            System.out.println("调用qvvrdll成功-----------");
            if (typeDataStruct.evt_num > 0) {
                // 全局比较找出最小三相电压特征值
                float globalMinVoltage = Float.MAX_VALUE;
                int globalFaultType = 10;
                for (int i = 0; i < typeDataStruct.evt_num; i++) {
                    QvvrDLL.EventBuffer evt = typeDataStruct.evt_buf[i];
                    for (int j = 0; j < evt.u_min_num; j++) {
                        float u3min = evt.u3_min[j];
                        if (u3min < globalMinVoltage) {
                            globalMinVoltage = u3min;
                            globalFaultType = evt.qvvr_cata_type[j];
                        }
                    }
                }


                //上传HR
                eventAnalysis.setType(globalFaultType);
            } else {
                eventAnalysis.setType(DataFeature.TYPE10);
            }

            System.out.println("结束qvvrdll方法调用-----------");
        } catch (Exception e) {
            eventAnalysis.setType(DataFeature.TYPE10);
            eventAnalysis.setTypeFlag(0);
        }


        // 暂降原因JNA的方式
        QvvrCauseDLL.QvvrDataStruct causeDataStruct = new QvvrCauseDLL.QvvrDataStruct();
        causeDataStruct.smp_rate = waveDataDTO.getComtradeCfgDTO().getFinalSampleRate();
        causeDataStruct.smp_len = listWaveData.size();
        // 获取ABC三相的瞬时数据
        for (int i = 0; i < listWaveData.size(); i++) {
            causeDataStruct.smp_va[i] = listWaveData.get(i).get(1);
            causeDataStruct.smp_vb[i] = listWaveData.get(i).get(2);
            causeDataStruct.smp_vc[i] = listWaveData.get(i).get(3);
        }
        // 执行算法分析 - 直接调用C DLL
        try {
            QvvrCauseDLL.INSTANCE.qvvr_fun_cause(causeDataStruct);
            eventAnalysis.setCause(causeDataStruct.cause);
            if (causeDataStruct.no_cal != 0) {
                eventAnalysis.setCauseFlag(0);
            }
        } catch (Exception e) {
            eventAnalysis.setCause(DataFeature.CAUSE_TYPE0);
            eventAnalysis.setCauseFlag(0);
        }
        String str = null;
        try {
            str = WriteData2File(typeDataStruct,causeDataStruct);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (Objects.isNull(wlFilePath)) {
            String hdrPath = OssPath.WAVE_DIR + ip+StrUtil.SLASH;
            String hdrName =  waveName + GeneralConstant.HDR_LOWER;
            fileStorageUtil.uploadStreamSpecifyName(new ByteArrayInputStream(str.getBytes()),hdrPath,hdrName);
        } else {
            //  comtrade/00:B7:8D:00:A8:7A/PQMonitor_PQM1_00100_20260204_162453_071_WAV.hdr
            String fullPath =  wlFilePath + GeneralConstant.HDR_LOWER;
            int lastSlashIndex = fullPath.lastIndexOf('/');
            String hdrPath = fullPath.substring(0, lastSlashIndex + 1);
            String hdrName = fullPath.substring(lastSlashIndex + 1);
            fileStorageUtil.uploadStreamSpecifyName(new ByteArrayInputStream(str.getBytes()),hdrPath,hdrName);
        }
        System.out.println("暂降原因分析完毕===============");
        System.out.println("cause:" + eventAnalysis);
        } finally {
            lock.unlock(); // 释放锁
        }
        return eventAnalysis;
    }

    public String WriteData2File(QvvrDLL.QvvrDataStruct rect, QvvrCauseDLL.QvvrDataStruct causeDataStruct) throws Exception {
        StringBuilder stringBuilder = new StringBuilder("{" + EnumEvt.NEWLINE.getProperty());

        /**
         * @写入返回事件总数
         */
        stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.EVT_NUM.getProperty()));
        stringBuilder.append(EnumEvt.setEnter(Utils.int2String(rect.evt_num), 1));
        stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.EVT_BUF.getProperty()) + "[");

        /**
         * @写入返回事件参数
         */
        for (int i = 0; i < rect.evt_num; i++) {
            stringBuilder.append(EnumEvt.setNewLine() + EnumEvt.setTab(2));
            /**
             * @波形起始点
             */
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.POW_A.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.float2String(rect.evt_buf[i].POW_a), 3));
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.POW_B.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.float2String(rect.evt_buf[i].POW_b), 3));
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.POW_C.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.float2String(rect.evt_buf[i].POW_c), 3));
            /**
             * @跳变段电压变化率
             */
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.VOLTAGECHANGE_VA.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.float2String(rect.evt_buf[i].Voltagechange_Va), 3));
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.VOLTAGECHANGE_VB.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.float2String(rect.evt_buf[i].Voltagechange_Vb), 3));
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.VOLTAGECHANGE_VC.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.float2String(rect.evt_buf[i].Voltagechange_Vc), 3));
            /**
             * @持续时间
             */
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.HOLD_TIME_RMS.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.float2String(rect.evt_buf[i].hold_time_rms), 3));
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.HOLD_TIME_DQ.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.float2String(rect.evt_buf[i].hold_time_dq), 3));
            /**
             * @分段数目
             */
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.SEG_T_NUM.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.int2String(rect.evt_buf[i].SEG_T_num), 3));
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.SEG_T_IDX.getProperty()));
            stringBuilder.append(EnumEvt.setNewLine() + EnumEvt.setTab(3));

            for (int j = 0; j < rect.evt_buf[i].SEG_T_num; j++) {
                stringBuilder.append(EnumEvt.setEvtProperty(Utils.int2String(j)));

                if (rect.evt_buf[i].SEG_T_num - 1 == j) {
                    stringBuilder.append(Utils.int2String(rect.evt_buf[i].SEG_T_idx[j]));
                } else {
                    stringBuilder.append(EnumEvt.setEnter(Utils.int2String(rect.evt_buf[i].SEG_T_idx[j]), 4));
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @特征幅值
             */
            stringBuilder.append(EnumEvt.setEvtProperty(EnumEvt.U_MIN_NUM.getProperty()));
            stringBuilder.append(EnumEvt.setEnter(Utils.int2String(rect.evt_buf[i].u_min_num), 3));

            /**
             * @最小值位置
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.ORDER_MIN_IDX.getProperty(), null,
                        rect.evt_buf[i].order_min_idx[k]);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @A相电压特征值
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.UA_MIN.getProperty(), rect.evt_buf[i].ua_min[k], null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @B相电压特征值
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.UB_MIN.getProperty(), rect.evt_buf[i].ub_min[k], null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @C相电压特征值
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.UC_MIN.getProperty(), rect.evt_buf[i].uc_min[k], null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @三相电压特征值
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.U3_MIN.getProperty(), rect.evt_buf[i].u3_min[k], null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @A相相位正跳变
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.ANGLE_DIFF_AP.getProperty(), rect.evt_buf[i].angle_diff_ap[k],
                        null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @B相相位正跳变
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.ANGLE_DIFF_BP.getProperty(), rect.evt_buf[i].angle_diff_bp[k],
                        null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @C相相位正跳变
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.ANGLE_DIFF_CP.getProperty(), rect.evt_buf[i].angle_diff_cp[k],
                        null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @A相相位负跳变
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.ANGLE_DIFF_AN.getProperty(), rect.evt_buf[i].angle_diff_an[k],
                        null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @B相相位负跳变
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.ANGLE_DIFF_BN.getProperty(), rect.evt_buf[i].angle_diff_bn[k],
                        null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @C相相位负跳变
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.ANGLE_DIFF_CN.getProperty(), rect.evt_buf[i].angle_diff_cn[k],
                        null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @不平衡度
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.BPH_MAX_VALUE.getProperty(), rect.evt_buf[i].bph_max_value[k],
                        null);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @暂降原因
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.QVVR_CATA_CAUSE.getProperty(), null,
                        causeDataStruct.cause);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @暂降类型
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.QVVR_CATA_TYPE.getProperty(), null,
                        rect.evt_buf[i].qvvr_cata_type[k]);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(3), 3));

            /**
             * @暂降相别
             */
            for (int k = 0; k < rect.evt_buf[i].u_min_num; k++) {
                setEigenVlaue(k, stringBuilder, EnumEvt.QVVR_PHASETYPE.getProperty(), null,
                        rect.evt_buf[i].qvvr_phasetype[k]);

                if (rect.evt_buf[i].u_min_num - 1 == k) {
                    stringBuilder.delete(stringBuilder.lastIndexOf(","), stringBuilder.length() - 1);
                }
            }

            stringBuilder.append(EnumEvt.setClose(3));

            if (rect.evt_num - 1 == i) {
                stringBuilder.append(EnumEvt.setClose(2));
                stringBuilder.append("]" + EnumEvt.ENTER.getProperty());
            } else {
                stringBuilder.append(EnumEvt.setEnter(EnumEvt.setClose(2), 2));
            }
        }
        if(rect.evt_num==0){
            stringBuilder.append("]");

        }

        stringBuilder.append("}");
        return stringBuilder.toString();
    }
    /**
     * @特征值处理
     */
    public void setEigenVlaue(int len, StringBuilder stringBuilder, String string, Float f, Integer integer) {
        if (0 == len) {
            stringBuilder.append(EnumEvt.setEvtProperty(string));
            stringBuilder.append(EnumEvt.setNewLine() + EnumEvt.setTab(3));
        }

        stringBuilder.append(EnumEvt.setEvtProperty(Integer.toString(len)));

        if (null == f) {
            stringBuilder.append(EnumEvt.setEnter(Utils.int2String(integer.intValue()), 4));
        } else {
            stringBuilder.append(EnumEvt.setEnter(Utils.float2String(f.floatValue()), 4));
        }
    }

}
