package com.evobms.project.bms.controller;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;

public class GBT32960ExtremeDataExtractor {

    /**
     * 从完整的GBT32960协议数据中提取极值数据
     */
    public static ExtremeData extractExtremeData(byte[] receivedData, String deviceSn) {
        try {
            System.out.println("=== 开始提取极值数据 ===");

            // 1. 解密数据
            byte[] decryptedData = decryptGBT32960Data(receivedData, deviceSn);
            if (decryptedData == null) {
                System.err.println("数据解密失败");
                return null;
            }
            System.out.println("解密后数据长度: " + decryptedData.length + " 字节");
            System.out.println("解密数据: " + bytesToHex(decryptedData));

            // 2. 在数据单元中查找极值数据
            return findAndParseExtremeData(decryptedData);

        } catch (Exception e) {
            System.err.println("提取极值数据时发生错误: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解密GBT32960协议数据
     */
    private static byte[] decryptGBT32960Data(byte[] receivedData, String deviceSn) throws Exception {
        // 检查起始位
        if (receivedData.length < 25 || receivedData[0] != 0x23 || receivedData[1] != 0x23) {
            System.err.println("无效的GBT32960数据格式");
            return null;
        }

        int offset = 2; // 跳过起始位

        // 解析协议头部
        byte commandId = receivedData[offset++];
        byte responseFlag = receivedData[offset++];

        // VIN码 (17字节)
        offset += 17;

        // 加密方式
        byte encryptionMethod = receivedData[offset++];
        if (encryptionMethod != 0x03) {
            System.err.println("不支持的解密方式: " + encryptionMethod);
            return null;
        }

        // 数据单元长度
        int dataUnitLength = ((receivedData[offset] & 0xFF) << 8) | (receivedData[offset + 1] & 0xFF);
        offset += 2;

        System.out.println("数据单元长度: " + dataUnitLength);

        // 提取加密数据
        byte[] encryptedData = Arrays.copyOfRange(receivedData, offset, offset + dataUnitLength);

        // 生成AES密钥
        byte[] aesKey = generateAesKeyFromSn(deviceSn);

        // 解密数据
        return decryptData(encryptedData, aesKey);
    }

    /**
     * 从SN码生成AES密钥
     */
    private static byte[] generateAesKeyFromSn(String sn) {
        String keyStr = sn;
        while (keyStr.length() < 16) {
            keyStr += "0";
        }
        keyStr = keyStr.substring(0, 16);
        return keyStr.getBytes(java.nio.charset.StandardCharsets.UTF_8);
    }

    /**
     * AES解密
     */
    private static byte[] decryptData(byte[] encryptedData, byte[] key) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return cipher.doFinal(encryptedData);
    }

    /**
     * 在数据单元中查找并解析极值数据
     */
    public static ExtremeData findAndParseExtremeData(byte[] dataUnit) {
        if (dataUnit == null || dataUnit.length == 0) {
            return null;
        }

        int offset = 0;
        while (offset < dataUnit.length) {
            byte dataType = dataUnit[offset];

            if (dataType == 0x06) {
                System.out.println("找到极值数据，位置: " + offset);
                return parseExtremeData(dataUnit, offset);
            }

            // 跳过其他数据类型
            offset = skipDataItem(dataUnit, offset);
        }

        System.out.println("未找到极值数据");
        return null;
    }

    /**
     * 解析极值数据
     */
    private static ExtremeData parseExtremeData(byte[] data, int offset) {
        if (data == null || offset >= data.length) {
            return null;
        }

        ExtremeData extremeData = new ExtremeData();

        try {
            // 检查数据类型
            byte dataType = data[offset++];
            if (dataType != 0x06) {
                System.err.println("错误的数据类型，期望0x06(极值数据)，实际: 0x" + String.format("%02X", dataType));
                return null;
            }

            // 数据长度
            byte dataLength = data[offset++];
            System.out.println("极值数据长度: " + (dataLength & 0xFF) + " 字节");

            // 电池电压最高值 (2字节, 单位: 0.01V)
            int maxVoltage = ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
            offset += 2;
            extremeData.setMaxVoltage(maxVoltage / 100.0); // 转换为V
            System.out.println("最高电压原始值: " + maxVoltage + " (0.01V), 转换后: " + extremeData.getMaxVoltage() + "V");

            // 电池电压最高所在子系统号 (1字节)
            extremeData.setMaxVoltageSubsystemId(data[offset++] & 0xFF);

            // 电池电压最高所在电芯号 (1字节)
            extremeData.setMaxVoltageCellId(data[offset++] & 0xFF);

            // 电池电压最低值 (2字节, 单位: 0.01V)
            int minVoltage = ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
            offset += 2;
            extremeData.setMinVoltage(minVoltage / 100.0); // 转换为V
            System.out.println("最低电压原始值: " + minVoltage + " (0.01V), 转换后: " + extremeData.getMinVoltage() + "V");

            // 电池电压最低所在子系统号 (1字节)
            extremeData.setMinVoltageSubsystemId(data[offset++] & 0xFF);

            // 电池电压最低所在电芯号 (1字节)
            extremeData.setMinVoltageCellId(data[offset++] & 0xFF);

            // 电池温度最高值 (1字节, 偏移量40°C, 单位: 1°C)
            int maxTemperature = (data[offset++] & 0xFF) - 40;
            extremeData.setMaxTemperature(maxTemperature);
            System.out.println("最高温度原始值: " + (data[offset-1] & 0xFF) + ", 转换后: " + maxTemperature + "°C");

            // 电池温度最高所在子系统号 (1字节)
            extremeData.setMaxTemperatureSubsystemId(data[offset++] & 0xFF);

            // 电池温度最高所在探针号 (1字节)
            extremeData.setMaxTemperatureProbeId(data[offset++] & 0xFF);

            // 电池温度最低值 (1字节, 偏移量40°C, 单位: 1°C)
            int minTemperature = (data[offset++] & 0xFF) - 40;
            extremeData.setMinTemperature(minTemperature);
            System.out.println("最低温度原始值: " + (data[offset-1] & 0xFF) + ", 转换后: " + minTemperature + "°C");

            // 电池温度最低所在子系统号 (1字节)
            extremeData.setMinTemperatureSubsystemId(data[offset++] & 0xFF);

            // 电池温度最低所在探针号 (1字节)
            extremeData.setMinTemperatureProbeId(data[offset++] & 0xFF);

            System.out.println("极值数据解析完成");
            return extremeData;

        } catch (Exception e) {
            System.err.println("解析极值数据时发生错误: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 跳过数据项
     */
    private static int skipDataItem(byte[] data, int offset) {
        if (offset >= data.length) return offset;

        offset++; // 跳过数据类型
        if (offset < data.length) {
            byte length = data[offset];
            offset += 1 + (length & 0xFF); // 跳过长度字节和数据内容
        }

        return offset;
    }

    /**
     * 字节数组转16进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    /**
     * 极值数据实体类
     */
    public static class ExtremeData {
        private double maxVoltage;          // 最高电压 (V)
        private int maxVoltageSubsystemId;  // 最高电压子系统号
        private int maxVoltageCellId;       // 最高电压电芯号
        private double minVoltage;          // 最低电压 (V)
        private int minVoltageSubsystemId;  // 最低电压子系统号
        private int minVoltageCellId;       // 最低电压电芯号
        private int maxTemperature;         // 最高温度 (°C)
        private int maxTemperatureSubsystemId; // 最高温度子系统号
        private int maxTemperatureProbeId;  // 最高温度探针号
        private int minTemperature;         // 最低温度 (°C)
        private int minTemperatureSubsystemId; // 最低温度子系统号
        private int minTemperatureProbeId;  // 最低温度探针号

        // Getter和Setter方法
        public double getMaxVoltage() { return maxVoltage; }
        public void setMaxVoltage(double maxVoltage) { this.maxVoltage = maxVoltage; }

        public int getMaxVoltageSubsystemId() { return maxVoltageSubsystemId; }
        public void setMaxVoltageSubsystemId(int maxVoltageSubsystemId) { this.maxVoltageSubsystemId = maxVoltageSubsystemId; }

        public int getMaxVoltageCellId() { return maxVoltageCellId; }
        public void setMaxVoltageCellId(int maxVoltageCellId) { this.maxVoltageCellId = maxVoltageCellId; }

        public double getMinVoltage() { return minVoltage; }
        public void setMinVoltage(double minVoltage) { this.minVoltage = minVoltage; }

        public int getMinVoltageSubsystemId() { return minVoltageSubsystemId; }
        public void setMinVoltageSubsystemId(int minVoltageSubsystemId) { this.minVoltageSubsystemId = minVoltageSubsystemId; }

        public int getMinVoltageCellId() { return minVoltageCellId; }
        public void setMinVoltageCellId(int minVoltageCellId) { this.minVoltageCellId = minVoltageCellId; }

        public int getMaxTemperature() { return maxTemperature; }
        public void setMaxTemperature(int maxTemperature) { this.maxTemperature = maxTemperature; }

        public int getMaxTemperatureSubsystemId() { return maxTemperatureSubsystemId; }
        public void setMaxTemperatureSubsystemId(int maxTemperatureSubsystemId) { this.maxTemperatureSubsystemId = maxTemperatureSubsystemId; }

        public int getMaxTemperatureProbeId() { return maxTemperatureProbeId; }
        public void setMaxTemperatureProbeId(int maxTemperatureProbeId) { this.maxTemperatureProbeId = maxTemperatureProbeId; }

        public int getMinTemperature() { return minTemperature; }
        public void setMinTemperature(int minTemperature) { this.minTemperature = minTemperature; }

        public int getMinTemperatureSubsystemId() { return minTemperatureSubsystemId; }
        public void setMinTemperatureSubsystemId(int minTemperatureSubsystemId) { this.minTemperatureSubsystemId = minTemperatureSubsystemId; }

        public int getMinTemperatureProbeId() { return minTemperatureProbeId; }
        public void setMinTemperatureProbeId(int minTemperatureProbeId) { this.minTemperatureProbeId = minTemperatureProbeId; }

        @Override
        public String toString() {
            return String.format(
                    "=== 极值数据 ===\n" +
                            "电压信息:\n" +
                            "  最高电压: %.2f V (子系统%d, 电芯%d)\n" +
                            "  最低电压: %.2f V (子系统%d, 电芯%d)\n" +
                            "温度信息:\n" +
                            "  最高温度: %d°C (子系统%d, 探针%d)\n" +
                            "  最低温度: %d°C (子系统%d, 探针%d)",
                    maxVoltage, maxVoltageSubsystemId, maxVoltageCellId,
                    minVoltage, minVoltageSubsystemId, minVoltageCellId,
                    maxTemperature, maxTemperatureSubsystemId, maxTemperatureProbeId,
                    minTemperature, minTemperatureSubsystemId, minTemperatureProbeId
            );
        }
    }

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        try {
            // 模拟测试数据
            String testHexData = "23230200000000000000000000000000000000000003000C06420F01010FA102023C0101280202";
            byte[] testData = hexStringToByteArray(testHexData);
            String deviceSn = "TEST123456789";

            ExtremeData result = extractExtremeData(testData, deviceSn);
            if (result != null) {
                System.out.println(result.toString());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 16进制字符串转字节数组
     */
    private static byte[] hexStringToByteArray(String hex) {
        hex = hex.replaceAll("\\s", "");
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }
}
