package at.procon.eventhub.processing.eventprocessing.module;

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

import at.procon.eventhub.dto.DriverRefDto;
import at.procon.eventhub.dto.EventDetailsDto;
import at.procon.eventhub.dto.EventDomain;
import at.procon.eventhub.dto.EventHubEventDto;
import at.procon.eventhub.dto.EventHubPackageRequest;
import at.procon.eventhub.dto.EventLifecycle;
import at.procon.eventhub.dto.EventSourceDto;
import at.procon.eventhub.dto.EventType;
import at.procon.eventhub.dto.ImportScopeDto;
import at.procon.eventhub.dto.VehicleRefDto;
import at.procon.eventhub.dto.VehicleRegistrationRefDto;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVehicleUsageInterval;
import at.procon.eventhub.processing.dto.UnifiedRuntimeProcessingApiRequest;
import at.procon.eventhub.processing.eventprocessing.plan.RuntimeProcessingExecutionApiRequest;
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.Test;

class DriverVehicleUsageIntervalsModuleTest {

    @Test
    void pairsVehicleUsagePointsWhenCardStatusDiffersAcrossLifecycleEvents() {
        DriverVehicleUsageIntervalsModule module = new DriverVehicleUsageIntervalsModule();
        RuntimeProcessingModuleContext context = new RuntimeProcessingModuleContext(
                new RuntimeProcessingExecutionApiRequest(
                        "driver-working-time-v1",
                        runtimeScope(),
                        null,
                        List.of(),
                        Map.of()
                ),
                List.of(
                        vehicleUsageEvent(
                                "CVU-1",
                                EventType.CARD_INSERTED,
                                EventLifecycle.INSERT,
                                "2026-05-01T07:50:00Z",
                                "2026-05-01T07:50:00Z",
                                "2026-05-01T10:10:00Z",
                                100_000L,
                                "INSERTED"
                        ),
                        vehicleUsageEvent(
                                "CVU-99",
                                EventType.CARD_WITHDRAWN,
                                EventLifecycle.WITHDRAW,
                                "2026-05-01T10:10:00Z",
                                "2026-05-01T07:50:00Z",
                                "2026-05-01T10:10:00Z",
                                140_000L,
                                "NOT_INSERTED"
                        )
                ),
                Map.of(),
                Map.of()
        );

        RuntimeProcessingModuleResult result = module.execute(context);

        assertThat(result.status()).isEqualTo(RuntimeProcessingModuleStatus.SUCCESS);
        @SuppressWarnings("unchecked")
        List<DriverWorkingTimeVehicleUsageInterval> intervals =
                (List<DriverWorkingTimeVehicleUsageInterval>) result.output();
        assertThat(intervals).hasSize(1);
        assertThat(intervals.get(0).intervalId()).isEqualTo("CVU-1");
        assertThat(intervals.get(0).startedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T07:50:00Z"));
        assertThat(intervals.get(0).endedAt()).isEqualTo(OffsetDateTime.parse("2026-05-01T10:10:00Z"));
    }

    private UnifiedRuntimeProcessingApiRequest runtimeScope() {
        return new UnifiedRuntimeProcessingApiRequest(
                UUID.randomUUID(),
                List.of(),
                null,
                "default",
                Set.of(UnifiedEventSourceFamily.TACHOGRAPH_FILE_SESSION),
                null,
                null,
                "DRIVER:42",
                Set.of(),
                false,
                Set.of(),
                false,
                null,
                null,
                null,
                OffsetDateTime.parse("2026-05-01T00:00:00Z"),
                OffsetDateTime.parse("2026-05-02T00:00:00Z"),
                true,
                0,
                null,
                null,
                null,
                false,
                false
        );
    }

    private EventHubEventDto vehicleUsageEvent(
            String intervalId,
            EventType eventType,
            EventLifecycle lifecycle,
            String occurredAt,
            String startedAt,
            String endedAt,
            long odometerM,
            String cardStatus
    ) {
        ObjectNode raw = JsonNodeFactory.instance.objectNode();
        raw.put("intervalId", intervalId);
        raw.put("driverKey", "DRIVER:42");
        raw.put("startedAt", startedAt);
        raw.put("endedAt", endedAt);
        raw.put("registrationKey", "12:REG-1");
        raw.put("vehicleKey", "VIN-1");
        raw.put("sourceKind", "DRIVER_CARD");
        raw.putArray("sourceRowIds").add("row-" + intervalId);
        ObjectNode payload = JsonNodeFactory.instance.objectNode();
        payload.set("raw", raw);
        ObjectNode attributes = JsonNodeFactory.instance.objectNode();
        attributes.put("cardStatus", cardStatus);
        OffsetDateTime occurred = OffsetDateTime.parse(occurredAt);
        return new EventHubEventDto(
                UUID.randomUUID(),
                intervalId + ":" + eventType.name(),
                new DriverRefDto("DRIVER:42", null),
                new VehicleRefDto("VEH-1", "VIN-1", "VR-1", new VehicleRegistrationRefDto("12", 12, "REG-1")),
                occurred,
                null,
                occurred,
                EventDomain.DRIVER_CARD,
                eventType,
                lifecycle,
                odometerM,
                null,
                new EventDetailsDto("DRIVER_CARD", attributes),
                null,
                payload,
                false,
                packageInfo()
        );
    }

    private EventHubPackageRequest packageInfo() {
        EventSourceDto source = new EventSourceDto("TACHOGRAPH", "DRIVER_CARD", "SOURCE", null, null, null);
        return new EventHubPackageRequest(
                "default",
                source,
                null,
                ImportScopeDto.tenantAll(
                        OffsetDateTime.parse("2026-05-01T00:00:00Z"),
                        OffsetDateTime.parse("2026-05-02T00:00:00Z")
                ),
                EventDomain.DRIVER_CARD.name(),
                LocalDate.parse("2026-05-01"),
                source.stableKey() + ":" + EventDomain.DRIVER_CARD.name() + ":2026-05-01"
        );
    }
}
