package com.njcn.gather.tools.comtrade.comparewave.core.io;

import com.njcn.gather.tools.comtrade.comparewave.core.model.PqsDataStruct;
import com.njcn.gather.tools.comtrade.comparewave.core.model.ThresholdConfig;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * 结果输出器
 * <p>对应C代码：main_pro.c中的结果输出部分</p>
 * <p><b>重要：输出格式必须与C代码完全一致</b></p>
 * <p>负责将电能质量检测数据的比较结果输出为多种格式的文件</p>
 * 
 * @author hongawen
 * @since 1.0
 */
@Slf4j
public class ResultWriter {
    
    /** 三位小数格式化器 */
    private static final DecimalFormat DF3 = new DecimalFormat("0.000");
    
    /** 两位小数格式化器 */
    private static final DecimalFormat DF2 = new DecimalFormat("0.00");
    
    /** 一位小数格式化器 */
    private static final DecimalFormat DF1 = new DecimalFormat("0.0");
    
    /**
     * 比较结果数据结构
     * <p>封装单个检测项目的比较结果信息</p>
     */
    public static class CompareResult {
        /** 检测项目名称 */
        public String itemName;
        
        /** 源设备数值 */
        public double sourceValue;
        
        /** 被检设备数值 */
        public double targetValue;
        
        /** 绝对误差 */
        public double absoluteError;
        
        /** 相对误差 (%) */
        public double relativeError;
        
        /** 阈值门限 */
        public double threshold;
        
        /** 是否超过门限 */
        public boolean isOverLimit;
        
        public CompareResult(String itemName, double sourceValue, double targetValue, double threshold) {
            this.itemName = itemName;
            this.sourceValue = sourceValue;
            this.targetValue = targetValue;
            this.threshold = threshold;
            this.absoluteError = Math.abs(targetValue - sourceValue);
            
            // 计算相对误差百分比
            if (Math.abs(sourceValue) > 0.001) {
                this.relativeError = this.absoluteError * 100.0 / Math.abs(sourceValue);
            } else {
                // 源值过小时，设置相对误差为零以避免除零错误
                this.relativeError = 0;
            }
            
            // 判断是否超过门限值
            this.isOverLimit = this.absoluteError > threshold;
        }
    }
    
    /**
     * 写入比较结果到多个文件
     * <p>对应C代码中的结果输出逻辑</p>
     * 
     * @param outputPath 输出文件夹路径
     * @param sourceData 源设备数据列表
     * @param targetData 被检设备数据列表
     * @param thresholds 门限配置信息
     * @throws IOException 文件输出异常
     */
    public static void writeCompareResults(String outputPath, 
                                          List<PqsDataStruct> sourceData,
                                          List<PqsDataStruct> targetData,
                                          ThresholdConfig thresholds) throws IOException {
        
        List<CompareResult> allResults = new ArrayList<>();
        
        // 比较所有数据点
        int dataPoints = Math.min(sourceData.size(), targetData.size());
        for (int i = 0; i < dataPoints; i++) {
            PqsDataStruct source = sourceData.get(i);
            PqsDataStruct target = targetData.get(i);
            
            // 比较有效值
            compareRmsValues(allResults, source, target, thresholds, i);
            
            // 比较谐波
            compareHarmonics(allResults, source, target, thresholds, i);
            
            // 比较功率
            comparePower(allResults, source, target, thresholds, i);
            
            // 比较序分量
            compareSequence(allResults, source, target, thresholds, i);
            
            // 比较频率
            compareFrequency(allResults, source, target, thresholds, i);
        }
        
        // 写入结果文件
        writeResultFile(outputPath + "/Result.txt", allResults);
        
        // 写入超限统计
        writeOverLimitSummary(outputPath + "/OverLimit.txt", allResults);
        
        // 写入CSV格式
        writeCsvResults(outputPath + "/diff_res_min_max.csv", allResults);
        
        // 写入完成标志
        writeCompleteFlag(outputPath + "/Completed.txt");
    }
    
    /**
     * 比较有效值
     */
    private static void compareRmsValues(List<CompareResult> results,
                                        PqsDataStruct source,
                                        PqsDataStruct target,
                                        ThresholdConfig thresholds,
                                        int dataPoint) {
        
        // 相电压有效值
        for (int i = 0; i < 3; i++) {
            String name = String.format("第%d点_U%c_RMS", dataPoint + 1, 'A' + i);
            results.add(new CompareResult(name, source.getRms()[i], target.getRms()[i], thresholds.getVoltageRmsThreshold()));
        }
        
        // 相电流有效值
        for (int i = 0; i < 3; i++) {
            String name = String.format("第%d点_I%c_RMS", dataPoint + 1, 'A' + i);
            results.add(new CompareResult(name, source.getRms()[i + 3], target.getRms()[i + 3], thresholds.getCurrentRmsThreshold()));
        }
        
        // 线电压有效值
        for (int i = 0; i < 3; i++) {
            String name = String.format("第%d点_U%c%c_RMS", dataPoint + 1, 
                'A' + i, 'B' + ((i + 1) % 3));
            results.add(new CompareResult(name, source.getRms()[i + 6], target.getRms()[i + 6], thresholds.getVoltageRmsThreshold()));
        }
    }
    
    /**
     * 比较谐波
     */
    private static void compareHarmonics(List<CompareResult> results,
                                        PqsDataStruct source,
                                        PqsDataStruct target,
                                        ThresholdConfig thresholds,
                                        int dataPoint) {
        
        // 比较前50次谐波
        for (int harm = 0; harm < 50; harm++) {
            // 电压谐波
            for (int ch = 0; ch < 3; ch++) {
                String name = String.format("第%d点_U%c_%d次谐波", dataPoint + 1, 'A' + ch, harm + 1);
                results.add(new CompareResult(name, 
                    source.getFuHarm()[ch][harm], 
                    target.getFuHarm()[ch][harm],
                        // 电压谐波门限: 1%Un
                    thresholds.getHarmonicVoltageThreshold()));
            }
            
            // 电流谐波
            for (int ch = 0; ch < 3; ch++) {
                String name = String.format("第%d点_I%c_%d次谐波", dataPoint + 1, 'A' + ch, harm + 1);
                results.add(new CompareResult(name, 
                    source.getFuHarm()[ch + 3][harm], 
                    target.getFuHarm()[ch + 3][harm],
                        // 电流谐波门限: 3%In
                    thresholds.getHarmonicCurrentThreshold()));
            }
        }
        
        // THD比较
        for (int ch = 0; ch < 6; ch++) {
            String prefix = ch < 3 ? "U" : "I";
            char phase = (char)('A' + (ch % 3));
            String name = String.format("第%d点_%c%c_THD", dataPoint + 1, prefix.charAt(0), phase);
            results.add(new CompareResult(name, 
                source.getHarmTHD()[ch], 
                target.getHarmTHD()[ch], 
                ch < 3 ? thresholds.getThdVoltageThreshold() : thresholds.getThdCurrentThreshold()));
        }
    }
    
    /**
     * 比较功率
     */
    private static void comparePower(List<CompareResult> results,
                                    PqsDataStruct source,
                                    PqsDataStruct target,
                                    ThresholdConfig thresholds,
                                    int dataPoint) {
        
        String[] phases = {"A", "B", "C", "总"};
        
        for (int i = 0; i < 4; i++) {
            // 有功功率
            String nameP = String.format("第%d点_%s_有功功率", dataPoint + 1, phases[i]);
            results.add(new CompareResult(nameP, source.getTotalP()[i], target.getTotalP()[i], thresholds.getActivePowerThreshold()));
            
            // 无功功率
            String nameQ = String.format("第%d点_%s_无功功率", dataPoint + 1, phases[i]);
            results.add(new CompareResult(nameQ, source.getTotalQ()[i], target.getTotalQ()[i], thresholds.getReactivePowerThreshold()));
            
            // 视在功率
            String nameS = String.format("第%d点_%s_视在功率", dataPoint + 1, phases[i]);
            results.add(new CompareResult(nameS, source.getTotalS()[i], target.getTotalS()[i], thresholds.getApparentPowerThreshold()));
            
            // 功率因数
            String namePF = String.format("第%d点_%s_功率因数", dataPoint + 1, phases[i]);
            results.add(new CompareResult(namePF, source.getCosPF()[i], target.getCosPF()[i], thresholds.getPowerFactorThreshold()));
        }
    }
    
    /**
     * 比较序分量
     */
    private static void compareSequence(List<CompareResult> results,
                                       PqsDataStruct source,
                                       PqsDataStruct target,
                                       ThresholdConfig thresholds,
                                       int dataPoint) {
        
        String[] seqNames = {"零序", "正序", "负序"};
        
        // 电压序分量
        for (int i = 0; i < 3; i++) {
            String name = String.format("第%d点_电压%s分量", dataPoint + 1, seqNames[i]);
            results.add(new CompareResult(name, source.getUiSeq()[0][i], target.getUiSeq()[0][i], thresholds.getSequenceVoltageThreshold()));
        }
        
        // 电流序分量
        for (int i = 0; i < 3; i++) {
            String name = String.format("第%d点_电流%s分量", dataPoint + 1, seqNames[i]);
            results.add(new CompareResult(name, source.getUiSeq()[1][i], target.getUiSeq()[1][i], thresholds.getSequenceCurrentThreshold()));
        }
        
        // 不平衡度
        String nameVUF = String.format("第%d点_电压负序不平衡度", dataPoint + 1);
        results.add(new CompareResult(nameVUF, source.getUiSeq()[0][4], target.getUiSeq()[0][4], thresholds.getUnbalanceThreshold()));
        
        String nameIUF = String.format("第%d点_电流负序不平衡度", dataPoint + 1);
        results.add(new CompareResult(nameIUF, source.getUiSeq()[1][4], target.getUiSeq()[1][4], thresholds.getUnbalanceThreshold()));
    }
    
    /**
     * 比较频率
     */
    private static void compareFrequency(List<CompareResult> results,
                                        PqsDataStruct source,
                                        PqsDataStruct target,
                                        ThresholdConfig thresholds,
                                        int dataPoint) {
        
        String nameFreq = String.format("第%d点_频率", dataPoint + 1);
        results.add(new CompareResult(nameFreq, source.getFreq()[0], target.getFreq()[0], thresholds.getFrequencyThreshold()));
        
        String nameDev = String.format("第%d点_频率偏差", dataPoint + 1);
        results.add(new CompareResult(nameDev, source.getFreq()[1], target.getFreq()[1], thresholds.getFrequencyDeviationThreshold()));
    }
    
    /**
     * 写入结果文件
     */
    private static void writeResultFile(String filePath, List<CompareResult> results) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
            writer.write("================================ 电能质量数据比较结果 ================================\n");
            writer.write("项目名称\t\t源值\t\t目标值\t\t绝对误差\t相对误差(%)\t门限\t\t是否超限\n");
            writer.write("====================================================================================\n");
            
            for (CompareResult result : results) {
                writer.write(String.format("%-30s\t%10s\t%10s\t%10s\t%10s\t%10s\t%s\n",
                    result.itemName,
                    DF3.format(result.sourceValue),
                    DF3.format(result.targetValue),
                    DF3.format(result.absoluteError),
                    DF3.format(result.relativeError),
                    DF3.format(result.threshold),
                    result.isOverLimit ? "超限" : "正常"
                ));
            }
            
            // 统计信息
            long overLimitCount = results.stream().filter(r -> r.isOverLimit).count();
            writer.write("\n====================================================================================\n");
            writer.write(String.format("总项目数: %d, 超限项目数: %d, 超限率: %.2f%%\n",
                results.size(), overLimitCount, overLimitCount * 100.0 / results.size()));
        }
    }
    
    /**
     * 写入超限汇总
     */
    private static void writeOverLimitSummary(String filePath, List<CompareResult> results) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
            writer.write("================================ 超限项目汇总 ================================\n");
            
            results.stream()
                .filter(r -> r.isOverLimit)
                .forEach(r -> {
                    try {
                        writer.write(String.format("%s: 源值=%s, 目标值=%s, 误差=%s, 门限=%s\n",
                            r.itemName,
                            DF3.format(r.sourceValue),
                            DF3.format(r.targetValue),
                            DF3.format(r.absoluteError),
                            DF3.format(r.threshold)
                        ));
                    } catch (IOException e) {
                        log.error("写入超限项目失败", e);
                    }
                });
        }
    }
    
    /**
     * 写入CSV结果
     */
    private static void writeCsvResults(String filePath, List<CompareResult> results) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
            // CSV头
            writer.write("项目名称,源值,目标值,绝对误差,相对误差(%),门限,是否超限\n");
            
            for (CompareResult result : results) {
                writer.write(String.format("%s,%.3f,%.3f,%.3f,%.3f,%.3f,%s\n",
                    result.itemName,
                    result.sourceValue,
                    result.targetValue,
                    result.absoluteError,
                    result.relativeError,
                    result.threshold,
                    result.isOverLimit ? "1" : "0"
                ));
            }
        }
    }
    
    /**
     * 写入完成标志
     */
    private static void writeCompleteFlag(String filePath) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
            writer.write("1\n");
            writer.write("比较完成时间: " + new java.util.Date() + "\n");
        }
    }
}