package com.njcn.product.advance.responsility.calculator;


import com.njcn.product.advance.responsility.analysis.CanonicalCorrelationAnalysis;
import com.njcn.product.advance.responsility.model.HarmonicData;
import com.njcn.product.advance.responsility.pojo.constant.CalculationMode;
import com.njcn.product.advance.responsility.pojo.constant.CalculationStatus;
import com.njcn.product.advance.responsility.pojo.constant.HarmonicConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 谐波责任计算主引擎
 * 严格对应C代码中的harm_res系列函数
 * 
 * @author hongawen
 * @version 2.0 - 修复版本，严格对照C代码实现
 */
public class HarmonicCalculationEngine {
    
    private static final Logger logger = LoggerFactory.getLogger(HarmonicCalculationEngine.class);
    
    // 对应C代码中的全局变量
    private int P;          // 节点数 p_node
    private int TL;         // 功率数据长度 p_num
    private int LL;         // 谐波数据长度 harm_num
    private int JIANGE;     // 数据间隔比例
    private int width;      // 窗口大小
    private float XIANE;    // 谐波门槛
    
    /**
     * 主计算入口
     * 对应C代码中的harm_res函数
     * 
     * @param data 谐波数据对象
     * @return 计算是否成功
     */
    public boolean calculate(HarmonicData data) {
        logger.info("Starting harmonic calculation, mode: {}", data.getCalculationMode());
        
        try {
            if (data.getCalculationMode() == CalculationMode.FULL_CALCULATION) {
                return fullCalculation(data);
            } else {
                return partialCalculation(data);
            }
        } catch (Exception e) {
            logger.error("Calculation failed with exception: " + e.getMessage(), e);
            e.printStackTrace();
            data.setCalculationStatus(CalculationStatus.FAILED);
            return false;
        }
    }
    
    /**
     * 完整计算模式
     * 严格对应C代码中的harm_res_all函数
     * 
     * @param data 谐波数据对象
     * @return 计算是否成功
     */
    private boolean fullCalculation(HarmonicData data) {
        logger.info("Executing full calculation mode");
        
        // 1. 数据初始化 - 对应 data_init_all()
        if (!initializeFullCalculationData(data)) {
            logger.error("Data initialization failed");
            data.setCalculationStatus(CalculationStatus.FAILED);
            return false;
        }
        
        // 2. 创建工作数组 - 对应C代码行536-540
        float[][] a = new float[TL][P];  // 功率数据副本
        float[] b = new float[LL];       // 谐波数据副本
        float[] u = new float[TL];       // 对齐后的谐波数据
        
        // 3. 复制数据 - 对应C代码行542-552
        for (int i = 0; i < TL; i++) {
            for (int j = 0; j < P; j++) {
                a[i][j] = data.getPowerData()[i][j];
            }
        }
        for (int i = 0; i < LL; i++) {
            b[i] = data.getHarmonicData()[i];
        }
        
        // 4. 数据对齐处理 - 严格对应C代码行554-562
        // 注意：C代码是原地修改数组b
        for (int i = 0; i < LL; i += JIANGE) {
            float tempt = 0.0f;
            for (int j = 0; j < JIANGE; j++) {
                tempt += b[i + j];
            }
            b[i] = tempt / JIANGE;  // 覆盖原位置
        }
        
        // 5. 构建Udata - 严格对应C代码行570-580
        // 注意：使用 i*JIANGE 索引
        for (int i = 0; i < TL; i++) {
            u[i] = b[i * JIANGE];  // 关键：使用 i*JIANGE 索引
        }
        
        int slcorlength = TL - width;
        
        // 6. 计算滑动典则相关系数 - 对应C代码行584
        logger.info("Computing sliding canonical correlation");
        float[] cancorrelation = CanonicalCorrelationAnalysis.slidingCanonicalCorrelation(
            a, u, width, P, TL
        );
        
        // 7. 保存典则相关系数 - 对应C代码行592-601
        float[] Core = new float[slcorlength];
        float[] BjCore = new float[slcorlength];
        for (int i = 0; i < slcorlength; i++) {
            Core[i] = cancorrelation[i];
            BjCore[i] = 1 - cancorrelation[i];
        }
        data.setCanonicalCorrelation(Core);
        data.setBackgroundCanonicalCorr(BjCore);
        
        // 8. 计算动态相关系数矩阵 - 对应C代码行605-635
        logger.info("Computing correlation matrix");
        float[][] simCor = new float[slcorlength][P];
        
        // 对应C代码行618-632：对每个节点计算动态相关系数
        for (int i = 0; i < P; i++) {
            // 提取第i个节点的功率数据
            float[] xe = new float[TL];
            for (int m = 0; m < TL; m++) {
                xe[m] = a[m][i];  // 对应 Pdata.block(0, i, TL, 1)
            }
            
            // 计算该节点的滑动相关系数
            float[] slidecor = CanonicalCorrelationAnalysis.slidingCorrelation(
                xe, u, cancorrelation, width
            );
            
            // 存储结果
            for (int j = 0; j < slcorlength; j++) {
                simCor[j][i] = slidecor[j];
            }
        }
        data.setCorrelationData(simCor);
        
        // 9. 计算EK值 - 对应C代码行642-654
        logger.info("Computing EK values");
        float[][] EKdata = ResponsibilityCalculator.computeEK(
            simCor, a, width, P, TL
        );
        
        // 10. 计算FK值 - 对应C代码行660-673
        logger.info("Computing FK values");
        float[][] FKdata = ResponsibilityCalculator.computeFK(
            EKdata, width, P, TL
        );
        data.setFkData(FKdata);
        
        // 11. 计算HK值 - 对应C代码行678-691
        logger.info("Computing HK values");
        float[][] HKdata = ResponsibilityCalculator.computeHK(
            BjCore, EKdata, width, P, TL
        );
        data.setHkData(HKdata);
        
        // 12. 设置结果数量 - 对应C代码行693
        data.setResponsibilityDataCount(slcorlength);
        
        // 13. 统计超限时段的责任 - 对应C代码行696-724
        logger.info("Computing responsibility sums");

        // 重要修正：C代码的SumHK函数中，虽然Udata长度是TL，但是循环只遍历前slg(=TL-width)个元素
        // 所以我们需要传入完整的u数组（长度TL），让sumResponsibility内部处理
        // 对应C代码：VectorXd Udata(TL); 以及 SumHK函数调用

        // 统计HK责任（包含背景）- 对应C代码行698-710
        // 注意：传入完整的u数组（TL长度），而不是截取的数组
        float[] sumHK = ResponsibilityCalculator.sumResponsibility(
            HKdata, u, XIANE, width, P + 1, TL
        );
        data.setSumHKData(sumHK);
        
        // 统计FK责任（不包含背景）- 对应C代码行712-724
        // 同样传入完整的u数组和TL参数
        float[] sumFK = ResponsibilityCalculator.sumResponsibility(
            FKdata, u, XIANE, width, P, TL
        );
        data.setSumFKData(sumFK);
        
        // 14. 标记计算成功 - 对应C代码行739
        data.setCalculationStatus(CalculationStatus.CALCULATED);
        logger.info("Full calculation completed successfully");
        
        return true;
    }
    
    /**
     * 初始化完整计算数据
     * 对应C代码中的data_init_all函数
     */
    private boolean initializeFullCalculationData(HarmonicData data) {
        // 设置全局变量 - 对应C代码行478-483
        P = data.getPowerNodeCount();
        TL = data.getPowerCount();
        LL = data.getHarmonicCount();
        // 对应C代码第481行：JIANGE = pq_buf.harm_num/pq_buf.p_num;
        // 重要修正：JIANGE应该是 谐波数量/功率点数，不是谐波数量/节点数
        JIANGE = LL / TL;  // 这个是正确的：harm_num / p_num (其中p_num是功率点数)
        width = data.getWindowSize();
        XIANE = data.getHarmonicThreshold();
        
        // 验证数据 - 对应C代码行485-504
        if (JIANGE * TL != LL || JIANGE < 1) {
            logger.error("Data length mismatch: JIANGE({}) * TL({}) != LL({})", 
                        JIANGE, TL, LL);
            return false;
        }
        
        if (width < HarmonicConstants.MIN_WIN_LEN || width > HarmonicConstants.MAX_WIN_LEN) {
            logger.error("Invalid window size: {}", width);
            return false;
        }
        
        if (TL < 2 * width) {
            logger.error("Power data length {} is too short for window size {}", TL, width);
            return false;
        }
        
        if (P > HarmonicConstants.MAX_P_NODE || TL > HarmonicConstants.MAX_P_NUM || 
            LL > HarmonicConstants.MAX_HARM_NUM) {
            logger.error("Data size exceeds limits");
            return false;
        }
        
        return true;
    }
    
    /**
     * 部分重算模式
     * 对应C代码中的harm_res_part函数
     * 
     * @param data 谐波数据对象
     * @return 计算是否成功
     */
    private boolean partialCalculation(HarmonicData data) {
        logger.info("Executing partial calculation mode");
        
        // 1. 数据初始化 - 对应 data_init_part()
        if (!initializePartialCalculationData(data)) {
            logger.error("Data initialization failed for partial calculation");
            data.setCalculationStatus(CalculationStatus.FAILED);
            return false;
        }
        
        // 2. 准备Udata - 对应C代码行816-818
        // C代码：VectorXd Udata(TL); 并从pq_buf.harm_data复制TL个元素
        int res_num = data.getResponsibilityDataCount();

        // 验证责任数据行数
        if (res_num != TL - width) {
            logger.warn("责任数据行数({})与期望值(TL-width={})不匹配", res_num, TL - width);
            res_num = TL - width;  // 使用正确的值
        }

        // 重要修正：与C代码保持一致，Udata长度应该是TL，而不是res_num
        // C代码：VectorXd Udata(TL);
        float[] Udata = new float[TL];

        // 从harm_data复制TL个元素到Udata
        // C代码：for (int j = 0; j < TL; j++) Udata[j] = pq_buf.harm_data[j];
        if (data.getHarmonicData().length < TL) {
            logger.warn("谐波数据长度({})小于TL({}), 将补零",
                       data.getHarmonicData().length, TL);
            System.arraycopy(data.getHarmonicData(), 0, Udata, 0, data.getHarmonicData().length);
            // 剩余部分自动补零
        } else {
            System.arraycopy(data.getHarmonicData(), 0, Udata, 0, TL);
        }

        logger.debug("准备Udata完成: 长度={} (对应C代码TL), 责任数据行数={}", Udata.length, res_num);

        // 3. 统计HK责任 - 对应C代码行806-830
        logger.info("Recalculating HK responsibility sums");

        // 对应C代码第808-814行：创建新的HKdata矩阵，只包含RES_NUM行
        // C代码：MatrixXd HKdata(RES_NUM, (P + 1));

        // 添加数据验证
        if (data.getHkData() == null || data.getHkData().length == 0) {
            logger.error("HK数据为空或长度为0");
            data.setCalculationStatus(CalculationStatus.FAILED);
            return false;
        }

        // 重要：C代码创建了新的RES_NUM行的HKdata，从原始数据复制前RES_NUM行
        // 对应C代码第808-814行
        float[][] HKdataForCalc = new float[res_num][P + 1];
        int copyRows = Math.min(res_num, data.getHkData().length);

        logger.debug("创建用于计算的HK数据矩阵: {}x{}, 从原始数据复制{}行",
                    res_num, P + 1, copyRows);

        for (int i = 0; i < copyRows; i++) {
            for (int j = 0; j < P + 1; j++) {
                if (j < data.getHkData()[i].length) {
                    HKdataForCalc[i][j] = data.getHkData()[i][j];
                }
            }
        }


        logger.debug("调用HK sumResponsibility参数: HKdata[{}x{}], Udata[{}], TL={}, width={}",
                    HKdataForCalc.length, HKdataForCalc.length > 0 ? HKdataForCalc[0].length : 0,
                    Udata.length, TL, width);

        try {
            // 对应C代码第819行：arrHKsum = SumHK(HKdata, Udata, wdith, colK, TL);
            float[] sumHK = ResponsibilityCalculator.sumResponsibility(
                HKdataForCalc,  // 使用新创建的RES_NUM行的HK数据
                Udata,          // 长度为TL的数组
                XIANE,
                width,
                P + 1,
                TL              // 传入TL参数
            );
            data.setSumHKData(sumHK);
            logger.debug("HK责任计算完成，结果长度: {}", sumHK != null ? sumHK.length : "null");
        } catch (Exception e) {
            logger.error("HK责任计算失败: " + e.getMessage(), e);
            throw e;
        }

        // 4. 统计FK责任 - 对应C代码行839-851
        logger.info("Recalculating FK responsibility sums");

        // 对应C代码：虽然没有显式创建新的FKdata，但逻辑相同

        // 添加数据验证
        if (data.getFkData() == null || data.getFkData().length == 0) {
            logger.error("FK数据为空或长度为0");
            data.setCalculationStatus(CalculationStatus.FAILED);
            return false;
        }

        // 创建用于计算的FK数据矩阵（RES_NUM行）
        float[][] FKdataForCalc = new float[res_num][P];
        int copyRowsFK = Math.min(res_num, data.getFkData().length);

        logger.debug("创建用于计算的FK数据矩阵: {}x{}, 从原始数据复制{}行",
                    res_num, P, copyRowsFK);

        for (int i = 0; i < copyRowsFK; i++) {
            for (int j = 0; j < P; j++) {
                if (j < data.getFkData()[i].length) {
                    FKdataForCalc[i][j] = data.getFkData()[i][j];
                }
            }
        }


        logger.debug("调用FK sumResponsibility参数: FKdata[{}x{}], Udata[{}], TL={}, width={}",
                    FKdataForCalc.length, FKdataForCalc.length > 0 ? FKdataForCalc[0].length : 0,
                    Udata.length, TL, width);

        try {
            // 对应C代码第840行：arrHKsum = SumHK(FKdata, Udata, wdith, colK, TL);
            float[] sumFK = ResponsibilityCalculator.sumResponsibility(
                FKdataForCalc,  // 使用新创建的RES_NUM行的FK数据
                Udata,          // 使用相同的Udata(长度TL)
                XIANE,
                width,
                P,
                TL              // 传入TL参数
            );
            data.setSumFKData(sumFK);
            logger.debug("FK责任计算完成，结果长度: {}", sumFK != null ? sumFK.length : "null");
        } catch (Exception e) {
            logger.error("FK责任计算失败: " + e.getMessage(), e);
            throw e;
        }
        
        // 5. 标记计算成功 - 对应C代码行858
        data.setCalculationStatus(CalculationStatus.CALCULATED);
        logger.info("Partial calculation completed successfully");
        
        return true;
    }
    
    /**
     * 初始化部分计算数据
     * 对应C代码中的data_init_part函数
     */
    private boolean initializePartialCalculationData(HarmonicData data) {
        // 设置变量 - 对应C代码行762-766
        int RES_NUM = data.getResponsibilityDataCount();
        P = data.getPowerNodeCount();
        TL = data.getWindowSize() + RES_NUM;
        width = data.getWindowSize();
        XIANE = data.getHarmonicThreshold();
        
        // 验证数据 - 对应C代码行756-778
        if ((RES_NUM + width) != data.getHarmonicCount()) {
            logger.error("Data length mismatch: res_num({}) + win({}) != harm_num({})",
                        RES_NUM, width, data.getHarmonicCount());
            return false;
        }
        
        if (width < HarmonicConstants.MIN_WIN_LEN || width > HarmonicConstants.MAX_WIN_LEN) {
            logger.error("Invalid window size: {}", width);
            return false;
        }
        
        if (P > HarmonicConstants.MAX_P_NODE || TL > HarmonicConstants.MAX_P_NUM) {
            logger.error("Data size exceeds limits");
            return false;
        }
        
        // 验证FK和HK数据存在
        if (data.getFkData() == null || data.getHkData() == null) {
            logger.error("FK or HK data is null");
            return false;
        }
        
        return true;
    }
}