-- Загрузка DDS dim_airplanes: SCD1 UPSERT (UPDATE изменившихся + INSERT новых).

-- Statement 1: UPDATE существующих записей (если атрибуты изменились).
WITH seats_agg AS (
    SELECT
        s.airplane_code,
        COUNT(*)::INTEGER AS total_seats
    FROM ods.seats AS s
    GROUP BY s.airplane_code
),
src AS (
    SELECT
        a.airplane_code,
        a.model,
        a.range_km,
        a.speed_kmh,
        COALESCE(sa.total_seats, 0) AS total_seats
    FROM ods.airplanes AS a
    LEFT JOIN seats_agg AS sa
        ON sa.airplane_code = a.airplane_code
)
UPDATE dds.dim_airplanes AS d
SET model       = s.model,
    range_km    = s.range_km,
    speed_kmh   = s.speed_kmh,
    total_seats = s.total_seats,
    updated_at  = now(),
    _load_id    = '{{ run_id }}',
    _load_ts    = now()
FROM src AS s
WHERE d.airplane_bk = s.airplane_code
    AND (
        d.model IS DISTINCT FROM s.model
        OR d.range_km IS DISTINCT FROM s.range_km
        OR d.speed_kmh IS DISTINCT FROM s.speed_kmh
        OR d.total_seats IS DISTINCT FROM s.total_seats
    );

-- Statement 2: INSERT новых записей (MAX(sk) + ROW_NUMBER()).
WITH seats_agg AS (
    SELECT
        s.airplane_code,
        COUNT(*)::INTEGER AS total_seats
    FROM ods.seats AS s
    GROUP BY s.airplane_code
),
src AS (
    SELECT
        a.airplane_code,
        a.model,
        a.range_km,
        a.speed_kmh,
        COALESCE(sa.total_seats, 0) AS total_seats
    FROM ods.airplanes AS a
    LEFT JOIN seats_agg AS sa
        ON sa.airplane_code = a.airplane_code
),
-- Учебный комментарий: Генерация SK через MAX() + ROW_NUMBER()
-- Этот подход работает безопасно только потому, что Airflow запускает
-- джобы загрузки для одной таблицы строго последовательно (concurrency=1).
-- При параллельной загрузке возникнет состояние гонки (race condition) и возможны дубли SK.
max_sk AS (
    SELECT COALESCE(MAX(airplane_sk), 0) AS v
    FROM dds.dim_airplanes
)
INSERT INTO dds.dim_airplanes (
    airplane_sk,
    airplane_bk,
    model,
    range_km,
    speed_kmh,
    total_seats,
    created_at,
    updated_at,
    _load_id,
    _load_ts
)
SELECT
    (SELECT v FROM max_sk) + ROW_NUMBER() OVER (ORDER BY s.airplane_code)::INTEGER,
    s.airplane_code,
    s.model,
    s.range_km,
    s.speed_kmh,
    s.total_seats,
    now(),
    now(),
    '{{ run_id }}',
    now()
FROM src AS s
WHERE NOT EXISTS (
    SELECT 1
    FROM dds.dim_airplanes AS d
    WHERE d.airplane_bk = s.airplane_code
);

ANALYZE dds.dim_airplanes;
