package com.lingniu.ingest.vehiclestat.jt808;

import com.lingniu.ingest.sink.kafka.proto.TelemetryField;
import com.lingniu.ingest.sink.kafka.proto.TelemetrySnapshot;
import com.lingniu.ingest.sink.kafka.proto.VehicleEnvelope;
import org.junit.jupiter.api.Test;

import java.time.Instant;

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

class Jt808LocationPointExtractorTest {

    private final Jt808LocationPointExtractor extractor = new Jt808LocationPointExtractor();

    @Test
    void extractsJt808LocationPointWithVin() {
        var point = extractor.extract(envelope("JT808", "VIN001", "13900000001",
                field("longitude", "118.901034"),
                field("latitude", "31.946325"),
                field("speed_kmh", "52.3"),
                field("location_status_raw", "3"),
                field("total_mileage_km", "1234.5"))).orElseThrow();

        assertThat(point.vehicleKey()).isEqualTo("VIN001");
        assertThat(point.vin()).isEqualTo("VIN001");
        assertThat(point.phone()).isEqualTo("13900000001");
        assertThat(point.eventTime()).isEqualTo(Instant.ofEpochMilli(1_782_112_400_000L));
        assertThat(point.longitude()).isEqualTo(118.901034);
        assertThat(point.latitude()).isEqualTo(31.946325);
        assertThat(point.speedKmh()).isEqualTo(52.3);
        assertThat(point.statusFlag()).isEqualTo(3L);
        assertThat(point.totalMileageKm()).isEqualTo(1234.5);
    }

    @Test
    void usesPhoneFallbackWhenVinIsUnknown() {
        var point = extractor.extract(envelope("JT808", "unknown", "40692934289",
                field("longitude", "118.901034"),
                field("latitude", "31.946325"))).orElseThrow();

        assertThat(point.vehicleKey()).isEqualTo("jt808:40692934289");
        assertThat(point.vin()).isEqualTo("unknown");
        assertThat(point.phone()).isEqualTo("40692934289");
    }

    @Test
    void ignoresNonJt808Envelope() {
        assertThat(extractor.extract(envelope("GB32960", "VIN001", "",
                field("longitude", "118.901034"),
                field("latitude", "31.946325")))).isEmpty();
    }

    @Test
    void ignoresEnvelopeWithoutCoordinates() {
        assertThat(extractor.extract(envelope("JT808", "VIN001", "13900000001",
                field("longitude", "118.901034")))).isEmpty();
    }

    @Test
    void ignoresJt808NonLocationSnapshot() {
        VehicleEnvelope envelope = envelope("JT808", "VIN001", "13900000001",
                field("longitude", "118.901034"),
                field("latitude", "31.946325"))
                .toBuilder()
                .setTelemetrySnapshot(TelemetrySnapshot.newBuilder()
                        .setEventType("REGISTER")
                        .addFields(field("longitude", "118.901034"))
                        .addFields(field("latitude", "31.946325")))
                .build();

        assertThat(extractor.extract(envelope)).isEmpty();
    }

    private static VehicleEnvelope envelope(String source, String vin, String phone, TelemetryField... fields) {
        TelemetrySnapshot.Builder snapshot = TelemetrySnapshot.newBuilder().setEventType("LOCATION");
        for (TelemetryField field : fields) {
            snapshot.addFields(field);
        }
        return VehicleEnvelope.newBuilder()
                .setEventId("event-1")
                .setVin(vin)
                .setSource(source)
                .putMetadata("phone", phone)
                .setEventTimeMs(1_782_112_400_000L)
                .setIngestTimeMs(1_782_112_401_000L)
                .setTelemetrySnapshot(snapshot)
                .build();
    }

    private static TelemetryField field(String key, String value) {
        return TelemetryField.newBuilder()
                .setKey(key)
                .setValueType("DOUBLE")
                .setValue(value)
                .setQuality("GOOD")
                .build();
    }
}
