package com.lingniu.ingest.protocol.gb32960.codec;

import com.lingniu.ingest.codec.BccChecksum;
import io.netty.channel.embedded.EmbeddedChannel;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;

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

class Gb32960FrameDecoderTest {

    @Test
    void keepsPlatformLoginWithMd5HexPasswordAsOneFrame() {
        byte[] frame = buildPlatformLoginFrame("Hyundai", "f2e3445d7cda409fb4f278f6fb890734");
        EmbeddedChannel channel = new EmbeddedChannel(new Gb32960FrameDecoder());

        assertThat(channel.writeInbound(frame)).isTrue();

        byte[] decoded = channel.readInbound();
        assertThat(decoded).isEqualTo(frame);
        assertThat((Object) channel.readInbound()).isNull();
    }

    private static byte[] buildPlatformLoginFrame(String username, String password) {
        ByteArrayOutputStream body = new ByteArrayOutputStream();
        body.write(26); body.write(6); body.write(22); body.write(20); body.write(40); body.write(45);
        writeU16(body, 1);
        writePaddedAscii(body, username, 12);
        writePaddedAscii(body, password, password.length());
        body.write(0x01);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        out.write(0x23); out.write(0x23);
        out.write(0x05);
        out.write(0xFE);
        for (int i = 0; i < 17; i++) out.write(0);
        out.write(0x01);
        writeU16(out, 41);
        byte[] bodyBytes = body.toByteArray();
        out.write(bodyBytes, 0, bodyBytes.length);
        byte[] almost = out.toByteArray();
        out.write(BccChecksum.compute(almost, 2, almost.length - 2) & 0xFF);
        return out.toByteArray();
    }

    private static void writeU16(ByteArrayOutputStream os, int v) {
        os.write((v >> 8) & 0xFF);
        os.write(v & 0xFF);
    }

    private static void writePaddedAscii(ByteArrayOutputStream os, String value, int len) {
        byte[] bytes = value.getBytes(StandardCharsets.US_ASCII);
        int copy = Math.min(bytes.length, len);
        os.write(bytes, 0, copy);
        for (int i = copy; i < len; i++) os.write(0);
    }
}
