package com.lingniu.ingest.protocol.jt808.handler;

import com.lingniu.ingest.api.ProtocolId;
import com.lingniu.ingest.api.event.VehicleEvent;
import com.lingniu.ingest.api.pipeline.IngestContext;
import com.lingniu.ingest.api.pipeline.RawFrame;
import com.lingniu.ingest.core.dispatcher.AnnotationHandlerBeanPostProcessor;
import com.lingniu.ingest.core.dispatcher.HandlerInvoker;
import com.lingniu.ingest.core.dispatcher.HandlerRegistry;
import com.lingniu.ingest.identity.InMemoryVehicleIdentityService;
import com.lingniu.ingest.protocol.jt808.mapper.Jt808EventMapper;
import com.lingniu.ingest.protocol.jt808.model.Jt808Body;
import com.lingniu.ingest.protocol.jt808.model.Jt808Header;
import com.lingniu.ingest.protocol.jt808.model.Jt808Message;
import org.junit.jupiter.api.Test;

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

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

class Jt808LocationHandlerTest {

    @Test
    void unknownRawMessageRoutesToPassthroughHandler() {
        Jt808LocationHandler handler = new Jt808LocationHandler(
                new Jt808EventMapper(new InMemoryVehicleIdentityService()));
        HandlerRegistry registry = new HandlerRegistry();
        new AnnotationHandlerBeanPostProcessor(registry).postProcessAfterInitialization(handler, "jt808Handler");
        Jt808Message message = new Jt808Message(
                new Jt808Header(0x0F01, 3, 0, false,
                        Jt808Header.ProtocolVersion.V2013, "123456789012", 7, 0, 0),
                new Jt808Body.Raw(0x0F01, new byte[]{0x01, 0x02, 0x03}));

        var definitions = registry.resolve(ProtocolId.JT808, 0x0F01, 0);

        assertThat(definitions).hasSize(1);
        var events = new HandlerInvoker().invoke(definitions.getFirst(), new RawFrame(
                ProtocolId.JT808, 0x0F01, 0, message, new byte[]{0x7e},
                Map.of("phone", "123456789012"), Instant.now()), new IngestContext("trace-1"));
        assertThat(events).singleElement().satisfies(event -> {
            assertThat(event).isInstanceOf(VehicleEvent.Passthrough.class);
            VehicleEvent.Passthrough passthrough = (VehicleEvent.Passthrough) event;
            assertThat(passthrough.passthroughType()).isEqualTo(0x0F01);
            assertThat(passthrough.metadata()).containsEntry("rawBody", "true");
        });
    }
}
