package com.lingniu.ingest.sink.kafka;

import com.lingniu.ingest.api.ProtocolId;
import com.lingniu.ingest.api.event.AlarmPayload;
import com.lingniu.ingest.api.event.LocationPayload;
import com.lingniu.ingest.api.event.RealtimePayload;
import com.lingniu.ingest.api.event.VehicleEvent;
import org.junit.jupiter.api.Test;

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

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

class TopicRouterTest {

    @Test
    void rawArchiveRoutesToVersionedGb32960RawTopicByDefault() {
        TopicRouter router = new TopicRouter(new KafkaSinkProperties.Topics());

        assertThat(router.route(rawArchive())).isEqualTo("vehicle.raw.gb32960.v1");
    }

    @Test
    void normalizedGb32960EventsRouteToVersionedEventTopicByDefault() {
        TopicRouter router = new TopicRouter(new KafkaSinkProperties.Topics());

        assertThat(router.route(realtime())).isEqualTo("vehicle.event.gb32960.v1");
        assertThat(router.route(location())).isEqualTo("vehicle.event.gb32960.v1");
        assertThat(router.route(alarm())).isEqualTo("vehicle.event.gb32960.v1");
        assertThat(router.route(login())).isEqualTo("vehicle.event.gb32960.v1");
        assertThat(router.route(logout())).isEqualTo("vehicle.event.gb32960.v1");
        assertThat(router.route(heartbeat())).isEqualTo("vehicle.event.gb32960.v1");
    }

    @Test
    void dlqDefaultsToVersionedGb32960DlqTopic() {
        KafkaSinkProperties.Topics topics = new KafkaSinkProperties.Topics();

        assertThat(topics.getDlq()).isEqualTo("vehicle.dlq.gb32960.v1");
    }

    private static VehicleEvent.RawArchive rawArchive() {
        return new VehicleEvent.RawArchive(
                "raw-1",
                "VIN001",
                ProtocolId.GB32960,
                Instant.parse("2026-06-23T07:00:00Z"),
                Instant.parse("2026-06-23T07:00:01Z"),
                "trace-raw-1",
                Map.of("platformAccount", "Hyundai"),
                0x02,
                0,
                new byte[] {0x23, 0x23});
    }

    private static VehicleEvent.Realtime realtime() {
        return new VehicleEvent.Realtime(
                "event-1",
                "VIN001",
                ProtocolId.GB32960,
                Instant.parse("2026-06-23T07:00:00Z"),
                Instant.parse("2026-06-23T07:00:01Z"),
                "trace-1",
                Map.of("platformAccount", "Hyundai"),
                new RealtimePayload(
                        42.1, 1234.5, 80.0, null, null,
                        null, null, null, null, null, null,
                        RealtimePayload.VehicleState.STARTED,
                        RealtimePayload.ChargingState.UNCHARGED,
                        RealtimePayload.RunningMode.ELECTRIC,
                        null, null, null,
                        113.12, 23.45, null, null, null, null));
    }

    private static VehicleEvent.Location location() {
        return new VehicleEvent.Location(
                "event-2",
                "VIN001",
                ProtocolId.GB32960,
                Instant.parse("2026-06-23T07:00:00Z"),
                Instant.parse("2026-06-23T07:00:01Z"),
                "trace-2",
                Map.of("platformAccount", "Hyundai"),
                new LocationPayload(113.12, 23.45, 0, 42.1, 90, 0, 0));
    }

    private static VehicleEvent.Alarm alarm() {
        return new VehicleEvent.Alarm(
                "event-3",
                "VIN001",
                ProtocolId.GB32960,
                Instant.parse("2026-06-23T07:00:00Z"),
                Instant.parse("2026-06-23T07:00:01Z"),
                "trace-3",
                Map.of("platformAccount", "Hyundai"),
                new AlarmPayload(
                        AlarmPayload.AlarmLevel.MINOR,
                        1,
                        "GB32960_ALARM",
                        List.of("1"),
                        Set.of("bit0"),
                        113.12,
                        23.45,
                        AlarmPayload.SafetyCategory.GENERAL,
                        false,
                        AlarmPayload.HydrogenLeakLevel.NONE,
                        false));
    }

    private static VehicleEvent.Login login() {
        return new VehicleEvent.Login(
                "event-4",
                "VIN001",
                ProtocolId.GB32960,
                Instant.parse("2026-06-23T07:00:00Z"),
                Instant.parse("2026-06-23T07:00:01Z"),
                "trace-4",
                Map.of("platformAccount", "Hyundai"),
                "iccid-1",
                "V2016");
    }

    private static VehicleEvent.Logout logout() {
        return new VehicleEvent.Logout(
                "event-5",
                "VIN001",
                ProtocolId.GB32960,
                Instant.parse("2026-06-23T07:00:00Z"),
                Instant.parse("2026-06-23T07:00:01Z"),
                "trace-5",
                Map.of("platformAccount", "Hyundai"));
    }

    private static VehicleEvent.Heartbeat heartbeat() {
        return new VehicleEvent.Heartbeat(
                "event-6",
                "VIN001",
                ProtocolId.GB32960,
                Instant.parse("2026-06-23T07:00:00Z"),
                Instant.parse("2026-06-23T07:00:01Z"),
                "trace-6",
                Map.of("platformAccount", "Hyundai"));
    }
}
