alter table eventhub.vehicle
    add column if not exists source_vehicle_entity_id text,
    add column if not exists vin text;

do $migration$
begin
    if to_regclass('eventhub.vehicle_identifier') is not null
        and exists (
            select 1
            from information_schema.columns
            where table_schema = 'eventhub'
              and table_name = 'vehicle_identifier'
              and column_name = 'vehicle_id'
        )
    then
        execute $sql$
            update eventhub.vehicle v
            set source_vehicle_entity_id = src.identifier_value
            from eventhub.vehicle_identifier src
            where src.vehicle_id = v.id
              and src.identifier_type = 'SOURCE_VEHICLE'
              and v.source_vehicle_entity_id is null
        $sql$;

        execute $sql$
            update eventhub.vehicle v
            set vin = src.identifier_value
            from eventhub.vehicle_identifier src
            where src.vehicle_id = v.id
              and src.identifier_type = 'VIN'
              and v.vin is null
        $sql$;
    end if;
end
$migration$;

create table if not exists eventhub.vehicle_registration (
    id uuid primary key,
    tenant_key text not null,
    event_source_id integer not null references eventhub.event_source(id),
    source_registration_entity_id text,
    nation text not null,
    registration_number text not null,
    valid_from timestamptz,
    valid_to timestamptz,
    source_updated_at timestamptz,
    payload jsonb not null default '{}'::jsonb,
    created_at timestamptz not null default now(),
    updated_at timestamptz not null default now(),
    constraint chk_vehicle_registration_valid_time_order
        check (valid_from is null or valid_to is null or valid_from <= valid_to)
);

create table if not exists eventhub.vehicle_registration_assignment (
    id uuid primary key,
    tenant_key text not null,
    event_source_id integer not null references eventhub.event_source(id),
    vehicle_registration_id uuid not null references eventhub.vehicle_registration(id) on delete cascade,
    vehicle_id uuid not null references eventhub.vehicle(id) on delete cascade,
    valid_from timestamptz,
    valid_to timestamptz,
    source_updated_at timestamptz,
    payload jsonb not null default '{}'::jsonb,
    created_at timestamptz not null default now(),
    updated_at timestamptz not null default now(),
    constraint chk_vehicle_registration_assignment_valid_time_order
        check (valid_from is null or valid_to is null or valid_from <= valid_to)
);

do $migration$
begin
    if to_regclass('eventhub.vehicle_identifier') is not null
        and exists (
            select 1
            from information_schema.columns
            where table_schema = 'eventhub'
              and table_name = 'vehicle_identifier'
              and column_name = 'vehicle_id'
        )
    then
        execute $sql$
            insert into eventhub.vehicle_registration(
                id, tenant_key, event_source_id, source_registration_entity_id, nation, registration_number,
                valid_from, valid_to, payload
            )
            select gen_random_uuid(),
                   src.tenant_key,
                   src.event_source_id,
                   source_reg.identifier_value,
                   src.nation,
                   src.identifier_value,
                   src.valid_from,
                   src.valid_to,
                   src.payload
            from eventhub.vehicle_identifier src
            left join eventhub.vehicle_identifier source_reg on source_reg.vehicle_id = src.vehicle_id
                and source_reg.identifier_type = 'SOURCE_REGISTRATION'
            where src.identifier_type = 'VRN'
              and src.nation is not null
              and not exists (
                  select 1
                  from eventhub.vehicle_registration existing
                  where existing.tenant_key = src.tenant_key
                    and existing.event_source_id = src.event_source_id
                    and existing.nation = src.nation
                    and existing.registration_number = src.identifier_value
                    and existing.valid_from is not distinct from src.valid_from
                    and existing.valid_to is not distinct from src.valid_to
              )
        $sql$;

        execute $sql$
            insert into eventhub.vehicle_registration_assignment(
                id, tenant_key, event_source_id, vehicle_registration_id, vehicle_id, valid_from, valid_to, payload
            )
            select gen_random_uuid(),
                   reg.tenant_key,
                   reg.event_source_id,
                   reg.id,
                   v.id,
                   reg.valid_from,
                   reg.valid_to,
                   jsonb_build_object('migrated_from', 'vehicle_identifier')
            from eventhub.vehicle_registration reg
            join eventhub.vehicle_identifier vrn on vrn.tenant_key = reg.tenant_key
                and vrn.event_source_id = reg.event_source_id
                and vrn.identifier_type = 'VRN'
                and vrn.nation = reg.nation
                and vrn.identifier_value = reg.registration_number
                and vrn.valid_from is not distinct from reg.valid_from
                and vrn.valid_to is not distinct from reg.valid_to
            join eventhub.vehicle v on v.id = vrn.vehicle_id
            where not exists (
                select 1
                from eventhub.vehicle_registration_assignment existing
                where existing.vehicle_registration_id = reg.id
                  and existing.vehicle_id = v.id
                  and existing.valid_from is not distinct from reg.valid_from
                  and existing.valid_to is not distinct from reg.valid_to
            )
        $sql$;
    end if;
end
$migration$;

do $migration$
begin
    if exists (
        select 1
        from information_schema.columns
        where table_schema = 'eventhub'
          and table_name = 'event'
          and column_name = 'vehicle_entity_id'
    )
    and not exists (
        select 1
        from information_schema.columns
        where table_schema = 'eventhub'
          and table_name = 'event'
          and column_name = 'vehicle_id'
    )
    then
        alter table eventhub.event rename column vehicle_entity_id to vehicle_id;
    end if;

    if not exists (
        select 1
        from information_schema.columns
        where table_schema = 'eventhub'
          and table_name = 'event'
          and column_name = 'vehicle_id'
    )
    then
        alter table eventhub.event add column vehicle_id uuid references eventhub.vehicle(id);
    end if;
end
$migration$;

alter table eventhub.event
    drop constraint if exists event_vehicle_entity_id_fkey;

alter table eventhub.event
    drop constraint if exists fk_event_vehicle;

do $migration$
begin
    if exists (
        select 1
        from information_schema.columns
        where table_schema = 'eventhub'
          and table_name = 'event'
          and column_name = 'vehicle_id'
    )
    then
        alter table eventhub.event
            add constraint fk_event_vehicle
            foreign key (vehicle_id)
            references eventhub.vehicle(id)
            not valid;
    end if;
end
$migration$;

alter table eventhub.event
    add column if not exists vehicle_registration_id uuid references eventhub.vehicle_registration(id);

create index if not exists idx_vehicle_source_entity
    on eventhub.vehicle(tenant_key, event_source_id, source_vehicle_entity_id)
    where source_vehicle_entity_id is not null;

create index if not exists idx_vehicle_vin
    on eventhub.vehicle(tenant_key, event_source_id, vin)
    where vin is not null;

create index if not exists idx_vehicle_registration_source_entity
    on eventhub.vehicle_registration(tenant_key, event_source_id, source_registration_entity_id)
    where source_registration_entity_id is not null;

create index if not exists idx_vehicle_registration_plate
    on eventhub.vehicle_registration(tenant_key, event_source_id, nation, registration_number, valid_from desc);

create index if not exists idx_vehicle_registration_assignment_registration_time
    on eventhub.vehicle_registration_assignment(vehicle_registration_id, valid_from desc, valid_to);

create index if not exists idx_vehicle_registration_assignment_vehicle_time
    on eventhub.vehicle_registration_assignment(vehicle_id, valid_from desc, valid_to);

create index if not exists idx_event_vehicle_registration_time
    on eventhub.event(vehicle_registration_id, occurred_at desc)
    where vehicle_registration_id is not null;

alter table eventhub.event
    drop constraint if exists chk_event_driver_or_vehicle_ref;

alter table eventhub.event
    add constraint chk_event_driver_or_vehicle_ref
        check (
            driver_entity_id is not null
            or vehicle_id is not null
            or vehicle_registration_id is not null
        );
