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

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.RuntimeDriverPartitionDebugDto;
import at.procon.eventhub.processing.dto.RuntimeSupportEvidenceNormalizationDebugDto;
import at.procon.eventhub.processing.dto.UnifiedRuntimeDerivedProjectionResultDto;
import at.procon.eventhub.processing.eventprocessing.RuntimeEventProcessingService;
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventPartitioningApiRequest;
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingApiRequest;
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingPartitionResultDto;
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingResultDto;
import at.procon.eventhub.processing.eventprocessing.partition.RuntimeEventPartitioningStrategy;
import at.procon.eventhub.processing.eventprocessing.profile.TachographDriverEsperRuntimeEventProcessingProfile;
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
import at.procon.eventhub.processing.model.UnifiedRuntimeEventBackend;
import at.procon.eventhub.processing.dto.UnifiedRuntimeProcessingApiRequest;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

class RuntimeMixedSourceEvidenceValidationServiceTest {

    @Test
    void validatesAttachedAndNormalizedEvidenceCounts() {
        RuntimeEventProcessingService processingService = Mockito.mock(RuntimeEventProcessingService.class);
        RuntimeMixedSourceEvidenceValidationService service = new RuntimeMixedSourceEvidenceValidationService(processingService);

        UnifiedRuntimeDerivedProjectionResultDto driverResult = new UnifiedRuntimeDerivedProjectionResultDto(
                null,
                2,
                1,
                1,
                3,
                List.of(),
                null,
                List.of("projection note"),
                new RuntimeSupportEvidenceNormalizationDebugDto(3, 1, 2, List.of("normalization note")),
                new RuntimeDriverPartitionDebugDto(
                        "DRIVER:1",
                        2,
                        1,
                        1,
                        1,
                        0,
                        3,
                        List.of(),
                        List.of(),
                        List.of("debug note"),
                        List.of()
                )
        );
        when(processingService.process(any())).thenReturn(new RuntimeEventProcessingResultDto(
                TachographDriverEsperRuntimeEventProcessingProfile.PROFILE_KEY,
                RuntimeEventPartitioningStrategy.DRIVER,
                null,
                3,
                1,
                1,
                List.of(),
                Map.of("DRIVER:1", new RuntimeEventProcessingPartitionResultDto(
                        "DRIVER",
                        "DRIVER:1",
                        "UnifiedRuntimeDerivedProjectionResultDto",
                        driverResult,
                        Map.of()
                )),
                List.of("runtime note"),
                List.of()
        ));

        RuntimeMixedSourceEvidenceValidationResultDto result = service.validate(new RuntimeMixedSourceEvidenceValidationApiRequest(
                new RuntimeEventProcessingApiRequest(
                        TachographDriverEsperRuntimeEventProcessingProfile.PROFILE_KEY,
                        new UnifiedRuntimeProcessingApiRequest(
                                null,
                                List.of(),
                                null,
                                "default",
                                Set.of(UnifiedEventSourceFamily.TACHOGRAPH_FILE_SESSION),
                                UnifiedRuntimeEventBackend.SOURCE_DB,
                                null,
                                "DRIVER:1",
                                Set.of(),
                                false,
                                Set.of(),
                                false,
                                null,
                                null,
                                null,
                                OffsetDateTime.parse("2026-05-01T00:00:00Z"),
                                OffsetDateTime.parse("2026-05-02T00:00:00Z"),
                                true,
                                15,
                                3,
                                720
                        ),
                        new RuntimeEventPartitioningApiRequest(
                                RuntimeEventPartitioningStrategy.DRIVER,
                                null,
                                null,
                                Set.of("DRIVER:1"),
                                null,
                                null,
                                null,
                                true,
                                15,
                                false
                        ),
                        Map.of()
                ),
                Set.of("DRIVER:1"),
                1,
                1,
                true
        ));

        assertThat(result.status()).isEqualTo("PASSED");
        assertThat(result.totalAttachedVehicleEvidenceEventCount()).isEqualTo(1);
        assertThat(result.totalNormalizedSupportEvidenceEventCount()).isEqualTo(1);
        assertThat(result.partitions().get("DRIVER:1").partitionDebugPresent()).isTrue();
        assertThat(result.partitions().get("DRIVER:1").normalizedSupportEvidenceEventCount()).isEqualTo(1);

        ArgumentCaptor<RuntimeEventProcessingApiRequest> captor = ArgumentCaptor.forClass(RuntimeEventProcessingApiRequest.class);
        verify(processingService).process(captor.capture());
        assertThat(captor.getValue().partitioning().includeDebugOrDefault()).isTrue();
        assertThat(captor.getValue().parameters()).containsEntry("includePartitionDebug", true);
    }
}
