package at.procon.eventhub.yellowfox.service;

import at.procon.eventhub.config.EventHubProperties;
import at.procon.eventhub.dto.AcquisitionStrategy;
import at.procon.eventhub.dto.EventSourceDto;
import at.procon.eventhub.dto.ImportMode;
import at.procon.eventhub.dto.ImportScopeDto;
import at.procon.eventhub.dto.ImportCursorStateDto;
import at.procon.eventhub.dto.SourceGroupRefDto;
import at.procon.eventhub.dto.SourceGroupType;
import at.procon.eventhub.yellowfox.dto.YellowFoxD8ImportRequest;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.EnumSet;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.DefaultResourceLoader;

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

class JdbcYellowFoxD8BookingExtractionBatchExecutorTest {

    @Test
    void omitsCursorParametersWhenNoCursorExists() {
        JdbcYellowFoxD8BookingExtractionBatchExecutor executor = executor(Duration.ofHours(2));

        JdbcYellowFoxD8BookingExtractionBatchExecutor.QuerySpec query = executor.buildQuerySpec(
                request(AcquisitionStrategy.SOURCE_ROW_WATERMARK),
                ImportScopeDto.tenantAll(
                        OffsetDateTime.parse("2026-04-01T00:00:00+02:00"),
                        OffsetDateTime.parse("2026-04-02T00:00:00+02:00")
                ),
                null
        );

        assertThat(query.sql()).contains("b.utc >= :occurredFrom");
        assertThat(query.sql()).contains("b.utc < :occurredTo");
        assertThat(query.sql()).contains("f.id = :fleetId");
        assertThat(query.sql()).doesNotContain(":lastOccurredTo");
        assertThat(query.sql()).doesNotContain(" is null");
        assertThat(query.params()).containsOnlyKeys("occurredFrom", "occurredTo", "fleetId");
        assertThat(query.fleetId()).isEqualTo(7);
    }

    @Test
    void keepsStrictUtcEventIdCursorWhenOverlapIsDisabled() {
        JdbcYellowFoxD8BookingExtractionBatchExecutor executor = executor(Duration.ZERO);
        OffsetDateTime cursorTime = OffsetDateTime.parse("2026-04-02T09:15:00+02:00");

        JdbcYellowFoxD8BookingExtractionBatchExecutor.QuerySpec query = executor.buildQuerySpec(
                request(AcquisitionStrategy.SOURCE_ROW_WATERMARK),
                ImportScopeDto.tenantAll(null, null),
                new ImportCursorStateDto(null, "4711", null, cursorTime)
        );

        assertThat(query.sql()).contains("b.utc > :lastOccurredTo");
        assertThat(query.sql()).contains("b.utc = :lastOccurredTo");
        assertThat(query.sql()).contains("b.eventid > :lastSourceRowId");
        assertThat(query.sql()).doesNotContain(" is null");
        assertThat(query.params()).containsEntry("lastOccurredTo", cursorTime);
        assertThat(query.params()).containsEntry("lastSourceRowId", "4711");
    }

    @Test
    void keepsOccurredToCapOnceCursorExistsForWatermarkIncrementalRuns() {
        JdbcYellowFoxD8BookingExtractionBatchExecutor executor = executor(Duration.ZERO);
        OffsetDateTime cursorTime = OffsetDateTime.parse("2026-04-02T09:15:00+02:00");

        JdbcYellowFoxD8BookingExtractionBatchExecutor.QuerySpec query = executor.buildQuerySpec(
                request(AcquisitionStrategy.SOURCE_ROW_WATERMARK),
                ImportScopeDto.tenantAll(
                        OffsetDateTime.parse("2026-04-01T00:00:00+02:00"),
                        OffsetDateTime.parse("2026-04-02T00:00:00+02:00")
                ),
                new ImportCursorStateDto(null, "4711", null, cursorTime)
        );

        assertThat(query.sql()).contains("b.utc >= :occurredFrom");
        assertThat(query.sql()).contains("b.utc < :occurredTo");
        assertThat(query.params()).containsEntry("occurredFrom", OffsetDateTime.parse("2026-04-01T00:00:00+02:00"));
        assertThat(query.params()).containsEntry("occurredTo", OffsetDateTime.parse("2026-04-02T00:00:00+02:00"));
    }

    private JdbcYellowFoxD8BookingExtractionBatchExecutor executor(Duration overlap) {
        EventHubProperties properties = new EventHubProperties();
        properties.getYellowFox().setOccurredAtOverlap(overlap);
        return new JdbcYellowFoxD8BookingExtractionBatchExecutor(
                null,
                null,
                null,
                new DefaultResourceLoader(),
                null,
                properties,
                null,
                null,
                null
        );
    }

    private YellowFoxD8ImportRequest request(AcquisitionStrategy strategy) {
        return new YellowFoxD8ImportRequest(
                "tenant-1",
                new EventSourceDto("YELLOWFOX", "TELEMATICS_PLATFORM", "YELLOWFOX_D8", "instance-1", "setting-1", null),
                new SourceGroupRefDto(SourceGroupType.FLEET, "7", null, "Fleet 7"),
                ImportScopeDto.tenantAll(null, null),
                EnumSet.noneOf(at.procon.eventhub.dto.EventFamily.class),
                ImportMode.INCREMENTAL_UPDATE,
                false,
                strategy
        );
    }
}
