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

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import at.procon.eventhub.processing.dto.UnifiedRuntimeDerivedProjectionResultDto;
import at.procon.eventhub.processing.dto.UnifiedRuntimeProcessingApiRequest;
import at.procon.eventhub.processing.dto.UnifiedRuntimeTachographEsperScopeResultDto;
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventPartitioningApiRequest;
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingApiRequest;
import at.procon.eventhub.processing.eventprocessing.partition.RuntimeEventPartitioningStrategy;
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest;
import at.procon.eventhub.processing.service.UnifiedRuntimeTachographEsperScopeProcessingService;
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;
import org.mockito.ArgumentCaptor;

class TachographDriverEsperRuntimeEventProcessingProfileTest {

    @Test
    void exposesDiscoveryMetadata() {
        TachographDriverEsperRuntimeEventProcessingProfile profile = new TachographDriverEsperRuntimeEventProcessingProfile(
                org.mockito.Mockito.mock(UnifiedRuntimeTachographEsperScopeProcessingService.class)
        );

        assertThat(profile.profileKey()).isEqualTo("tachograph-driver-esper-v1");
        assertThat(profile.displayName()).isEqualTo("Tachograph Driver Esper Processing");
        assertThat(profile.defaultPartitioningStrategy()).isEqualTo(RuntimeEventPartitioningStrategy.DRIVER);
        assertThat(profile.supportedPartitioningStrategies()).containsExactly(RuntimeEventPartitioningStrategy.DRIVER);
        assertThat(profile.optionalParameters()).containsExactlyInAnyOrder("significantDrivingMinutes", "minimumRestPeriodMinutes", "attachVehicleOnlyEvents", "vehicleEvidencePaddingMinutes");
    }

    @Test
    void delegatesToTachographScopeServiceAndMapsPartitionResults() {
        UnifiedRuntimeTachographEsperScopeProcessingService scopeService = org.mockito.Mockito.mock(UnifiedRuntimeTachographEsperScopeProcessingService.class);
        TachographDriverEsperRuntimeEventProcessingProfile profile = new TachographDriverEsperRuntimeEventProcessingProfile(scopeService);

        UUID sessionId = UUID.randomUUID();
        UnifiedRuntimeProcessingApiRequest scope = new UnifiedRuntimeProcessingApiRequest(
                sessionId,
                List.of(),
                null,
                null,
                Set.of(UnifiedEventSourceFamily.TACHOGRAPH_FILE_SESSION),
                null,
                null,
                Set.of(),
                false,
                Set.of(),
                false,
                null,
                null,
                null,
                OffsetDateTime.parse("2026-05-01T00:00:00Z"),
                OffsetDateTime.parse("2026-05-31T23:59:59Z"),
                true,
                15,
                null,
                null
        );
        RuntimeEventProcessingApiRequest request = new RuntimeEventProcessingApiRequest(
                TachographDriverEsperRuntimeEventProcessingProfile.PROFILE_KEY,
                scope,
                new RuntimeEventPartitioningApiRequest(
                        RuntimeEventPartitioningStrategy.DRIVER,
                        Set.of("12:DRIVER-1"),
                        false,
                        Set.of(),
                        false,
                        null,
                        null,
                        null,
                        null
                ),
                Map.of(
                        "significantDrivingMinutes", 5,
                        "minimumRestPeriodMinutes", "600",
                        "vehicleEvidencePaddingMinutes", 20,
                        "attachVehicleOnlyEvents", true
                )
        );

        UnifiedRuntimeProcessingRequest processedRequest = new UnifiedRuntimeProcessingRequest(
                sessionId,
                List.of(sessionId),
                null,
                null,
                Set.of(UnifiedEventSourceFamily.TACHOGRAPH_FILE_SESSION),
                null,
                "12:DRIVER-1",
                Set.of("12:DRIVER-1"),
                false,
                Set.of(),
                false,
                null,
                null,
                null,
                OffsetDateTime.parse("2026-05-01T00:00:00Z"),
                OffsetDateTime.parse("2026-05-31T23:59:59Z"),
                true,
                15
        );
        UnifiedRuntimeDerivedProjectionResultDto driverResult = new UnifiedRuntimeDerivedProjectionResultDto(
                processedRequest,
                2,
                1,
                3,
                5,
                List.of(),
                null,
                List.of("driver processed")
        );
        when(scopeService.processScope(any()))
                .thenReturn(new UnifiedRuntimeTachographEsperScopeResultDto(
                        processedRequest,
                        5,
                        1,
                        1,
                        List.of(),
                        Map.of("12:DRIVER-1", driverResult),
                        List.of("scope processed"),
                        List.of()
                ));

        var result = profile.process(request);

        assertThat(result.profileKey()).isEqualTo(TachographDriverEsperRuntimeEventProcessingProfile.PROFILE_KEY);
        assertThat(result.partitioningStrategy()).isEqualTo(RuntimeEventPartitioningStrategy.DRIVER);
        assertThat(result.partitionResults()).containsOnlyKeys("12:DRIVER-1");
        assertThat(result.partitionResults().get("12:DRIVER-1").partitionType()).isEqualTo("DRIVER");
        assertThat(result.partitionResults().get("12:DRIVER-1").result()).isSameAs(driverResult);

        ArgumentCaptor<UnifiedRuntimeProcessingApiRequest> captor = ArgumentCaptor.forClass(UnifiedRuntimeProcessingApiRequest.class);
        verify(scopeService).processScope(captor.capture());
        UnifiedRuntimeProcessingApiRequest delegated = captor.getValue();
        assertThat(delegated.driverKeys()).containsExactly("12:DRIVER-1");
        assertThat(delegated.significantDrivingMinutes()).isEqualTo(5);
        assertThat(delegated.minimumRestPeriodMinutes()).isEqualTo(600);
        assertThat(delegated.vehicleExpansionPaddingMinutes()).isEqualTo(20);
        assertThat(delegated.expandVehicleEvents()).isTrue();
    }
}
