package at.procon.eventhub.tachographfilesession.service;

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

import at.procon.eventhub.tachographfilesession.model.DriverExtractionSession;
import at.procon.eventhub.tachographfilesession.model.ExtractedCardActivityInterval;
import at.procon.eventhub.tachographfilesession.model.ExtractedCardVehicleUsageInterval;
import at.procon.eventhub.tachographfilesession.model.ExtractionStats;
import at.procon.eventhub.tachographfilesession.model.ResolvedDriverTimeline;
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingDerivedProjectionBundle;
import at.procon.eventhub.tachographfilesession.model.TachographEsperDrivingInterruptionIntervalEvent;
import at.procon.eventhub.tachographfilesession.model.TachographEsperPotentialHomeOvernightStayIntervalEvent;
import at.procon.eventhub.tachographfilesession.model.TachographEsperVuCardAbsentIntervalEvent;
import at.procon.eventhub.tachographfilesession.model.TachographFileSession;
import at.procon.eventhub.tachographfilesession.model.TachographFileSessionMetadata;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.junit.jupiter.api.Test;

class DriverTimelineReusableProjectionBuilderTest {

    private final DriverTimelineBuilder legacyBuilder = new DriverTimelineBuilder();
    private final DriverTimelineReusableProjectionBuilder reusableBuilder =
            new DriverTimelineReusableProjectionBuilder(legacyBuilder);

    @Test
    void matchesLegacyDrivingDerivedProjectionChain() {
        DriverExtractionSession driver = new DriverExtractionSession(
                "12:123",
                null,
                null,
                List.of(),
                List.of(),
                List.of(
                        new ExtractedCardVehicleUsageInterval(
                                "CVU-1",
                                OffsetDateTime.parse("2026-05-01T08:00:00Z"),
                                OffsetDateTime.parse("2026-05-01T10:00:00Z"),
                                100L,
                                200L,
                                "12:REG-1",
                                "VIN-1",
                                "vu-1"
                        ),
                        new ExtractedCardVehicleUsageInterval(
                                "CVU-2",
                                OffsetDateTime.parse("2026-05-02T00:00:00Z"),
                                OffsetDateTime.parse("2026-05-02T02:00:00Z"),
                                201L,
                                260L,
                                "12:REG-2",
                                "VIN-2",
                                "vu-2"
                        )
                ),
                List.of(
                        new ExtractedCardActivityInterval(
                                "ACT-1",
                                OffsetDateTime.parse("2026-05-01T08:00:00Z"),
                                OffsetDateTime.parse("2026-05-01T10:00:00Z"),
                                "DRIVE",
                                "DRIVER",
                                "INSERTED",
                                "SINGLE",
                                "12:REG-1",
                                "VIN-1",
                                "a"
                        ),
                        new ExtractedCardActivityInterval(
                                "ACT-2",
                                OffsetDateTime.parse("2026-05-02T00:00:00Z"),
                                OffsetDateTime.parse("2026-05-02T00:30:00Z"),
                                "DRIVE",
                                "DRIVER",
                                "INSERTED",
                                "SINGLE",
                                "12:REG-2",
                                "VIN-2",
                                "b"
                        )
                ),
                List.of(),
                List.of()
        );
        TachographFileSession session = new TachographFileSession(
                UUID.randomUUID(),
                new TachographFileSessionMetadata("default", "legalrequirements-drivercard", "sample", "sample.ddd", "a", 2, "42", "b", true, null),
                Map.of(driver.driverKey(), driver),
                new ExtractionStats(1, 2, 2, 1, 1, 0),
                List.of(),
                Instant.now(),
                Instant.now().plus(4, ChronoUnit.HOURS)
        );

        ResolvedDriverTimeline timeline = legacyBuilder.build(session, driver);
        List<TachographEsperDrivingInterruptionIntervalEvent> legacyDrivingInterruptions =
                legacyBuilder.buildEsperDrivingInterruptionIntervalEvents(session.sessionId(), driver.driverKey(), timeline, 3);
        List<TachographEsperDrivingInterruptionIntervalEvent> legacyDailyWeeklyRestCandidates =
                legacyBuilder.buildEsperDailyWeeklyRestCandidateIntervalEvents(legacyDrivingInterruptions, 720);
        List<TachographEsperDrivingInterruptionIntervalEvent> legacyDrivingInterruptionVehicleChanges =
                legacyBuilder.buildEsperDrivingInterruptionVehicleChangeIntervalEvents(legacyDailyWeeklyRestCandidates);
        List<TachographEsperVuCardAbsentIntervalEvent> legacyVuCardAbsentIntervals =
                legacyBuilder.buildEsperVuCardAbsentIntervalEvents(timeline);
        List<TachographEsperPotentialHomeOvernightStayIntervalEvent> legacyPotentialHomeOvernightStays =
                legacyBuilder.buildEsperPotentialHomeOvernightStayIntervalEvents(
                        legacyDrivingInterruptionVehicleChanges,
                        legacyVuCardAbsentIntervals
                );

        TachographEsperDrivingDerivedProjectionBundle reusableBundle =
                reusableBuilder.buildEsperDrivingDerivedProjectionBundle(
                        session.sessionId(),
                        driver.driverKey(),
                        timeline,
                        3,
                        720
                );

        assertThat(reusableBundle.drivingInterruptionIntervals()).containsExactlyElementsOf(legacyDrivingInterruptions);
        assertThat(reusableBundle.dailyWeeklyRestCandidateIntervals()).containsExactlyElementsOf(legacyDailyWeeklyRestCandidates);
        assertThat(reusableBundle.drivingInterruptionVehicleChangeIntervals()).containsExactlyElementsOf(legacyDrivingInterruptionVehicleChanges);
        assertThat(reusableBundle.vuCardAbsentIntervals()).containsExactlyElementsOf(legacyVuCardAbsentIntervals);
        assertThat(reusableBundle.potentialHomeOvernightStayIntervals()).containsExactlyElementsOf(legacyPotentialHomeOvernightStays);
    }
}
