package com.lingniu.ingest.protocol.gb32960.codec.parser.vendor.guangdong;

import com.lingniu.ingest.protocol.gb32960.model.InfoBlock;
import org.junit.jupiter.api.Test;

import java.nio.ByteBuffer;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.within;

/**
 * 单元测试：广东燃料电池规范 fixed-length parser（0x32 / 0x33 / 0x34 / 0x80）逐字段还原。
 * 0x30/0x31 是变长，集成层会在 BodyParser 全链路测试里覆盖。
 */
class GdFcParserTest {

    @Test
    void dcDcBlockParsesAllFields() {
        // inV=300.0 inC=120.0 outV=560.0 outC=110.5 ctrlTemp=65°C
        ByteBuffer buf = ByteBuffer.wrap(new byte[]{
                0x0B, (byte) 0xB8, // 0x0BB8 = 3000  → 300.0 V
                0x04, (byte) 0xB0, // 0x04B0 = 1200  → 120.0 A
                0x15, (byte) 0xE0, // 0x15E0 = 5600  → 560.0 V
                0x04, 0x52,        // 0x0452 = 1106  → 110.6 A
                0x69               // 0x69 = 105 - 40 = 65 °C
        });
        InfoBlock.GuangdongFc.DcDc b =
                (InfoBlock.GuangdongFc.DcDc) new GdFcDcDcBlockParser().parse(buf);
        assertThat(b.inputVoltageV()).isCloseTo(300.0, within(1e-6));
        assertThat(b.inputCurrentA()).isCloseTo(120.0, within(1e-6));
        assertThat(b.outputVoltageV()).isCloseTo(560.0, within(1e-6));
        assertThat(b.outputCurrentA()).isCloseTo(110.6, within(1e-6));
        assertThat(b.controllerTempC()).isEqualTo(65);
    }

    @Test
    void airConditionerParsesPowerOffsetAndStatus() {
        // status=01 power raw=20 (= 15 kw after -5 offset) inputV=540.0
        ByteBuffer buf = ByteBuffer.wrap(new byte[]{
                0x01,
                0x00, 0x14,            // 20 - 5 = 15 kw
                0x15, (byte) 0x18      // 0x1518 = 5400 → 540.0 V
        });
        InfoBlock.GuangdongFc.AirConditioner b =
                (InfoBlock.GuangdongFc.AirConditioner) new GdFcAirConditionerBlockParser().parse(buf);
        assertThat(b.status()).isEqualTo(1);
        assertThat(b.powerKw()).isEqualTo(15);
        assertThat(b.compressorInputVoltageV()).isCloseTo(540.0, within(1e-6));
    }

    @Test
    void vehicleInfoParsesAmbientFields() {
        // collision=00 ambientTemp raw=70 (=30°C) ambientPressure raw=1100 (10kPa) h2Mass raw=80 (8.0 kg)
        ByteBuffer buf = ByteBuffer.wrap(new byte[]{
                0x00,
                0x00, 0x46,            // 70 - 40 = 30°C
                0x04, 0x4C,            // 0x044C = 1100 → 110*0.1 - 100 = 10.0 kPa
                0x00, 0x50             // 0x0050 = 80 → 8.0 kg
        });
        InfoBlock.GuangdongFc.VehicleInfo b =
                (InfoBlock.GuangdongFc.VehicleInfo) new GdFcVehicleInfoBlockParser().parse(buf);
        assertThat(b.collisionAlarm()).isEqualTo(0);
        assertThat(b.ambientTempC()).isEqualTo(30);
        assertThat(b.ambientPressureKpa()).isCloseTo(10.0, within(1e-6));
        assertThat(b.hydrogenMassKg()).isCloseTo(8.0, within(1e-6));
    }

    @Test
    void demoExtensionParsesInnerLengthAndFields() {
        // length=9, stackTemp=50, acV=372.0, acC=0, h2V=1.3V, h2C=0
        ByteBuffer buf = ByteBuffer.wrap(new byte[]{
                0x00, 0x09,            // declared length
                0x5A,                  // 90 - 40 = 50°C
                0x0E, (byte) 0x88,     // 0x0E88 = 3720 → 372.0V
                0x27, 0x10,            // 0x2710 = 10000 → 0 A (after -1000)
                0x00, 0x0D,            // 0x000D = 13 → 1.3V
                0x27, 0x10             // 0 A
        });
        InfoBlock.GuangdongFc.DemoExtension b =
                (InfoBlock.GuangdongFc.DemoExtension) new GdFcDemoExtensionBlockParser().parse(buf);
        assertThat(b.stackTempC()).isEqualTo(50);
        assertThat(b.airCompressorVoltageV()).isCloseTo(372.0, within(1e-6));
        assertThat(b.airCompressorCurrentA()).isCloseTo(0.0, within(1e-6));
        assertThat(b.hydrogenPumpVoltageV()).isCloseTo(1.3, within(1e-6));
        assertThat(b.hydrogenPumpCurrentA()).isCloseTo(0.0, within(1e-6));
    }
}
