package at.procon.eventhub.processing.service;

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

import at.procon.eventhub.dto.EventHubEventDto;
import at.procon.eventhub.processing.model.UnifiedDiscoveredVehicleRef;
import at.procon.eventhub.processing.model.UnifiedDriverEventsRequest;
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
import at.procon.eventhub.processing.model.UnifiedRuntimeEventBackend;
import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest;
import at.procon.eventhub.processing.model.UnifiedVehicleEventsRequest;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;

class EventHubRuntimeEventLoaderTest {

    @Test
    void supportsOnlyEventHubBackendForTachographAndYellowFox() {
        EventHubRuntimeEventLoader loader = new EventHubRuntimeEventLoader(
                new UnifiedDriverEventSourceService(List.of(new CapturingDriverSource())),
                new UnifiedVehicleEventSourceService(List.of(new CapturingVehicleSource()))
        );

        UnifiedRuntimeProcessingRequest eventHubRequest = UnifiedRuntimeProcessingRequest.forDriverFromEventHub(
                "default",
                Set.of(UnifiedEventSourceFamily.TACHOGRAPH_DB),
                "DRIVER:42",
                null,
                null,
                OffsetDateTime.parse("2026-05-01T00:00:00Z"),
                OffsetDateTime.parse("2026-05-02T00:00:00Z"),
                true,
                15
        );
        UnifiedRuntimeProcessingRequest sourceDbRequest = UnifiedRuntimeProcessingRequest.forDriver(
                "default",
                Set.of(UnifiedEventSourceFamily.TACHOGRAPH_DB),
                "DRIVER:42",
                null,
                null,
                OffsetDateTime.parse("2026-05-01T00:00:00Z"),
                OffsetDateTime.parse("2026-05-02T00:00:00Z")
        );

        assertThat(loader.supports(eventHubRequest, UnifiedEventSourceFamily.TACHOGRAPH_DB)).isTrue();
        assertThat(loader.supports(eventHubRequest, UnifiedEventSourceFamily.YELLOWFOX_DB)).isTrue();
        assertThat(loader.supports(sourceDbRequest, UnifiedEventSourceFamily.TACHOGRAPH_DB)).isFalse();
        assertThat(loader.supports(eventHubRequest, UnifiedEventSourceFamily.TACHOGRAPH_FILE_SESSION)).isFalse();
    }

    @Test
    void buildsDriverRequestsForLocalEventHubSources() {
        CapturingDriverSource driverSource = new CapturingDriverSource();
        EventHubRuntimeEventLoader loader = new EventHubRuntimeEventLoader(
                new UnifiedDriverEventSourceService(List.of(driverSource)),
                new UnifiedVehicleEventSourceService(List.of(new CapturingVehicleSource()))
        );
        UnifiedRuntimeProcessingRequest request = UnifiedRuntimeProcessingRequest.forDriverFromEventHub(
                "default",
                Set.of(UnifiedEventSourceFamily.TACHOGRAPH_DB, UnifiedEventSourceFamily.YELLOWFOX_DB),
                "DRIVER:42",
                "AT",
                "123",
                OffsetDateTime.parse("2026-05-01T00:00:00Z"),
                OffsetDateTime.parse("2026-05-02T00:00:00Z"),
                true,
                15
        );

        loader.loadDriverEvents(request, UnifiedEventSourceFamily.TACHOGRAPH_DB);
        loader.loadDriverEvents(request, UnifiedEventSourceFamily.YELLOWFOX_DB);

        assertThat(driverSource.requests).hasSize(2);
        assertThat(driverSource.requests).extracting(UnifiedDriverEventsRequest::sourceFamily)
                .containsExactly(UnifiedEventSourceFamily.TACHOGRAPH_DB, UnifiedEventSourceFamily.YELLOWFOX_DB);
        assertThat(driverSource.requests).allSatisfy(driverRequest -> {
            assertThat(driverRequest.tenantKey()).isEqualTo("default");
            assertThat(driverRequest.driverSourceEntityId()).isEqualTo("DRIVER:42");
            assertThat(driverRequest.driverCardNation()).isEqualTo("AT");
            assertThat(driverRequest.driverCardNumber()).isEqualTo("123");
            assertThat(driverRequest.occurredFrom()).isEqualTo(OffsetDateTime.parse("2026-05-01T00:00:00Z"));
            assertThat(driverRequest.occurredTo()).isEqualTo(OffsetDateTime.parse("2026-05-02T00:00:00Z"));
        });
    }

    @Test
    void buildsVehicleRequestsForLocalEventHubSourcesWithPadding() {
        CapturingVehicleSource vehicleSource = new CapturingVehicleSource();
        EventHubRuntimeEventLoader loader = new EventHubRuntimeEventLoader(
                new UnifiedDriverEventSourceService(List.of(new CapturingDriverSource())),
                new UnifiedVehicleEventSourceService(List.of(vehicleSource))
        );
        UnifiedRuntimeProcessingRequest request = UnifiedRuntimeProcessingRequest.forDriverFromEventHub(
                "default",
                Set.of(UnifiedEventSourceFamily.TACHOGRAPH_DB, UnifiedEventSourceFamily.YELLOWFOX_DB),
                "DRIVER:42",
                null,
                null,
                OffsetDateTime.parse("2026-05-01T00:00:00Z"),
                OffsetDateTime.parse("2026-05-02T00:00:00Z"),
                true,
                15
        );
        UnifiedDiscoveredVehicleRef vehicleRef = new UnifiedDiscoveredVehicleRef("VEH-1", "VIN-1", "AT", "W-1");

        loader.loadVehicleEvents(request, UnifiedEventSourceFamily.TACHOGRAPH_DB, vehicleRef);
        loader.loadVehicleEvents(request, UnifiedEventSourceFamily.YELLOWFOX_DB, vehicleRef);

        assertThat(vehicleSource.requests).hasSize(2);
        assertThat(vehicleSource.requests).extracting(UnifiedVehicleEventsRequest::sourceFamily)
                .containsExactly(UnifiedEventSourceFamily.TACHOGRAPH_DB, UnifiedEventSourceFamily.YELLOWFOX_DB);
        assertThat(vehicleSource.requests).allSatisfy(vehicleRequest -> {
            assertThat(vehicleRequest.tenantKey()).isEqualTo("default");
            assertThat(vehicleRequest.vehicleSourceEntityId()).isEqualTo("VEH-1");
            assertThat(vehicleRequest.vin()).isEqualTo("VIN-1");
            assertThat(vehicleRequest.registrationNation()).isEqualTo("AT");
            assertThat(vehicleRequest.registrationNumber()).isEqualTo("W-1");
            assertThat(vehicleRequest.occurredFrom()).isEqualTo(OffsetDateTime.parse("2026-04-30T23:45:00Z"));
            assertThat(vehicleRequest.occurredTo()).isEqualTo(OffsetDateTime.parse("2026-05-02T00:15:00Z"));
        });
    }

    private static final class CapturingDriverSource implements UnifiedDriverEventSource {

        private final List<UnifiedDriverEventsRequest> requests = new ArrayList<>();

        @Override
        public boolean supports(UnifiedDriverEventsRequest request) {
            return request.sourceFamily() == UnifiedEventSourceFamily.TACHOGRAPH_DB
                    || request.sourceFamily() == UnifiedEventSourceFamily.YELLOWFOX_DB;
        }

        @Override
        public List<EventHubEventDto> loadDriverEvents(UnifiedDriverEventsRequest request) {
            requests.add(request);
            return List.of();
        }
    }

    private static final class CapturingVehicleSource implements UnifiedVehicleEventSource {

        private final List<UnifiedVehicleEventsRequest> requests = new ArrayList<>();

        @Override
        public boolean supports(UnifiedVehicleEventsRequest request) {
            return request.sourceFamily() == UnifiedEventSourceFamily.TACHOGRAPH_DB
                    || request.sourceFamily() == UnifiedEventSourceFamily.YELLOWFOX_DB;
        }

        @Override
        public List<EventHubEventDto> loadVehicleEvents(UnifiedVehicleEventsRequest request) {
            requests.add(request);
            return List.of();
        }
    }
}
