package com.lingniu.ingest.core.pipeline.builtin;

import com.lingniu.ingest.api.ProtocolId;
import com.lingniu.ingest.api.pipeline.IngestContext;
import com.lingniu.ingest.api.pipeline.RawFrame;
import org.junit.jupiter.api.Test;

import java.time.Instant;
import java.util.Map;

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

class DedupInterceptorTest {

    @Test
    void usesRawFingerprintWhenSequenceIsMissing() {
        DedupInterceptor interceptor = new DedupInterceptor(100, 60);
        IngestContext ctx = new IngestContext("trace-1");

        RawFrame first = frame(new byte[]{0x23, 0x23, 0x02, 0x01});
        RawFrame differentPayload = frame(new byte[]{0x23, 0x23, 0x02, 0x02});
        RawFrame duplicate = frame(new byte[]{0x23, 0x23, 0x02, 0x01});

        assertThat(interceptor.before(first, ctx)).isTrue();
        assertThat(interceptor.before(differentPayload, ctx)).isTrue();
        assertThat(interceptor.before(duplicate, ctx)).isFalse();
        assertThat(ctx.aborted()).isTrue();
    }

    @Test
    void doesNotDeduplicateDifferentJt808PhonesWhenVinIsUnknownAndSequenceMatches() {
        DedupInterceptor interceptor = new DedupInterceptor(100, 60);

        RawFrame firstPhone = jt808Frame("13079960001", "1000");
        RawFrame secondPhone = jt808Frame("13079960002", "1000");
        RawFrame duplicateFirstPhone = jt808Frame("13079960001", "1000");

        assertThat(interceptor.before(firstPhone, new IngestContext("trace-1"))).isTrue();
        assertThat(interceptor.before(secondPhone, new IngestContext("trace-2"))).isTrue();
        IngestContext duplicateContext = new IngestContext("trace-3");
        assertThat(interceptor.before(duplicateFirstPhone, duplicateContext)).isFalse();
        assertThat(duplicateContext.abortReason()).contains("duplicate");
    }

    private static RawFrame frame(byte[] rawBytes) {
        return new RawFrame(
                ProtocolId.GB32960,
                0x02,
                0,
                new Object(),
                rawBytes,
                Map.of("vin", "TESTSTATVIN000001"),
                Instant.parse("2026-06-22T13:00:00Z"));
    }

    private static RawFrame jt808Frame(String phone, String seq) {
        return new RawFrame(
                ProtocolId.JT808,
                0x0200,
                0,
                new Object(),
                new byte[]{0x02, 0x00, 0x00, 0x1c},
                Map.of("vin", "unknown", "phone", phone, "seq", seq),
                Instant.parse("2026-06-22T13:00:00Z"));
    }
}
