package at.procon.eventhub.esperpoc.persistence;

import at.procon.eventhub.esperpoc.dto.EsperSupportEventDto;
import at.procon.eventhub.esperpoc.dto.EsperSourceSelectionMode;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.UUID;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class EsperPocDtiEnrichmentRepository {

    private final JdbcTemplate jdbcTemplate;

    public EsperPocDtiEnrichmentRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public List<EsperSupportEventDto> findDriverSupportEvents(
            String tenantKey,
            UUID driverId,
            OffsetDateTime supportFrom,
            OffsetDateTime supportTo,
            int precedingDriverCardEventCount,
            EsperSourceSelectionMode sourceSelectionMode
    ) {
        return jdbcTemplate.query(
                """
                with candidate as (
                    select
                        event.id,
                        event.occurred_at,
                        coalesce(
                            event.payload #>> '{raw,sourceRowId}',
                            regexp_replace(event.external_source_event_id, ':(START|END|INSERT|WITHDRAW)$', '')
                        ) as source_row_id,
                        event.external_source_event_id,
                        source.source_kind,
                        coalesce(pkg.extraction_code, '') as extraction_code,
                        event.driver_id,
                        event.driver_card_id,
                        event.vehicle_id,
                        event.vehicle_registration_id,
                        event.event_domain,
                        event.event_type,
                        event.lifecycle,
                        detail.attributes ->> 'cardSlot' as card_slot,
                        st_y(event.position::geometry) as latitude,
                        st_x(event.position::geometry) as longitude,
                        detail.attributes ->> 'country' as country,
                        detail.attributes ->> 'region' as region,
                        detail.attributes ->> 'countryFrom' as country_from,
                        detail.attributes ->> 'countryTo' as country_to,
                        detail.attributes ->> 'operation' as operation
                    from eventhub.event event
                    join eventhub.event_source source on source.id = event.event_source_id
                    join eventhub.data_package pkg on pkg.id = event.data_package_id
                    left join lateral (
                        select detail.attributes
                        from eventhub.event_detail detail
                        where detail.event_occurred_at = event.occurred_at
                          and detail.event_id = event.id
                        order by detail.detail_type
                        limit 1
                    ) detail on true
                    where pkg.tenant_key = ?
                      and source.provider_key = 'TACHOGRAPH'
                      and event.driver_id = ?
                      and (? <> 'DRIVER_CARD_ONLY' or source.source_kind = 'DRIVER_CARD')
                      and event.event_domain in ('DRIVER_CARD', 'POSITION', 'PLACE', 'BORDER_CROSSING', 'LOAD_UNLOAD', 'SPECIFIC_CONDITION', 'SPEEDING')
                      and event.occurred_at < ?
                ),
                in_range as (
                    select * from candidate where occurred_at >= ?
                ),
                preceding_driver_card as (
                    select *
                    from candidate
                    where occurred_at < ?
                      and event_domain = 'DRIVER_CARD'
                    order by occurred_at desc, id desc
                    limit ?
                )
                select *
                from (
                    select * from in_range
                    union all
                    select * from preceding_driver_card
                ) result
                order by occurred_at, lifecycle, event_domain, event_type, id
                """,
                (rs, rowNum) -> new EsperSupportEventDto(
                        (UUID) rs.getObject("id"),
                        rs.getObject("occurred_at", OffsetDateTime.class),
                        rs.getString("source_row_id"),
                        rs.getString("external_source_event_id"),
                        rs.getString("source_kind"),
                        rs.getString("extraction_code"),
                        (UUID) rs.getObject("driver_id"),
                        (UUID) rs.getObject("driver_card_id"),
                        (UUID) rs.getObject("vehicle_id"),
                        (UUID) rs.getObject("vehicle_registration_id"),
                        rs.getString("event_domain"),
                        rs.getString("event_type"),
                        rs.getString("lifecycle"),
                        rs.getString("card_slot"),
                        rs.getBigDecimal("latitude"),
                        rs.getBigDecimal("longitude"),
                        rs.getString("country"),
                        rs.getString("region"),
                        rs.getString("country_from"),
                        rs.getString("country_to"),
                        rs.getString("operation")
                ),
                tenantKey,
                driverId,
                sourceSelectionMode == null ? EsperSourceSelectionMode.MIXED.name() : sourceSelectionMode.name(),
                supportTo,
                supportFrom,
                supportFrom,
                precedingDriverCardEventCount
        );
    }
}
