package at.procon.eventhub.processing.driverworkingtime.service;

import at.procon.eventhub.processing.driverworkingtime.dto.DriverWorkingTimeProcessingResultDto;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeActivityInterval;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeDerivedProjectionBundle;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeDrivingInterruptionInterval;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeGeoEvidenceEvent;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimePotentialInVehicleTripInterval;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeProcessingInput;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeRestCoverageInterval;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeSupportGeoEvent;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVehicleUsageInterval;
import at.procon.eventhub.processing.driverworkingtime.model.DriverWorkingTimeVuCardAbsentInterval;
import at.procon.eventhub.processing.eventprocessing.support.RuntimeSupportEvidenceEvent;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import org.springframework.stereotype.Service;

/**
 * Source-neutral driver working-time processing core.
 *
 * <p>This core consumes canonical driver activity, vehicle-usage, and support-evidence
 * timelines. Tachograph files/databases, YellowFox, and future providers should only
 * contribute normalized EventHub events or reconstructed timelines; they should not own
 * the working-time processing logic.</p>
 */
@Service
public class DriverWorkingTimeProcessingCore {

    private final DriverWorkingTimeDerivedProjectionEngine derivedProjectionEngine;

    public DriverWorkingTimeProcessingCore(
            DriverWorkingTimeDerivedProjectionEngine derivedProjectionEngine
    ) {
        this.derivedProjectionEngine = derivedProjectionEngine;
    }

    public DriverWorkingTimeProcessingResultDto process(DriverWorkingTimeProcessingInput input) {
        Objects.requireNonNull(input, "input must not be null");
        OffsetDateTime loadedFrom = input.loadedFrom();
        OffsetDateTime loadedTo = input.loadedTo();
        String driverKey = input.driverKey();
        OffsetDateTime requestedFrom = input.requestedFrom() == null ? loadedFrom : utc(input.requestedFrom());
        OffsetDateTime requestedTo = input.requestedTo() == null ? loadedTo : utc(input.requestedTo());
        if (requestedFrom != null && requestedTo != null && requestedTo.isBefore(requestedFrom)) {
            throw new IllegalArgumentException("occurredTo must not be before occurredFrom.");
        }

        List<DriverWorkingTimeActivityInterval> activityIntervals = clipActivityIntervals(
                input.activityIntervals(),
                requestedFrom,
                requestedTo
        );
        List<DriverWorkingTimeActivityInterval> drivingIntervals = clipActivityIntervals(
                safeList(input.activityIntervals()).stream()
                        .filter(interval -> Objects.equals("DRIVE", interval.activityType()))
                        .toList(),
                requestedFrom,
                requestedTo
        );

        DriverWorkingTimeDerivedProjectionBundle derivedProjectionBundle = derivedProjectionEngine.build(input);

        List<DriverWorkingTimeDrivingInterruptionInterval> drivingInterruptionIntervals =
                clipDrivingInterruptionIntervals(
                        derivedProjectionBundle.drivingInterruptionIntervals(),
                        requestedFrom,
                        requestedTo
                );
        List<DriverWorkingTimeDrivingInterruptionInterval> dailyWeeklyRestCandidateIntervals =
                clipDrivingInterruptionIntervals(
                        derivedProjectionBundle.dailyWeeklyRestCandidateIntervals(),
                        requestedFrom,
                        requestedTo
                );
        List<DriverWorkingTimeDrivingInterruptionInterval> drivingInterruptionVehicleChangeIntervals =
                clipDrivingInterruptionIntervals(
                        derivedProjectionBundle.drivingInterruptionVehicleChangeIntervals(),
                        requestedFrom,
                        requestedTo
                );
        List<DriverWorkingTimeRestCoverageInterval> dailyWeeklyRestCandidateCoverageIntervals =
                clipRestCoverageIntervals(
                        derivedProjectionBundle.dailyWeeklyRestCandidateCoverageIntervals(),
                        requestedFrom,
                        requestedTo
                );
        List<DriverWorkingTimeRestCoverageInterval> unclassifiedDailyWeeklyRestCandidateCoverageIntervals =
                clipRestCoverageIntervals(
                        derivedProjectionBundle.unclassifiedDailyWeeklyRestCandidateCoverageIntervals(),
                        requestedFrom,
                        requestedTo
                );
        List<DriverWorkingTimeRestCoverageInterval> potentialHomeOvernightStayIntervals =
                clipRestCoverageIntervals(
                        derivedProjectionBundle.potentialHomeOvernightStayIntervals(),
                        requestedFrom,
                        requestedTo
                );
        List<DriverWorkingTimeRestCoverageInterval> potentialInVehicleOvernightStayIntervals =
                clipRestCoverageIntervals(
                        derivedProjectionBundle.potentialInVehicleOvernightStayIntervals(),
                        requestedFrom,
                        requestedTo
                );
        List<DriverWorkingTimePotentialInVehicleTripInterval> potentialInVehicleTripIntervals =
                clipPotentialInVehicleTripIntervals(
                        derivedProjectionBundle.potentialInVehicleTripIntervals(),
                        potentialInVehicleOvernightStayIntervals,
                        requestedFrom,
                        requestedTo
                );
        List<DriverWorkingTimeVehicleUsageInterval> vehicleUsageIntervals = clipVehicleUsageIntervals(
                input.vehicleUsageIntervals(),
                requestedFrom,
                requestedTo
        );
        List<DriverWorkingTimeVuCardAbsentInterval> vuCardAbsentIntervals = clipVuCardAbsentIntervals(
                derivedProjectionBundle.vuCardAbsentIntervals(),
                requestedFrom,
                requestedTo
        );
        List<DriverWorkingTimeSupportGeoEvent> supportGeoEvents = clipSupportGeoEvents(
                buildSupportGeoEvents(input.supportEvidenceEvents()),
                driverKey,
                requestedFrom,
                requestedTo
        );

        return new DriverWorkingTimeProcessingResultDto(
                input.sessionId(),
                driverKey,
                input.sourceKind(),
                loadedFrom,
                loadedTo,
                requestedFrom,
                requestedTo,
                activityIntervals.size(),
                drivingIntervals.size(),
                drivingInterruptionIntervals.size(),
                drivingInterruptionVehicleChangeIntervals.size(),
                dailyWeeklyRestCandidateIntervals.size(),
                dailyWeeklyRestCandidateCoverageIntervals.size(),
                unclassifiedDailyWeeklyRestCandidateCoverageIntervals.size(),
                potentialHomeOvernightStayIntervals.size(),
                potentialInVehicleOvernightStayIntervals.size(),
                potentialInVehicleTripIntervals.size(),
                vehicleUsageIntervals.size(),
                vuCardAbsentIntervals.size(),
                supportGeoEvents.size(),
                activityIntervals,
                drivingIntervals,
                drivingInterruptionIntervals,
                drivingInterruptionVehicleChangeIntervals,
                dailyWeeklyRestCandidateIntervals,
                dailyWeeklyRestCandidateCoverageIntervals,
                unclassifiedDailyWeeklyRestCandidateCoverageIntervals,
                potentialHomeOvernightStayIntervals,
                potentialInVehicleOvernightStayIntervals,
                potentialInVehicleTripIntervals,
                vehicleUsageIntervals,
                vuCardAbsentIntervals,
                supportGeoEvents,
                combinedNotes(input.notes())
        );
    }

    public DriverWorkingTimeProcessingResultDto processDriverWorkingTime(DriverWorkingTimeProcessingInput input) {
        return process(input);
    }

    private List<DriverWorkingTimeActivityInterval> clipActivityIntervals(
            List<DriverWorkingTimeActivityInterval> intervals,
            OffsetDateTime requestedFrom,
            OffsetDateTime requestedTo
    ) {
        if (requestedFrom == null || requestedTo == null) {
            return List.of();
        }
        return safeList(intervals).stream()
                .filter(interval -> interval.startedAt() != null && interval.endedAt() != null)
                .map(interval -> {
                    OffsetDateTime start = max(interval.startedAt(), requestedFrom);
                    OffsetDateTime end = min(interval.endedAt(), requestedTo);
                    if (!end.isAfter(start)) {
                        return null;
                    }
                    boolean clipped = interval.clippedToRequestedPeriod()
                            || !start.equals(interval.startedAt())
                            || !end.equals(interval.endedAt());
                    return new DriverWorkingTimeActivityInterval(
                            interval.sessionId(),
                            interval.driverKey(),
                            interval.intervalId(),
                            interval.activityType(),
                            interval.cardSlot(),
                            interval.cardStatus(),
                            interval.drivingStatus(),
                            interval.registrationKey(),
                            interval.vehicleKey(),
                            interval.sourceKind(),
                            interval.firstSourceIntervalId(),
                            interval.lastSourceIntervalId(),
                            start,
                            end,
                            start.toEpochSecond(),
                            end.toEpochSecond(),
                            Duration.between(start, end).getSeconds(),
                            interval.sourceIntervalIds(),
                            interval.synthetic(),
                            clipped,
                            interval.level()
                    );
                })
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(DriverWorkingTimeActivityInterval::startedAt)
                        .thenComparing(DriverWorkingTimeActivityInterval::endedAt)
                        .thenComparing(DriverWorkingTimeActivityInterval::activityType, Comparator.nullsLast(String::compareTo)))
                .toList();
    }

    private List<DriverWorkingTimeVehicleUsageInterval> clipVehicleUsageIntervals(
            List<DriverWorkingTimeVehicleUsageInterval> intervals,
            OffsetDateTime requestedFrom,
            OffsetDateTime requestedTo
    ) {
        if (requestedFrom == null || requestedTo == null) {
            return List.of();
        }
        return safeList(intervals).stream()
                .filter(interval -> interval.startedAt() != null && interval.endedAt() != null)
                .map(interval -> {
                    OffsetDateTime start = max(interval.startedAt(), requestedFrom);
                    OffsetDateTime end = min(interval.endedAt(), requestedTo);
                    if (!end.isAfter(start)) {
                        return null;
                    }
                    boolean startClipped = !start.equals(interval.startedAt());
                    boolean endClipped = !end.equals(interval.endedAt());
                    return new DriverWorkingTimeVehicleUsageInterval(
                            interval.sessionId(),
                            interval.driverKey(),
                            interval.intervalId(),
                            interval.firstSourceIntervalId(),
                            interval.lastSourceIntervalId(),
                            start,
                            end,
                            start.toEpochSecond(),
                            end.toEpochSecond(),
                            Duration.between(start, end).getSeconds(),
                            startClipped ? null : interval.odometerBeginKm(),
                            endClipped ? null : interval.odometerEndKm(),
                            interval.registrationKey(),
                            interval.vehicleKey(),
                            interval.sourceKind(),
                            interval.sourceIntervalIds()
                    );
                })
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(DriverWorkingTimeVehicleUsageInterval::startedAt)
                        .thenComparing(DriverWorkingTimeVehicleUsageInterval::endedAt)
                        .thenComparing(DriverWorkingTimeVehicleUsageInterval::intervalId, Comparator.nullsLast(String::compareTo)))
                .toList();
    }

    private List<DriverWorkingTimeSupportGeoEvent> buildSupportGeoEvents(
            List<RuntimeSupportEvidenceEvent> supportEvents
    ) {
        return safeList(supportEvents).stream()
                .filter(event -> event.occurredAt() != null)
                .map(event -> new DriverWorkingTimeSupportGeoEvent(
                        event.eventId(),
                        event.driverKey(),
                        utc(event.occurredAt()),
                        event.eventDomain(),
                        event.eventType(),
                        event.lifecycle(),
                        event.registrationKey(),
                        event.vehicleKey(),
                        event.countryCode(),
                        event.regionCode(),
                        event.countryFrom(),
                        event.countryTo(),
                        event.operation(),
                        event.latitude(),
                        event.longitude(),
                        event.odometerKm(),
                        rawRecordPath(event)
                ))
                .sorted(Comparator.comparing(DriverWorkingTimeSupportGeoEvent::occurredAt)
                        .thenComparing(DriverWorkingTimeSupportGeoEvent::eventId, Comparator.nullsLast(String::compareTo)))
                .toList();
    }

    private String rawRecordPath(RuntimeSupportEvidenceEvent event) {
        if (event == null) {
            return null;
        }
        Object value = event.rawAttributes().get("rawRecordPath");
        return value == null ? null : value.toString();
    }

    private List<DriverWorkingTimeSupportGeoEvent> clipSupportGeoEvents(
            List<DriverWorkingTimeSupportGeoEvent> supportEvents,
            String driverKey,
            OffsetDateTime requestedFrom,
            OffsetDateTime requestedTo
    ) {
        if (supportEvents == null || supportEvents.isEmpty() || requestedFrom == null || requestedTo == null) {
            return List.of();
        }
        return supportEvents.stream()
                .filter(event -> event.driverKey() == null || Objects.equals(driverKey, event.driverKey()))
                .filter(event -> event.occurredAt() != null)
                .filter(event -> event.latitude() != null && event.longitude() != null)
                .filter(event -> !event.occurredAt().isBefore(requestedFrom) && !event.occurredAt().isAfter(requestedTo))
                .sorted(Comparator.comparing(DriverWorkingTimeSupportGeoEvent::occurredAt)
                        .thenComparing(DriverWorkingTimeSupportGeoEvent::eventDomain, Comparator.nullsLast(String::compareTo))
                        .thenComparing(DriverWorkingTimeSupportGeoEvent::eventId, Comparator.nullsLast(String::compareTo)))
                .toList();
    }

    private List<DriverWorkingTimeDrivingInterruptionInterval> clipDrivingInterruptionIntervals(
            List<DriverWorkingTimeDrivingInterruptionInterval> intervals,
            OffsetDateTime requestedFrom,
            OffsetDateTime requestedTo
    ) {
        if (requestedFrom == null || requestedTo == null) {
            return List.of();
        }
        return safeList(intervals).stream()
                .map(interval -> {
                    OffsetDateTime start = max(interval.startedAt(), requestedFrom);
                    OffsetDateTime end = min(interval.endedAt(), requestedTo);
                    if (!end.isAfter(start)) {
                        return null;
                    }
                    return new DriverWorkingTimeDrivingInterruptionInterval(
                            interval.sessionId(),
                            interval.driverKey(),
                            start,
                            end,
                            Duration.between(start, end).getSeconds(),
                            interval.previousDrivingSourceIntervalId(),
                            interval.nextDrivingSourceIntervalId(),
                            interval.previousRegistrationKey(),
                            interval.nextRegistrationKey(),
                            interval.previousVehicleKey(),
                            interval.nextVehicleKey()
                    );
                })
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(DriverWorkingTimeDrivingInterruptionInterval::startedAt)
                        .thenComparing(DriverWorkingTimeDrivingInterruptionInterval::endedAt))
                .toList();
    }

    private List<DriverWorkingTimeVuCardAbsentInterval> clipVuCardAbsentIntervals(
            List<DriverWorkingTimeVuCardAbsentInterval> intervals,
            OffsetDateTime requestedFrom,
            OffsetDateTime requestedTo
    ) {
        if (requestedFrom == null || requestedTo == null) {
            return List.of();
        }
        return safeList(intervals).stream()
                .map(interval -> {
                    OffsetDateTime start = max(interval.startedAt(), requestedFrom);
                    OffsetDateTime end = min(interval.endedAt(), requestedTo);
                    if (!end.isAfter(start)) {
                        return null;
                    }
                    return new DriverWorkingTimeVuCardAbsentInterval(
                            interval.sessionId(),
                            interval.driverKey(),
                            start,
                            end,
                            Duration.between(start, end).getSeconds(),
                            interval.previousUsageIntervalId(),
                            interval.nextUsageIntervalId(),
                            interval.previousRegistrationKey(),
                            interval.nextRegistrationKey(),
                            interval.previousVehicleKey(),
                            interval.nextVehicleKey()
                    );
                })
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(DriverWorkingTimeVuCardAbsentInterval::startedAt)
                        .thenComparing(DriverWorkingTimeVuCardAbsentInterval::endedAt))
                .toList();
    }

    private List<DriverWorkingTimeRestCoverageInterval> clipRestCoverageIntervals(
            List<DriverWorkingTimeRestCoverageInterval> intervals,
            OffsetDateTime requestedFrom,
            OffsetDateTime requestedTo
    ) {
        if (requestedFrom == null || requestedTo == null) {
            return List.of();
        }
        return safeList(intervals).stream()
                .map(interval -> {
                    OffsetDateTime start = max(interval.startedAt(), requestedFrom);
                    OffsetDateTime end = min(interval.endedAt(), requestedTo);
                    if (!end.isAfter(start)) {
                        return null;
                    }
                    long durationSeconds = Duration.between(start, end).getSeconds();
                    boolean beginBoundaryChanged = !start.equals(interval.startedAt());
                    boolean endBoundaryChanged = !end.equals(interval.endedAt());
                    return new DriverWorkingTimeRestCoverageInterval(
                            interval.sessionId(),
                            interval.driverKey(),
                            start,
                            end,
                            durationSeconds,
                            interval.cardAbsentDurationSeconds(),
                            interval.cardAbsentCoveragePercent(),
                            interval.previousDrivingSourceIntervalId(),
                            interval.nextDrivingSourceIntervalId(),
                            interval.previousRegistrationKey(),
                            interval.nextRegistrationKey(),
                            interval.previousVehicleKey(),
                            interval.nextVehicleKey(),
                            beginBoundaryChanged ? null : interval.beginBoundaryOdometerKm(),
                            endBoundaryChanged ? null : interval.endBoundaryOdometerKm(),
                            beginBoundaryChanged ? null : interval.beginGeoEventId(),
                            beginBoundaryChanged ? null : interval.beginGeoEventDomain(),
                            beginBoundaryChanged ? null : interval.beginGeoOccurredAt(),
                            beginBoundaryChanged ? null : interval.beginLatitude(),
                            beginBoundaryChanged ? null : interval.beginLongitude(),
                            beginBoundaryChanged ? null : interval.beginGeoDistanceSeconds(),
                            beginBoundaryChanged ? null : interval.beginGeoOdometerKm(),
                            endBoundaryChanged ? null : interval.endGeoEventId(),
                            endBoundaryChanged ? null : interval.endGeoEventDomain(),
                            endBoundaryChanged ? null : interval.endGeoOccurredAt(),
                            endBoundaryChanged ? null : interval.endLatitude(),
                            endBoundaryChanged ? null : interval.endLongitude(),
                            endBoundaryChanged ? null : interval.endGeoDistanceSeconds(),
                            endBoundaryChanged ? null : interval.endGeoOdometerKm(),
                            beginBoundaryChanged || endBoundaryChanged ? null : interval.geoEvidenceMovementMeters(),
                            beginBoundaryChanged || endBoundaryChanged ? "UNKNOWN" : interval.geoEvidenceMovementCategory(),
                            beginBoundaryChanged
                                    ? null
                                    : geoEvidenceEvent(
                                            interval.beginGeoEventId(),
                                            interval.beginGeoEventDomain(),
                                            interval.beginGeoOccurredAt(),
                                            interval.beginLatitude(),
                                            interval.beginLongitude(),
                                            interval.beginGeoDistanceSeconds(),
                                            interval.beginGeoOdometerKm()
                                    ),
                            endBoundaryChanged
                                    ? null
                                    : geoEvidenceEvent(
                                            interval.endGeoEventId(),
                                            interval.endGeoEventDomain(),
                                            interval.endGeoOccurredAt(),
                                            interval.endLatitude(),
                                            interval.endLongitude(),
                                            interval.endGeoDistanceSeconds(),
                                            interval.endGeoOdometerKm()
                                    )
                    );
                })
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(DriverWorkingTimeRestCoverageInterval::startedAt)
                        .thenComparing(DriverWorkingTimeRestCoverageInterval::endedAt))
                .toList();
    }

    private List<DriverWorkingTimePotentialInVehicleTripInterval> clipPotentialInVehicleTripIntervals(
            List<DriverWorkingTimePotentialInVehicleTripInterval> intervals,
            List<DriverWorkingTimeRestCoverageInterval> potentialInVehicleOvernightStayIntervals,
            OffsetDateTime requestedFrom,
            OffsetDateTime requestedTo
    ) {
        if (requestedFrom == null || requestedTo == null) {
            return List.of();
        }
        if (intervals == null || intervals.isEmpty()
                || potentialInVehicleOvernightStayIntervals == null || potentialInVehicleOvernightStayIntervals.isEmpty()) {
            return List.of();
        }
        return intervals.stream()
                .map(interval -> {
                    OffsetDateTime start = max(interval.startedAt(), requestedFrom);
                    OffsetDateTime end = min(interval.endedAt(), requestedTo);
                    if (!end.isAfter(start)) {
                        return null;
                    }
                    List<DriverWorkingTimeRestCoverageInterval> containedIntervals =
                            potentialInVehicleOvernightStayIntervals.stream()
                                    .filter(candidate -> tripContainsPotentialInterval(
                                            interval.driverKey(),
                                            interval.registrationKey(),
                                            interval.vehicleKey(),
                                            start,
                                            end,
                                            candidate
                                    ))
                                    .sorted(Comparator.comparing(DriverWorkingTimeRestCoverageInterval::startedAt)
                                            .thenComparing(DriverWorkingTimeRestCoverageInterval::endedAt))
                                    .toList();
                    if (containedIntervals.isEmpty()) {
                        return null;
                    }
                    DriverWorkingTimeRestCoverageInterval first = containedIntervals.getFirst();
                    DriverWorkingTimeRestCoverageInterval last = containedIntervals.getLast();
                    return new DriverWorkingTimePotentialInVehicleTripInterval(
                            interval.sessionId(),
                            interval.driverKey(),
                            start,
                            end,
                            Duration.between(start, end).getSeconds(),
                            interval.registrationKey(),
                            interval.vehicleKey(),
                            containedIntervals.size(),
                            containedIntervals.stream()
                                    .mapToLong(DriverWorkingTimeRestCoverageInterval::durationSeconds)
                                    .sum(),
                            containedIntervals.stream()
                                    .mapToLong(DriverWorkingTimeRestCoverageInterval::cardAbsentDurationSeconds)
                                    .sum(),
                            first.startedAt(),
                            last.endedAt(),
                            first.previousDrivingSourceIntervalId(),
                            last.nextDrivingSourceIntervalId(),
                            containedIntervals
                    );
                })
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(DriverWorkingTimePotentialInVehicleTripInterval::startedAt)
                        .thenComparing(DriverWorkingTimePotentialInVehicleTripInterval::endedAt))
                .toList();
    }

    private boolean tripContainsPotentialInterval(
            String driverKey,
            String registrationKey,
            String vehicleKey,
            OffsetDateTime tripStartedAt,
            OffsetDateTime tripEndedAt,
            DriverWorkingTimeRestCoverageInterval candidate
    ) {
        if (!Objects.equals(driverKey, candidate.driverKey())) {
            return false;
        }
        if (!Objects.equals(registrationKey, candidate.previousRegistrationKey())) {
            return false;
        }
        if (vehicleKey != null && candidate.previousVehicleKey() != null
                && !Objects.equals(vehicleKey, candidate.previousVehicleKey())) {
            return false;
        }
        return !candidate.startedAt().isBefore(tripStartedAt)
                && !candidate.endedAt().isAfter(tripEndedAt);
    }

    private DriverWorkingTimeGeoEvidenceEvent geoEvidenceEvent(
            String eventId,
            String eventDomain,
            OffsetDateTime occurredAt,
            Double latitude,
            Double longitude,
            Long distanceSeconds,
            Long odometerKm
    ) {
        if (eventId == null
                && eventDomain == null
                && occurredAt == null
                && latitude == null
                && longitude == null
                && distanceSeconds == null
                && odometerKm == null) {
            return null;
        }
        return new DriverWorkingTimeGeoEvidenceEvent(
                eventId,
                eventDomain,
                occurredAt,
                latitude,
                longitude,
                distanceSeconds,
                odometerKm
        );
    }

    private <T> List<T> safeList(List<T> values) {
        return values == null ? List.of() : values;
    }

    private List<String> combinedNotes(List<String> extraNotes) {
        List<String> notes = new ArrayList<>();
        notes.addAll(esperProjectionNotes());
        if (extraNotes != null) {
            notes.addAll(extraNotes);
        }
        return List.copyOf(notes);
    }

    private List<String> esperProjectionNotes() {
        return List.of(
                "This result returns Esper-backed per-driver interval projections from the common runtime working-time engine.",
                "Driving intervals are a filtered projection of activity intervals where activityType = DRIVE.",
                "Driving interruption intervals are gaps between consecutive driving intervals longer than the configured significant-driving threshold.",
                "Driving interruption vehicle-change intervals are daily/weekly rest candidates where previousRegistrationKey differs from nextRegistrationKey.",
                "Daily/weekly rest candidate intervals are driving interruption intervals longer than the configured minimum rest-period threshold.",
                "Daily/weekly rest candidate coverage intervals enrich each rest candidate with card-present and card-absent coverage metrics computed from vehicle-usage and VU card-absent overlap.",
                "Daily/weekly rest candidate coverage intervals also attach begin/end geo evidence from nearby support events for the same driver and boundary-side vehicle identity.",
                "Boundary geo evidence prefers the nearest matching POSITION event, then PLACE, BORDER_CROSSING, and LOAD_UNLOAD within the configured lookback/lookahead windows.",
                "If both begin and end geo evidence carry odometer values, geoEvidenceMovementCategory classifies the interval as STATIONARY, MINOR, MOVED, or UNKNOWN.",
                "Unclassified daily/weekly rest candidate coverage intervals are the rest candidates that are neither potential home overnight stays nor potential in-vehicle overnight stays.",
                "Potential home overnight stay intervals are vehicle-change daily/weekly rest candidate coverage intervals where VU card-absent overlap covers at least 95% of the candidate interval.",
                "Potential in-vehicle overnight stay intervals are no-change daily/weekly rest candidate coverage intervals where card-present overlap covers the candidate rest period.",
                "Potential in-vehicle trip intervals span from the end of the coverage interval before a same-vehicle in-vehicle-overnight sequence to the start of the first coverage interval after that sequence.",
                "VU card-absent intervals are gaps between consecutive normalized vehicle-usage intervals for the same driver.",
                "occurredFrom and occurredTo clip the returned interval projections to the requested UTC time window.",
                "Vehicle-usage intervals clear clipped odometer endpoints because boundary odometer values cannot be recomputed safely from the source interval."
        );
    }

    private OffsetDateTime utc(OffsetDateTime value) {
        return value == null ? null : value.withOffsetSameInstant(ZoneOffset.UTC);
    }

    private OffsetDateTime max(OffsetDateTime left, OffsetDateTime right) {
        if (left == null) {
            return right;
        }
        if (right == null) {
            return left;
        }
        return left.isAfter(right) ? left : right;
    }

    private OffsetDateTime min(OffsetDateTime left, OffsetDateTime right) {
        if (left == null) {
            return right;
        }
        if (right == null) {
            return left;
        }
        return left.isBefore(right) ? left : right;
    }
}
