package at.procon.eventhub;

import at.procon.eventhub.dto.CardSlot;
import at.procon.eventhub.dto.DriverCardRefDto;
import at.procon.eventhub.dto.DriverRefDto;
import at.procon.eventhub.dto.EventDomain;
import at.procon.eventhub.dto.EventLifecycle;
import at.procon.eventhub.dto.EventType;
import at.procon.eventhub.dto.VehicleRefDto;
import at.procon.eventhub.dto.VehicleRegistrationRefDto;
import at.procon.eventhub.service.EventDetailsFactory;
import at.procon.eventhub.yellowfox.dto.YellowFoxD8BookingDto;
import at.procon.eventhub.yellowfox.service.YellowFoxD8BookingEventMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.OffsetDateTime;
import org.junit.jupiter.api.Test;

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

class YellowFoxD8BookingEventMapperTest {

    private final YellowFoxD8BookingEventMapper mapper = new YellowFoxD8BookingEventMapper(
            new EventDetailsFactory(new ObjectMapper())
    );

    @Test
    void mapsYellowFoxDriverSlotActivityAsStartWithSlotDetails() {
        var source = booking(2, 3, 1);

        var result = mapper.map(source);

        assertThat(result.eventDomain()).isEqualTo(EventDomain.DRIVER_ACTIVITY);
        assertThat(result.eventType()).isEqualTo(EventType.DRIVE);
        assertThat(result.lifecycle()).isEqualTo(EventLifecycle.START);
        assertThat(result.externalSourceEventId()).startsWith("D8_BOOKING:event-1:");
        assertThat(result.eventDetails().type()).isEqualTo("DRIVER_ACTIVITY");
        assertThat(result.eventDetails().attributes().get("slot").asText()).isEqualTo(CardSlot.DRIVER.name());
        assertThat(result.eventDetails().attributes().get("slotNumber").asInt()).isEqualTo(1);
        assertThat(result.eventDetails().attributes().get("yellowFoxStateMeaning").asText()).isEqualTo("STEERING_TIME");
        assertThat(result.eventDetails().attributes().get("ignitionState").asInt()).isEqualTo(1);
    }

    @Test
    void mapsYellowFoxCoDriverSlotActivityAsStartWithSlotDetails() {
        var result = mapper.map(booking(3, 2, 0));

        assertThat(result.eventDomain()).isEqualTo(EventDomain.DRIVER_ACTIVITY);
        assertThat(result.eventType()).isEqualTo(EventType.WORK);
        assertThat(result.lifecycle()).isEqualTo(EventLifecycle.START);
        assertThat(result.eventDetails().attributes().get("slot").asText()).isEqualTo(CardSlot.CO_DRIVER.name());
        assertThat(result.eventDetails().attributes().get("slotNumber").asInt()).isEqualTo(2);
    }

    @Test
    void mapsCardInsertedUsingSameTachographDomainTypeAndLifecycle() {
        var result = mapper.map(booking(0, 1, 1));

        assertThat(result.eventDomain()).isEqualTo(EventDomain.DRIVER_CARD);
        assertThat(result.eventType()).isEqualTo(EventType.CARD_INSERTED);
        assertThat(result.lifecycle()).isEqualTo(EventLifecycle.INSERT);
        assertThat(result.eventDetails().attributes().get("slot").asText()).isEqualTo(CardSlot.DRIVER.name());
    }

    @Test
    void mapsIgnitionTransitionOnlyWhenDetectorRequestsIt() {
        var result = mapper.mapIgnitionTransition(booking(2, 3, 1), 0);

        assertThat(result.eventDomain()).isEqualTo(EventDomain.IGNITION);
        assertThat(result.eventType()).isEqualTo(EventType.IGNITION_ON);
        assertThat(result.lifecycle()).isEqualTo(EventLifecycle.ON);
        assertThat(result.externalSourceEventId()).contains("D8_IGNITION:event-1:");
        assertThat(result.eventDetails().attributes().get("previousIgnitionState").asInt()).isEqualTo(0);
        assertThat(result.eventDetails().attributes().get("ignitionMeaning").asText()).isEqualTo("ON");
    }

    private YellowFoxD8BookingDto booking(int eventType, int state, int ignition) {
        return new YellowFoxD8BookingDto(
                "tenant-1",
                "yellowfox-tenant-7",
                "tenant-yellowfox-7",
                "7",
                "Fleet 7",
                "event-1",
                "key-1",
                ignition,
                null,
                eventType,
                state,
                OffsetDateTime.parse("2026-04-29T08:15:00+02:00"),
                null,
                new DriverRefDto("driver-source-100", new DriverCardRefDto("AT", "D123456789")),
                new VehicleRefDto("vehicle-source-200", "WDB9634031L123456", new VehicleRegistrationRefDto("AT", "W-12345")),
                null,
                null,
                null,
                null
        );
    }
}
