/*
 * 文 件 名:  ProtocolParserTest
 * 版    权:  华设设计集团股份有限公司
 * 描    述:  协议解析测试
 * 修 改 人:  lvwenbin
 * 修改时间:  2025/12/22
 */
package com.huashe.test;

import com.ruoyi.ems.charging.model.BaseFrame;
import com.ruoyi.ems.charging.model.req.*;
import com.ruoyi.ems.charging.model.resp.*;
import com.ruoyi.ems.charging.protocol.FrameParser;
import com.ruoyi.ems.charging.protocol.ProtocolConstants;
import com.ruoyi.ems.charging.utils.ByteUtils;
import com.ruoyi.ems.charging.utils.CRC16Utils;

/**
 * 协议解析测试
 * 验证编解码的正确性
 *
 * @author lvwenbin
 * @version [版本号, 2025/12/22]
 */
public class ProtocolParserTest {
    
    public static void main(String[] args) {
        System.out.println("========== 充电桩协议解析测试 ==========\n");
        
        // 测试CRC计算
        testCrc();
        
        // 测试登录请求解析
        testLoginRequest();
        
        // 测试登录应答编码
        testLoginResponse();
        
        // 测试心跳请求解析
        testHeartbeatRequest();
        
        // 测试心跳应答编码
        testHeartbeatResponse();
        
        // 测试实时数据解析
        testRealtimeData();
        
        // 测试工作参数设置编码
        testWorkParamSet();
        
        System.out.println("\n========== 测试完成 ==========");
    }
    
    /**
     * 测试CRC计算
     */
    private static void testCrc() {
        System.out.println("--- 测试CRC计算 ---");
        
        // 协议示例: 心跳请求
        // 68 0D 0001 00 03 32010200000001 01 00 6890
        byte[] data = ByteUtils.hexToBytes("0001 00 03 32010200000001 01 00");
        int crc = CRC16Utils.calculateCRC(data);
        System.out.printf("计算CRC: 0x%04X, 期望: 0x9068 (低位在前应为6890)%n", crc);
        
        // 验证：低字节在前，高字节在后
        System.out.printf("CRC低字节: 0x%02X, CRC高字节: 0x%02X%n", crc & 0xFF, (crc >> 8) & 0xFF);
        System.out.println();
    }
    
    /**
     * 测试登录请求解析
     */
    private static void testLoginRequest() {
        System.out.println("--- 测试登录请求(0x01)解析 ---");
        
        // 协议示例登录请求
        // 68 22 0000 00 01 55031412782305 00 02 0A 56342E312E353000 01 01010101010101010101 04 675A
        String hexData = "68 22 00 00 00 01 55 03 14 12 78 23 05 00 02 0A 56 34 2E 31 2E 35 30 00 01 01 01 01 01 01 01 01 01 01 04 67 5A";
        byte[] data = ByteUtils.hexToBytes(hexData);
        
        System.out.println("原始数据: " + ByteUtils.bytesToHex(data));
        
        BaseFrame frame = FrameParser.parse(data);
        if (frame instanceof LoginReqFrame) {
            LoginReqFrame login = (LoginReqFrame) frame;
            System.out.println("解析成功: " + login);
            System.out.println("  桩编码: " + login.getPileCode());
            System.out.println("  桩类型: " + login.getPileTypeDesc());
            System.out.println("  枪数量: " + login.getGunCount());
            System.out.println("  协议版本: " + login.getProtocolVersionDesc());
            System.out.println("  软件版本: " + login.getSoftwareVersion());
            System.out.println("  网络类型: " + login.getNetworkTypeDesc());
        } else {
            System.out.println("解析失败或类型不匹配");
        }
        System.out.println();
    }
    
    /**
     * 测试登录应答编码
     */
    private static void testLoginResponse() {
        System.out.println("--- 测试登录应答(0x02)编码 ---");
        
        LoginRespFrame resp = LoginRespFrame.success("55031412782305", 0);
        byte[] encoded = resp.encode();
        
        System.out.println("编码结果: " + ByteUtils.bytesToHex(encoded));
        System.out.println("帧长度: " + encoded.length);
        
        // 验证可以重新解析
        BaseFrame parsed = FrameParser.parse(encoded);
        System.out.println("重新解析: " + parsed);
        System.out.println();
    }
    
    /**
     * 测试心跳请求解析
     */
    private static void testHeartbeatRequest() {
        System.out.println("--- 测试心跳请求(0x03)解析 ---");
        
        // 协议示例
        // 68 0D 0001 00 03 32010200000001 01 00 6890
        String hexData = "68 0D 00 01 00 03 32 01 02 00 00 00 01 01 00 68 90";
        byte[] data = ByteUtils.hexToBytes(hexData);
        
        System.out.println("原始数据: " + ByteUtils.bytesToHex(data));
        
        BaseFrame frame = FrameParser.parse(data);
        if (frame instanceof HeartbeatReqFrame) {
            HeartbeatReqFrame hb = (HeartbeatReqFrame) frame;
            System.out.println("解析成功: " + hb);
            System.out.println("  桩编码: " + hb.getPileCode());
            System.out.println("  枪号: " + hb.getGunNo());
            System.out.println("  枪状态: " + hb.getGunStatusDesc());
        }
        System.out.println();
    }
    
    /**
     * 测试心跳应答编码
     */
    private static void testHeartbeatResponse() {
        System.out.println("--- 测试心跳应答(0x04)编码 ---");
        
        HeartbeatRespFrame resp = HeartbeatRespFrame.create("32010200000001", "01", 0x36);
        byte[] encoded = resp.encode();
        
        System.out.println("编码结果: " + ByteUtils.bytesToHex(encoded));
        System.out.println();
    }
    
    /**
     * 测试实时数据解析
     */
    private static void testRealtimeData() {
        System.out.println("--- 测试实时数据(0x13)解析 ---");
        
        // 创建模拟的实时数据帧
        RealtimeDataFrame data = new RealtimeDataFrame();
        data.setSequenceNo(0x031A);
        data.setTransactionNo("00000000000000000000000000000000");
        data.setPileCode("55031412782305");
        data.setGunNo("02");
        data.setStatus(ProtocolConstants.GUN_STATUS_CHARGING);
        data.setGunReturned(ProtocolConstants.GUN_RETURNED);
        data.setGunConnected(ProtocolConstants.GUN_CONNECTED);
        data.setOutputVoltage(ByteUtils.voltageToProtocol(380.5)); // 380.5V
        data.setOutputCurrent(ByteUtils.currentToProtocol(125.3)); // 125.3A
        data.setGunTemperature(ByteUtils.temperatureToProtocol(35)); // 35℃
        data.setGunLineCode(new byte[8]);
        data.setSoc(65);
        data.setBatteryMaxTemp(ByteUtils.temperatureToProtocol(42));
        data.setChargingTime(45); // 45分钟
        data.setRemainingTime(30); // 30分钟
        data.setChargingEnergy(ByteUtils.energyToProtocol(35.6789)); // 35.6789 kWh
        data.setLossCorrectedEnergy(ByteUtils.energyToProtocol(35.6789));
        data.setChargedAmount(ByteUtils.amountToProtocol(42.8147)); // 42.8147元
        data.setHardwareFault(0);
        
        // 编码
        byte[] encoded = data.encode();
        System.out.println("编码结果: " + ByteUtils.bytesToHex(encoded));
        System.out.println("帧长度: " + encoded.length);
        
        // 重新解析
        BaseFrame parsed = FrameParser.parse(encoded);
        if (parsed instanceof RealtimeDataFrame) {
            RealtimeDataFrame rd = (RealtimeDataFrame) parsed;
            System.out.println("解析成功: " + rd);
            System.out.println("  电压: " + rd.getOutputVoltageValue() + "V");
            System.out.println("  电流: " + rd.getOutputCurrentValue() + "A");
            System.out.println("  功率: " + String.format("%.2f", rd.getOutputPower()) + "kW");
            System.out.println("  电量: " + String.format("%.4f", rd.getChargingEnergyValue()) + "kWh");
            System.out.println("  金额: " + String.format("%.4f", rd.getChargedAmountValue()) + "元");
            System.out.println("  SOC: " + rd.getSoc() + "%");
            System.out.println("  状态: " + rd.getStatus());
        }
        System.out.println();
    }
    
    /**
     * 测试工作参数设置编码
     */
    private static void testWorkParamSet() {
        System.out.println("--- 测试工作参数设置(0x52)编码 ---");
        
        // 设置功率限制为80%
        WorkParamSetFrame frame = WorkParamSetFrame.createPowerLimit("32010200000001", 80, 0x08);
        byte[] encoded = frame.encode();
        
        System.out.println("编码结果: " + ByteUtils.bytesToHex(encoded));
        System.out.println("设置内容: " + frame);
        System.out.println();
    }
}
