package com.lingniu.ingest.vehiclestate;

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 static org.assertj.core.api.Assertions.assertThat;

class VehicleStateUpdaterTest {

    @Test
    void writesStateLocationSafetyAndLastEventFromTelemetrySnapshot() {
        InMemoryVehicleStateRepository repository = new InMemoryVehicleStateRepository();
        VehicleStateUpdater updater = new VehicleStateUpdater(repository);

        updater.update(envelope()
                .addField("speed_kmh", "DOUBLE", "80.5", "km/h")
                .addField("longitude", "DOUBLE", "113.12", "deg")
                .addField("latitude", "DOUBLE", "23.45", "deg")
                .addField("hydrogen_leak_detected", "BOOLEAN", "true", "")
                .addField("hydrogen_leak_level", "STRING", "CRITICAL", "")
                .build());

        assertThat(repository.state).contains("\"vin\":\"VIN001\"");
        assertThat(repository.state).contains("\"speed_kmh\"");
        assertThat(repository.location).contains("\"longitude\":\"113.12\"");
        assertThat(repository.location).contains("\"latitude\":\"23.45\"");
        assertThat(repository.safety).contains("\"hydrogen_leak_detected\":\"true\"");
        assertThat(repository.lastEvent).contains("\"eventId\":\"event-1\"");
    }

    @Test
    void doesNotOverwriteLocationOrSafetyWhenFieldsAreMissing() {
        InMemoryVehicleStateRepository repository = new InMemoryVehicleStateRepository();
        repository.location = "{\"longitude\":\"old\"}";
        repository.safety = "{\"hydrogen_leak_detected\":\"old\"}";

        new VehicleStateUpdater(repository).update(envelope()
                .addField("speed_kmh", "DOUBLE", "80.5", "km/h")
                .build());

        assertThat(repository.location).isEqualTo("{\"longitude\":\"old\"}");
        assertThat(repository.safety).isEqualTo("{\"hydrogen_leak_detected\":\"old\"}");
        assertThat(repository.state).contains("\"speed_kmh\"");
    }

    private static EnvelopeBuilder envelope() {
        return new EnvelopeBuilder();
    }

    private static final class EnvelopeBuilder {
        private final TelemetrySnapshot.Builder snapshot = TelemetrySnapshot.newBuilder()
                .setEventType("REALTIME")
                .setRawArchiveUri("archive://raw/event-1.bin");

        EnvelopeBuilder addField(String key, String valueType, String value, String unit) {
            snapshot.addFields(TelemetryField.newBuilder()
                    .setKey(key)
                    .setValueType(valueType)
                    .setValue(value)
                    .setUnit(unit)
                    .setQuality("GOOD")
                    .setSourcePath("test"));
            return this;
        }

        VehicleEnvelope build() {
            return VehicleEnvelope.newBuilder()
                    .setEventId("event-1")
                    .setTraceId("trace-1")
                    .setVin("VIN001")
                    .setSource("GB32960")
                    .setEventTimeMs(1_782_112_400_000L)
                    .setIngestTimeMs(1_782_112_401_000L)
                    .setTelemetrySnapshot(snapshot)
                    .build();
        }
    }
}
