package com.lingniu.ingest.protocol.jt1078;

import com.lingniu.ingest.api.ProtocolId;
import com.lingniu.ingest.api.pipeline.RawFrame;
import com.lingniu.ingest.identity.InMemoryVehicleIdentityService;
import com.lingniu.ingest.identity.VehicleIdentityBinding;
import com.lingniu.ingest.protocol.jt1078.media.Jt1078MalformedRtpEventPublisher;
import com.lingniu.ingest.protocol.jt1078.media.Jt1078MalformedRtpPacket;
import com.lingniu.ingest.protocol.jt1078.media.Jt1078MediaMessageId;
import org.junit.jupiter.api.Test;

import java.time.Instant;
import java.util.ArrayList;

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

class Jt1078MalformedRtpEventPublisherTest {

    @Test
    void malformedRtpPacketProducesRawFrameForUnifiedArchiveAndPassthrough() {
        ArrayList<RawFrame> frames = new ArrayList<>();
        Jt1078MalformedRtpEventPublisher publisher = new Jt1078MalformedRtpEventPublisher(
                new InMemoryVehicleIdentityService(), frames::add);
        Instant receivedAt = Instant.parse("2026-06-22T08:30:00Z");
        byte[] raw = new byte[]{0x30, 0x31, 0x63, 0x64};

        publisher.publish(new Jt1078MalformedRtpPacket(
                "udp", "10.0.0.8:1078", raw, raw.length, "jt1078 udp rtp packet too short: 4", receivedAt));

        assertThat(frames).hasSize(1);
        RawFrame frame = frames.getFirst();
        assertThat(frame.protocolId()).isEqualTo(ProtocolId.JT1078);
        assertThat(frame.command()).isEqualTo(Jt1078MediaMessageId.MALFORMED_RTP);
        assertThat(frame.payload()).isInstanceOf(Jt1078MalformedRtpPacket.class);
        assertThat(frame.rawBytes()).containsExactly(raw);
        assertThat(frame.receivedAt()).isEqualTo(receivedAt);
        assertThat(frame.sourceMeta()).containsEntry("transport", "udp")
                .containsEntry("peer", "10.0.0.8:1078")
                .containsEntry("malformedRtp", "true")
                .containsEntry("parseError", "true")
                .containsEntry("parseErrorMessage", "jt1078 udp rtp packet too short: 4")
                .containsEntry("packetLength", "4")
                .containsEntry("reason", "jt1078 udp rtp packet too short: 4");
    }

    @Test
    void malformedRtpPacketUsesSharedIdentityWhenSimIsAvailable() {
        InMemoryVehicleIdentityService identity = new InMemoryVehicleIdentityService();
        identity.bind(new VehicleIdentityBinding(
                ProtocolId.JT1078, "LNVIN107800000001", "013812345678", "", ""));
        ArrayList<RawFrame> frames = new ArrayList<>();
        Jt1078MalformedRtpEventPublisher publisher = new Jt1078MalformedRtpEventPublisher(identity, frames::add);
        Instant receivedAt = Instant.parse("2026-06-22T08:30:00Z");
        byte[] raw = new byte[]{0x30, 0x31, 0x63, 0x64, 0, 1};

        publisher.publish(new Jt1078MalformedRtpPacket(
                "tcp",
                "10.0.0.8:1078",
                "013812345678",
                raw,
                128,
                "jt1078 rtp packet too large: 128",
                receivedAt));

        assertThat(frames).hasSize(1);
        RawFrame frame = frames.getFirst();
        assertThat(frame.sourceMeta())
                .containsEntry("vin", "LNVIN107800000001")
                .containsEntry("sim", "013812345678")
                .containsEntry("identityResolved", "true")
                .containsEntry("identitySource", "BOUND_PHONE");
    }

    @Test
    void identityResolverFailureStillPublishesMalformedRtpWithOriginalPayload() {
        ArrayList<RawFrame> frames = new ArrayList<>();
        Jt1078MalformedRtpEventPublisher publisher = new Jt1078MalformedRtpEventPublisher(
                lookup -> {
                    throw new IllegalStateException("identity backend unavailable");
                },
                frames::add);
        Instant receivedAt = Instant.parse("2026-06-22T08:30:00Z");
        byte[] raw = new byte[]{0x30, 0x31, 0x63, 0x64, 0, 1};

        publisher.publish(new Jt1078MalformedRtpPacket(
                "tcp",
                "10.0.0.8:1078",
                "013812345678",
                raw,
                raw.length,
                "jt1078 rtp packet too short: 6",
                receivedAt));

        assertThat(frames).singleElement().satisfies(frame -> {
            assertThat(frame.protocolId()).isEqualTo(ProtocolId.JT1078);
            assertThat(frame.command()).isEqualTo(Jt1078MediaMessageId.MALFORMED_RTP);
            assertThat(frame.rawBytes()).containsExactly(raw);
            assertThat(frame.sourceMeta())
                    .containsEntry("vin", "unknown")
                    .containsEntry("sim", "013812345678")
                    .containsEntry("identityResolved", "false")
                    .containsEntry("identitySource", "UNKNOWN")
                    .containsEntry("identityError", "true")
                    .containsEntry("identityErrorMessage", "identity backend unavailable")
                    .containsEntry("parseError", "true")
                    .containsEntry("parseErrorMessage", "jt1078 rtp packet too short: 6");
        });
    }
}
