package com.njcn.gather.tools.comtrade.comparewave.service.impl;

import com.njcn.gather.tools.comtrade.comparewave.config.PowerQualityConfig;
import com.njcn.gather.tools.comtrade.comparewave.core.algorithm.PowerQualityCalculator;
import com.njcn.gather.tools.comtrade.comparewave.core.algorithm.WaveformAligner;
import com.njcn.gather.tools.comtrade.comparewave.core.io.ComtradeReader;
import com.njcn.gather.tools.comtrade.comparewave.core.model.ClockStruct;
import com.njcn.gather.tools.comtrade.comparewave.core.model.CompareWaveDTO;
import com.njcn.gather.tools.comtrade.comparewave.core.model.DataPq;
import com.njcn.gather.tools.comtrade.comparewave.core.model.PqsDataStruct;
import com.njcn.gather.tools.comtrade.comparewave.service.ICompareWaveService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import static com.njcn.gather.tools.comtrade.comparewave.core.Constants.MAX_CH_NUM;

/**
 * 波形比对分析服务实现类
 *
 * <p>提供电能质量波形数据的分析和比对功能，支持：</p>
 * <ul>
 *   <li>COMTRADE格式文件的流式读取和解析</li>
 *   <li>波形对齐算法，确保比对数据的时序一致性</li>
 *   <li>电能质量参数计算（谐波、间谐波、THD、功率等）</li>
 *   <li>多种接线方式支持（星型、V型）</li>
 *   <li>结果比对分析和报告生成</li>
 * </ul>
 *
 * @author hongawen
 * @version 1.0
 * @since 2025-09-02
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CompareWaveServiceImpl implements ICompareWaveService {

    /**
     * 电能质量配置参数
     *
     * <p>包含分析计算所需的各项配置：</p>
     * <ul>
     *   <li>谐波分析参数（谐波次数、计算方式等）</li>
     *   <li>门限配置（RMS、THD、功率等门限值）</li>
     *   <li>采样参数（默认采样率、编码格式等）</li>
     *   <li>输出配置（结果文件路径等）</li>
     * </ul>
     */
    private final PowerQualityConfig powerQualityConfig;


    /**
     * 执行电能质量分析和比较（使用InputStream）
     *
     * @param sourceCfgStream 源CFG文件流
     * @param sourceDatStream 源DAT文件流
     * @param targetCfgStream 目标CFG文件流
     * @param targetDatStream 目标DAT文件流
     * @param lineConfig      接线方式 0=星型接线, 1=V型接线
     * @return 解析后的数据结果
     */
    @Override
    public CompareWaveDTO analyzeAndCompareWithStreams(
            InputStream sourceCfgStream, InputStream sourceDatStream,
            InputStream targetCfgStream, InputStream targetDatStream, int lineConfig) {

        CompareWaveDTO compareWaveDTO = new CompareWaveDTO();

        // 使用局部变量确保线程安全
        DataPq sourceDataBuf = new DataPq();
        DataPq targetDataBuf = new DataPq();
        try {
            log.info("开始电能质量分析（使用流模式）...");

            // 初始化数据缓冲区
            sourceDataBuf.init();
            targetDataBuf.init();

            // 设置配置参数（包括接线方式和额定值）
            applyConfiguration(sourceDataBuf, lineConfig);
            applyConfiguration(targetDataBuf, lineConfig);

            // 读取源文件流
            log.info("读取源文件流...");
            boolean sourceSuccess = ComtradeReader.readSampleFile(
                    sourceCfgStream, sourceDatStream, sourceDataBuf,
                    powerQualityConfig.getReading().getEncoding()
            );

            if (!sourceSuccess) {
                log.error("读取源文件流失败");
                return compareWaveDTO;
            }

            // 读取目标文件流
            log.info("读取目标文件流...");
            boolean targetSuccess = ComtradeReader.readSampleFile(
                    targetCfgStream, targetDatStream, targetDataBuf,
                    powerQualityConfig.getReading().getEncoding()
            );

            if (!targetSuccess) {
                log.error("读取目标文件流失败");
                return compareWaveDTO;
            }

            // 执行后续的对齐、计算和比较（复用现有逻辑）
            return performAnalysisAndComparison(sourceDataBuf, targetDataBuf);

        } catch (Exception e) {
            log.error("分析过程中发生错误", e);
            return compareWaveDTO;
        }
    }

    /**
     * 应用配置参数（带接线方式和额定值）
     *
     * @param dataBuf    数据缓冲区
     * @param lineConfig 接线方式（0: 星型接线, 1: V型接线）
     */
    private void applyConfiguration(DataPq dataBuf, int lineConfig) {
        // 设置计算参数
        dataBuf.getCfg().setHarmTime(powerQualityConfig.getCalculation().getHarmonicTimes());
        // 使用传入的接线方式
        dataBuf.getCfg().setLineConfig(lineConfig);
        dataBuf.getCfg().setIbAdd(powerQualityConfig.getCalculation().getIbAdd() ? 1 : 0);
        dataBuf.getCfg().setUharmAdd(powerQualityConfig.getCalculation().getUharmAdd() ? 1 : 0);
        log.info("配置已应用 - 接线方式: {} ({}), 额定电压: {}V, 额定电流: {}A",
                lineConfig,
                lineConfig == 0 ? "星型接线" : "V型接线");

        // 设置默认采样率
        if (dataBuf.getSmpRate() == 0) {
            dataBuf.setSmpRate(powerQualityConfig.getCalculation().getSampling().getDefaultRate());
        }
    }

    /**
     * 执行分析和比较的核心逻辑
     *
     * @param sourceDataBuf 源数据缓冲区
     * @param targetDataBuf 目标数据缓冲区
     * @return 是否成功
     */
    private CompareWaveDTO performAnalysisAndComparison(DataPq sourceDataBuf, DataPq targetDataBuf) {
        CompareWaveDTO compareWaveDTO = new CompareWaveDTO();
        try {
            // 执行波形对齐
            log.info("开始波形对齐...");
            WaveformAligner.AlignmentResult alignmentResult = WaveformAligner.findStartPosition(sourceDataBuf, targetDataBuf);

            if (!alignmentResult.isSuccess()) {
                log.error("波形对齐失败: {}", alignmentResult.getErrorMessage());
                return compareWaveDTO;
            }

            // 应用对齐结果
            WaveformAligner.applyAlignment(sourceDataBuf, targetDataBuf, alignmentResult);

            log.info("波形对齐完成 - 源文件起始位置: {}, 目标文件起始位置: {}, 可计算窗口数: {}",
                    alignmentResult.getStartPos1(), alignmentResult.getStartPos2(), alignmentResult.getCalNum());

            // 执行电能质量计算
            log.info("开始计算电能质量参数...");
            List<PqsDataStruct> sourceResults = calculatePowerQuality(sourceDataBuf);
            List<PqsDataStruct> targetResults = calculatePowerQuality(targetDataBuf);
            compareWaveDTO.setSourceResults(sourceResults);
            compareWaveDTO.setTargetResults(targetResults);
        } catch (Exception e) {
            log.error("分析和比较过程中发生错误", e);
        }
        return compareWaveDTO;
    }

    /**
     * 计算电能质量参数
     * 使用对齐后的起始位置和窗口数量
     */
    private List<PqsDataStruct> calculatePowerQuality(DataPq dataBuf) {
        List<PqsDataStruct> results = new ArrayList<>();

        // 获取对齐后的参数
        int startCalPos = dataBuf.getStartCalPos();
        int calNum = dataBuf.getCalNum();
        ClockStruct startCalTime = dataBuf.getStartCalTime();

        // 如果没有设置对齐参数，使用默认值（兼容性）
        if (startCalTime == null) {
            startCalPos = 0;
            calNum = Math.min(dataBuf.getSmpNum() / (int) (dataBuf.getSmpRate() * 10), 100);
            startCalTime = new ClockStruct();
            startCalTime.setYear(2024);
            startCalTime.setMonth(1);
            startCalTime.setDay(1);
            startCalTime.setHour(0);
            startCalTime.setMinute(0);
            startCalTime.setSecond(0);
            startCalTime.setMicroSecond(0);
        }

        // 计算周期：每200ms（10个周波）计算一次
        int samplesPerWindow = (int) (dataBuf.getSmpRate() * 10);  // 10个周波的采样点数

        log.info("使用对齐参数 - 起始位置: {}, 窗口数: {}, 每周波采样点数: {}",
                startCalPos, calNum, dataBuf.getSmpRate());

        // 重置数据点位置
        dataBuf.setDataPoint(0);

        // 对每个窗口进行计算
        for (int window = 0; window < calNum; window++) {
            // 计算当前窗口的结束位置
            // 对应C代码：pqs_200ms_data_cal(pq, &data_time, pq->start_cal_pos + (i+1)*pq->smp_rate*10)
            int smpWrPoint = startCalPos + (window + 1) * samplesPerWindow;

            // 检查是否超出数据范围
            if (smpWrPoint > dataBuf.getSmpNum()) {
                log.warn("窗口 {} 超出数据范围，跳过", window);
                break;
            }

            // 计算当前窗口的时间戳
            ClockStruct dataTime = new ClockStruct();
            dataTime.setYear(startCalTime.getYear());
            dataTime.setMonth(startCalTime.getMonth());
            dataTime.setDay(startCalTime.getDay());
            dataTime.setHour(startCalTime.getHour());
            dataTime.setMinute(startCalTime.getMinute());
            dataTime.setSecond(startCalTime.getSecond());
            dataTime.setMicroSecond(startCalTime.getMicroSecond());

            // 添加时间偏移（每个窗口200ms）
            int totalMs = dataTime.getMicroSecond() / 1000 + window * 200;
            if (totalMs >= 1000) {
                dataTime.setSecond(dataTime.getSecond() + totalMs / 1000);
                totalMs = totalMs % 1000;

                // 处理秒溢出
                if (dataTime.getSecond() >= 60) {
                    dataTime.setMinute(dataTime.getMinute() + dataTime.getSecond() / 60);
                    dataTime.setSecond(dataTime.getSecond() % 60);

                    // 处理分钟溢出
                    if (dataTime.getMinute() >= 60) {
                        dataTime.setHour(dataTime.getHour() + dataTime.getMinute() / 60);
                        dataTime.setMinute(dataTime.getMinute() % 60);
                    }
                }
            }
            dataTime.setMicroSecond(totalMs * 1000);

            log.debug("计算窗口 {}: smpWrPoint={}, 时间={}-{}-{} {}:{}:{}.{}",
                    window, smpWrPoint, dataTime.getYear(), dataTime.getMonth(), dataTime.getDay(),
                    dataTime.getHour(), dataTime.getMinute(), dataTime.getSecond(), totalMs);

            // 执行200ms数据计算
            PowerQualityCalculator.pqs200msDataCal(dataBuf, dataTime, smpWrPoint);

            // 获取计算结果
            PqsDataStruct result = dataBuf.getPqData()[window];
            results.add(result);

            // 日志输出部分结果用于调试
            log.info("第" + window + "个窗口计算结果 - UA有效值: {}, UB有效值: {}, UC有效值: {}, 时间为：" + result.getClocktime().format(),
                    result.getRms()[0], result.getRms()[1], result.getRms()[2]);
            log.info("第" + window + "个窗口计算结果 - IA有效值: {}, IB有效值: {}, IC有效值: {}, 时间为：" + result.getClocktime().format(),
                    result.getRms()[3], result.getRms()[4], result.getRms()[5]);
        }

        return results;
    }

    /**
     * 使用段信息保留模式分析波形（新方法，不影响原有逻辑）
     * <p>核心改进：</p>
     * <ol>
     * <li>不进行跨段的统一降采样，每个段保留原始采样率（超过512才降到256）</li>
     * <li>对齐后判断每个200ms窗口是否跨段</li>
     * <li>跨段的窗口丢弃，只计算不跨段的窗口</li>
     * <li>每个窗口使用其所在段的实际采样率进行计算</li>
     * </ol>
     *
     * @param sourceCfgStream 源文件CFG流
     * @param sourceDatStream 源文件DAT流
     * @param targetCfgStream 目标文件CFG流
     * @param targetDatStream 目标文件DAT流
     * @param lineConfig      接线方式
     * @return 分析结果
     */
    public CompareWaveDTO analyzeWithSegmentPreservation(
            InputStream sourceCfgStream, InputStream sourceDatStream,
            InputStream targetCfgStream, InputStream targetDatStream, int lineConfig) {

        CompareWaveDTO compareWaveDTO = new CompareWaveDTO();

        DataPq sourceDataBuf = new DataPq();
        DataPq targetDataBuf = new DataPq();
        try {
            log.info("开始电能质量分析（段信息保留模式）...");

            // 初始化数据缓冲区
            sourceDataBuf.init();
            targetDataBuf.init();

            // 设置配置参数
            applyConfiguration(sourceDataBuf, lineConfig);
            applyConfiguration(targetDataBuf, lineConfig);

            // 使用新方法读取文件（保留段信息）
            log.info("读取源文件（保留段信息）...");
            boolean sourceSuccess = ComtradeReader.readSampleFilePreserveSegments(
                    sourceCfgStream, sourceDatStream, sourceDataBuf,
                    powerQualityConfig.getReading().getEncoding()
            );

            if (!sourceSuccess) {
                log.error("读取源文件失败");
                return compareWaveDTO;
            }

            log.info("读取目标文件（保留段信息）...");
            boolean targetSuccess = ComtradeReader.readSampleFilePreserveSegments(
                    targetCfgStream, targetDatStream, targetDataBuf,
                    powerQualityConfig.getReading().getEncoding()
            );

            if (!targetSuccess) {
                log.error("读取目标文件失败");
                return compareWaveDTO;
            }

            // 执行波形对齐
            log.info("开始波形对齐...");
            WaveformAligner.AlignmentResult alignmentResult = WaveformAligner.findStartPosition(sourceDataBuf, targetDataBuf);
            int calNum = alignmentResult.getCalNum();

            if (calNum <= 0) {
                log.warn("波形对齐失败，可计算窗口数: {}", calNum);
                return compareWaveDTO;
            }

            // 应用对齐结果到数据缓冲区
            WaveformAligner.applyAlignment(sourceDataBuf, targetDataBuf, alignmentResult);

            log.info("波形对齐完成 - 源文件起始位置: {}, 目标文件起始位置: {}, 可计算窗口数: {}",
                    sourceDataBuf.getStartCalPos(), targetDataBuf.getStartCalPos(), calNum);

            // 同步计算两个文件的电能质量参数（确保窗口对应）
            calculatePowerQualityWithAlignedWindows(sourceDataBuf, targetDataBuf, calNum, compareWaveDTO);

            log.info("电能质量分析完成 - 源文件有效窗口: {}, 目标文件有效窗口: {}",
                    compareWaveDTO.getSourceResults() != null ? compareWaveDTO.getSourceResults().size() : 0,
                    compareWaveDTO.getTargetResults() != null ? compareWaveDTO.getTargetResults().size() : 0);

            return compareWaveDTO;

        } catch (Exception e) {
            log.error("分析过程中发生错误", e);
            return compareWaveDTO;
        }
    }

    /**
     * 同步计算两个文件的电能质量参数（确保窗口对应）
     * <p>如果某个窗口在任一文件中跨段，两个文件都丢弃该窗口</p>
     *
     * @param sourceDataBuf 源文件数据缓冲区
     * @param targetDataBuf 目标文件数据缓冲区
     * @param maxCalNum     最大窗口数
     * @param compareWaveDTO 结果对象
     */
    private void calculatePowerQualityWithAlignedWindows(
            DataPq sourceDataBuf, DataPq targetDataBuf, int maxCalNum, CompareWaveDTO compareWaveDTO) {

        List<PqsDataStruct> sourceResults = new ArrayList<>();
        List<PqsDataStruct> targetResults = new ArrayList<>();

        int sourceStartPos = sourceDataBuf.getStartCalPos();
        int targetStartPos = targetDataBuf.getStartCalPos();

        log.info("开始同步计算 - 源文件起始: {}, 目标文件起始: {}, 最大窗口数: {}",
                sourceStartPos, targetStartPos, maxCalNum);

        // 获取起始时间
        ClockStruct sourceStartTime = sourceDataBuf.getStartCalTime();
        ClockStruct targetStartTime = targetDataBuf.getStartCalTime();

        if (sourceStartTime == null || targetStartTime == null) {
            log.error("起始时间为空，无法计算");
            return;
        }

        // 遍历每个窗口
        int sourceCurrentPos = sourceStartPos;
        int targetCurrentPos = targetStartPos;
        int validWindowCount = 0;

        for (int window = 0; window < maxCalNum; window++) {
            // 检查源文件窗口
            int sourceSegment = findSegmentIndex(sourceDataBuf, sourceCurrentPos);
            float sourceSampleRate = sourceDataBuf.getSegmentSampleRates()[sourceSegment];
            int sourceSamplesPerWindow = (int) (sourceSampleRate * 10);
            int sourceWindowEnd = sourceCurrentPos + sourceSamplesPerWindow;

            // 检查目标文件窗口
            int targetSegment = findSegmentIndex(targetDataBuf, targetCurrentPos);
            float targetSampleRate = targetDataBuf.getSegmentSampleRates()[targetSegment];
            int targetSamplesPerWindow = (int) (targetSampleRate * 10);
            int targetWindowEnd = targetCurrentPos + targetSamplesPerWindow;

            // 检查是否超出数据范围
            if (sourceWindowEnd > sourceDataBuf.getSmpNum() || targetWindowEnd > targetDataBuf.getSmpNum()) {
                log.warn("窗口 {} 超出数据范围，结束计算", window);
                break;
            }

            // 检查采样率是否过低（< 128）
            boolean sourceLowSampleRate = (sourceSampleRate < 128);
            boolean targetLowSampleRate = (targetSampleRate < 128);

            if (sourceLowSampleRate || targetLowSampleRate) {
                log.warn("窗口 {} - 采样率过低（源文件: {}点/周波, 目标文件: {}点/周波, 最小要求128），该窗口被丢弃",
                        window, sourceSampleRate, targetSampleRate);
                        
                
                // 推进位置到下一个窗口
                sourceCurrentPos = sourceWindowEnd;
                targetCurrentPos = targetWindowEnd;
                continue;
            }

            // 判断源文件窗口是否跨段
            int sourceEndSegment = findSegmentIndex(sourceDataBuf, sourceWindowEnd - 1);
            boolean sourceCrossSegment = (sourceSegment != sourceEndSegment);

            // 判断目标文件窗口是否跨段
            int targetEndSegment = findSegmentIndex(targetDataBuf, targetWindowEnd - 1);
            boolean targetCrossSegment = (targetSegment != targetEndSegment);

            // 如果任一文件跨段，两个文件都丢弃该窗口
            if (sourceCrossSegment || targetCrossSegment) {
                if (sourceCrossSegment) {
                    float sourceEndSampleRate = sourceDataBuf.getSegmentSampleRates()[sourceEndSegment];
                    log.warn("窗口 {} - 源文件跨段（段{}/{}点/周波 -> 段{}/{}点/周波），该窗口被丢弃",
                            window, sourceSegment, sourceSampleRate, sourceEndSegment, sourceEndSampleRate);
                }
                if (targetCrossSegment) {
                    float targetEndSampleRate = targetDataBuf.getSegmentSampleRates()[targetEndSegment];
                    log.warn("窗口 {} - 目标文件跨段（段{}/{}点/周波 -> 段{}/{}点/周波），该窗口被丢弃",
                            window, targetSegment, targetSampleRate, targetEndSegment, targetEndSampleRate);
                }

                // 推进位置到下一个窗口
                sourceCurrentPos = sourceWindowEnd;
                targetCurrentPos = targetWindowEnd;
                continue;
            }

            // 两个文件都不跨段，计算该窗口

            // 计算时间戳
            ClockStruct sourceDataTime = calculateWindowTime(sourceStartTime, window);
            ClockStruct targetDataTime = calculateWindowTime(targetStartTime, window);

            // 计算源文件窗口（如果采样率>512，降采样到256）
            PqsDataStruct sourceResult = calculateWindowWithDownsampling(
                    sourceDataBuf, sourceCurrentPos, sourceWindowEnd, 
                    sourceSampleRate, sourceDataTime, validWindowCount);
            sourceResults.add(sourceResult);

            // 计算目标文件窗口（如果采样率>512，降采样到256）
            PqsDataStruct targetResult = calculateWindowWithDownsampling(
                    targetDataBuf, targetCurrentPos, targetWindowEnd, 
                    targetSampleRate, targetDataTime, validWindowCount);
            targetResults.add(targetResult);

            log.info("有效窗口 {} (总窗口{}) - 源文件段{}/{}点, 目标文件段{}/{}点, UA: {}/{}, IA: {}/{}",
                    validWindowCount, window,
                    sourceSegment, sourceSampleRate, targetSegment, targetSampleRate,
                    sourceResult.getRms()[0], targetResult.getRms()[0],
                    sourceResult.getRms()[3], targetResult.getRms()[3]);

            validWindowCount++;

            // 推进到下一个窗口
            sourceCurrentPos = sourceWindowEnd;
            targetCurrentPos = targetWindowEnd;
        }

        // 校验结果数组长度是否一致（保险措施）
        if (sourceResults.size() != targetResults.size()) {
            int minSize = Math.min(sourceResults.size(), targetResults.size());
            log.warn("结果数组长度不一致！源文件: {}, 目标文件: {}, 截取到: {}",
                    sourceResults.size(), targetResults.size(), minSize);
            
            // 截取到较小的长度
            if (sourceResults.size() > minSize) {
                sourceResults = sourceResults.subList(0, minSize);
            }
            if (targetResults.size() > minSize) {
                targetResults = targetResults.subList(0, minSize);
            }
        }

        compareWaveDTO.setSourceResults(sourceResults);
        compareWaveDTO.setTargetResults(targetResults);
    }

    /**
     * 计算窗口电能质量参数（如果采样率>512，降采样到256）
     *
     * @param dataBuf       数据缓冲区
     * @param windowStart   窗口起始位置
     * @param windowEnd     窗口结束位置
     * @param sampleRate    窗口采样率（点/周波）
     * @param dataTime      时间戳
     * @param windowIndex   窗口索引
     * @return 计算结果
     */
    private PqsDataStruct calculateWindowWithDownsampling(
            DataPq dataBuf, int windowStart, int windowEnd,
            float sampleRate, ClockStruct dataTime, int windowIndex) {

        float originalRate = dataBuf.getSmpRate();
        int originalDataPoint = dataBuf.getDataPoint();

        try {
            // 判断是否需要降采样
            if (sampleRate > 512) {
                // 需要降采样到256
                int downsampleMod = Math.round(sampleRate / 256);
                float targetRate = 256;
                int windowSamples = windowEnd - windowStart;
                int downsampledSamples = (windowSamples + downsampleMod - 1) / downsampleMod;

                log.debug("窗口{}降采样: {}点/周波 -> 256点/周波, 模数: {}, 原始{}点 -> {}点",
                        windowIndex, sampleRate, downsampleMod, windowSamples, downsampledSamples);

                // 备份原始数据
                int[][] backup = new int[MAX_CH_NUM][windowSamples];
                for (int ch = 0; ch < MAX_CH_NUM; ch++) {
                    System.arraycopy(dataBuf.getSmpData()[ch], windowStart, backup[ch], 0, windowSamples);
                }

                // 降采样：每downsampleMod个点取1个
                int downsampledIndex = 0;
                for (int i = 0; i < windowSamples; i += downsampleMod) {
                    for (int ch = 0; ch < MAX_CH_NUM; ch++) {
                        dataBuf.getSmpData()[ch][windowStart + downsampledIndex] =
                                dataBuf.getSmpData()[ch][windowStart + i];
                    }
                    downsampledIndex++;
                }

                // 设置降采样后的采样率和窗口结束位置
                dataBuf.setSmpRate(targetRate);
                dataBuf.setDataPoint(windowIndex);
                int downsampledWindowEnd = windowStart + downsampledSamples;

                // 计算电能质量参数
                PowerQualityCalculator.pqs200msDataCal(dataBuf, dataTime, downsampledWindowEnd);

                // 恢复原始数据
                for (int ch = 0; ch < MAX_CH_NUM; ch++) {
                    System.arraycopy(backup[ch], 0, dataBuf.getSmpData()[ch], windowStart, windowSamples);
                }

            } else {
                // 不需要降采样，直接计算
                dataBuf.setSmpRate(sampleRate);
                dataBuf.setDataPoint(windowIndex);
                PowerQualityCalculator.pqs200msDataCal(dataBuf, dataTime, windowEnd);
            }

            return dataBuf.getPqData()[windowIndex];

        } finally {
            // 恢复原始设置
            dataBuf.setSmpRate(originalRate);
            dataBuf.setDataPoint(originalDataPoint);
        }
    }

    /**
     * 计算窗口的时间戳
     */
    private ClockStruct calculateWindowTime(ClockStruct startTime, int windowIndex) {
        ClockStruct dataTime = new ClockStruct();
        dataTime.setYear(startTime.getYear());
        dataTime.setMonth(startTime.getMonth());
        dataTime.setDay(startTime.getDay());
        dataTime.setHour(startTime.getHour());
        dataTime.setMinute(startTime.getMinute());
        dataTime.setSecond(startTime.getSecond());
        dataTime.setMicroSecond(startTime.getMicroSecond());

        // 添加时间偏移（每个窗口200ms）
        int totalMs = dataTime.getMicroSecond() / 1000 + windowIndex * 200;
        if (totalMs >= 1000) {
            dataTime.setSecond(dataTime.getSecond() + totalMs / 1000);
            totalMs = totalMs % 1000;

            if (dataTime.getSecond() >= 60) {
                dataTime.setMinute(dataTime.getMinute() + dataTime.getSecond() / 60);
                dataTime.setSecond(dataTime.getSecond() % 60);

                if (dataTime.getMinute() >= 60) {
                    dataTime.setHour(dataTime.getHour() + dataTime.getMinute() / 60);
                    dataTime.setMinute(dataTime.getMinute() % 60);
                }
            }
        }
        dataTime.setMicroSecond(totalMs * 1000);

        return dataTime;
    }

    /**
     * 计算电能质量参数（过滤跨段窗口）
     *
     * @param dataBuf      数据缓冲区（包含段信息）
     * @param startCalPos  起始计算位置
     * @param maxCalNum    最大窗口数
     * @return 有效窗口的计算结果
     */
    private List<PqsDataStruct> calculatePowerQualityWithSegmentFilter(
            DataPq dataBuf, int startCalPos, int maxCalNum) {

        List<PqsDataStruct> results = new ArrayList<>();

        // 获取起始时间
        ClockStruct startCalTime = dataBuf.getStartCalTime();
        if (startCalTime == null) {
            startCalTime = new ClockStruct();
            startCalTime.setYear(2024);
            startCalTime.setMonth(1);
            startCalTime.setDay(1);
            startCalTime.setHour(0);
            startCalTime.setMinute(0);
            startCalTime.setSecond(0);
            startCalTime.setMicroSecond(0);
        }

        // 重置数据点位置
        dataBuf.setDataPoint(0);

        log.info("开始计算电能质量参数 - 段数: {}, 起始位置: {}, 最大窗口数: {}",
                dataBuf.getSegmentCount(), startCalPos, maxCalNum);

        // 找出起始位置所在的段
        int currentSegment = findSegmentIndex(dataBuf, startCalPos);
        float currentSegmentRate = dataBuf.getSegmentSampleRates()[currentSegment];
        
        log.info("起始位置{}在段{}, 采样率: {}点/周波", startCalPos, currentSegment, currentSegmentRate);

        // 遍历每个窗口
        int validWindowCount = 0;
        int currentPos = startCalPos;  // 使用累计位置
        
        for (int window = 0; window < maxCalNum; window++) {
            // 找出窗口所在的段
            int windowStartSegment = findSegmentIndex(dataBuf, currentPos);
            float segmentSampleRate = dataBuf.getSegmentSampleRates()[windowStartSegment];
            int samplesPerWindow = (int) (segmentSampleRate * 10);  // 10个周波
            
            int windowStartPos = currentPos;
            int windowEndPos = currentPos + samplesPerWindow;

            // 检查窗口是否超出数据范围
            if (windowEndPos > dataBuf.getSmpNum()) {
                log.warn("窗口 {} 超出数据范围，结束计算", window);
                break;
            }

            // 判断窗口是否跨段
            int endSegment = findSegmentIndex(dataBuf, windowEndPos - 1);

            if (windowStartSegment != endSegment) {
                log.warn("窗口 {} 跨段（段{} -> 段{}），丢弃该窗口", window, windowStartSegment, endSegment);
                // 跨段窗口丢弃，但仍然推进位置到下一个窗口
                currentPos = windowEndPos;
                continue;
            }

            // 不跨段，计算窗口结束点
            int smpWrPoint = windowEndPos;

            // 计算当前窗口的时间戳
            ClockStruct dataTime = new ClockStruct();
            dataTime.setYear(startCalTime.getYear());
            dataTime.setMonth(startCalTime.getMonth());
            dataTime.setDay(startCalTime.getDay());
            dataTime.setHour(startCalTime.getHour());
            dataTime.setMinute(startCalTime.getMinute());
            dataTime.setSecond(startCalTime.getSecond());
            dataTime.setMicroSecond(startCalTime.getMicroSecond());

            // 添加时间偏移
            int totalMs = dataTime.getMicroSecond() / 1000 + window * 200;
            if (totalMs >= 1000) {
                dataTime.setSecond(dataTime.getSecond() + totalMs / 1000);
                totalMs = totalMs % 1000;

                if (dataTime.getSecond() >= 60) {
                    dataTime.setMinute(dataTime.getMinute() + dataTime.getSecond() / 60);
                    dataTime.setSecond(dataTime.getSecond() % 60);

                    if (dataTime.getMinute() >= 60) {
                        dataTime.setHour(dataTime.getHour() + dataTime.getMinute() / 60);
                        dataTime.setMinute(dataTime.getMinute() % 60);
                    }
                }
            }
            dataTime.setMicroSecond(totalMs * 1000);

            // 临时设置采样率为该段的采样率
            float originalSmpRate = dataBuf.getSmpRate();
            dataBuf.setSmpRate(segmentSampleRate);

            // 执行200ms数据计算
            PowerQualityCalculator.pqs200msDataCal(dataBuf, dataTime, smpWrPoint);

            // 恢复原始采样率
            dataBuf.setSmpRate(originalSmpRate);

            // 获取计算结果
            PqsDataStruct result = dataBuf.getPqData()[validWindowCount];
            results.add(result);

            log.info("有效窗口 {} (总窗口{}) - 段{}, 采样率: {}点/周波, UA有效值: {}, IA有效值: {}",
                    validWindowCount, window, windowStartSegment, segmentSampleRate,
                    result.getRms()[0], result.getRms()[3]);

            validWindowCount++;
            
            // 推进到下一个窗口的起始位置
            currentPos = windowEndPos;
        }

        return results;
    }

    /**
     * 查找指定采样点所在的段索引
     *
     * @param dataBuf    数据缓冲区
     * @param samplePos  采样点位置
     * @return 段索引
     */
    private int findSegmentIndex(DataPq dataBuf, int samplePos) {
        for (int seg = 0; seg < dataBuf.getSegmentCount(); seg++) {
            int segmentStart = dataBuf.getSegmentStartIndices()[seg];
            int segmentEnd;
            if (seg < dataBuf.getSegmentCount() - 1) {
                segmentEnd = dataBuf.getSegmentStartIndices()[seg + 1];
            } else {
                segmentEnd = dataBuf.getSmpNum();
            }

            if (samplePos >= segmentStart && samplePos < segmentEnd) {
                return seg;
            }
        }
        return dataBuf.getSegmentCount() - 1;  // 默认返回最后一段
    }

}
