drop index if exists eventhub.idx_vehicle_registration_plate;

alter table eventhub.vehicle_registration
    drop constraint if exists chk_vehicle_registration_valid_time_order;

alter table eventhub.vehicle_registration
    drop column if exists valid_from,
    drop column if exists valid_to;

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

update eventhub.source_master_entity
set valid_from = null,
    valid_to = null,
    updated_at = now()
where entity_type = 'VEHICLE_REGISTRATION'
  and (valid_from is not null or valid_to is not null);

with vehicle_entities as (
    select tenant_key,
           event_source_id,
           nullif(source_entity_id, '') as source_vehicle_entity_id,
           nullif(source_external_key, '') as vin
    from eventhub.source_master_entity
    where entity_type = 'VEHICLE'
      and (nullif(source_entity_id, '') is not null or nullif(source_external_key, '') is not null)
)
update eventhub.vehicle vehicle
set source_vehicle_entity_id = coalesce(vehicle.source_vehicle_entity_id, vehicle_entities.source_vehicle_entity_id),
    vin = coalesce(vehicle.vin, vehicle_entities.vin),
    updated_at = now()
from vehicle_entities
where vehicle.tenant_key = vehicle_entities.tenant_key
  and vehicle.event_source_id = vehicle_entities.event_source_id
  and (
      vehicle.source_vehicle_entity_id = vehicle_entities.source_vehicle_entity_id
      or vehicle.vin = vehicle_entities.vin
  );

with vehicle_entities as (
    select tenant_key,
           event_source_id,
           nullif(source_entity_id, '') as source_vehicle_entity_id,
           nullif(source_external_key, '') as vin
    from eventhub.source_master_entity
    where entity_type = 'VEHICLE'
      and (nullif(source_entity_id, '') is not null or nullif(source_external_key, '') is not null)
)
insert into eventhub.vehicle(id, tenant_key, event_source_id, source_vehicle_entity_id, vin)
select gen_random_uuid(),
       vehicle_entities.tenant_key,
       vehicle_entities.event_source_id,
       vehicle_entities.source_vehicle_entity_id,
       vehicle_entities.vin
from vehicle_entities
where not exists (
    select 1
    from eventhub.vehicle vehicle
    where vehicle.tenant_key = vehicle_entities.tenant_key
      and vehicle.event_source_id = vehicle_entities.event_source_id
      and (
          vehicle.source_vehicle_entity_id = vehicle_entities.source_vehicle_entity_id
          or vehicle.vin = vehicle_entities.vin
      )
);

with registration_entities as (
    select tenant_key,
           event_source_id,
           nullif(source_entity_id, '') as source_registration_entity_id,
           coalesce(
               nullif(payload ->> 'registration_nation', ''),
               nullif(split_part(source_external_key, ':', 1), '')
           ) as nation,
           coalesce(
               nullif(payload ->> 'registration_number', ''),
               case
                   when position(':' in source_external_key) > 0
                       then nullif(substring(source_external_key from position(':' in source_external_key) + 1), '')
                   else nullif(source_external_key, '')
               end
           ) as registration_number,
           source_updated_at
    from eventhub.source_master_entity
    where entity_type = 'VEHICLE_REGISTRATION'
)
update eventhub.vehicle_registration registration
set source_registration_entity_id = coalesce(
        registration.source_registration_entity_id,
        registration_entities.source_registration_entity_id
    ),
    nation = coalesce(registration_entities.nation, registration.nation),
    registration_number = coalesce(registration_entities.registration_number, registration.registration_number),
    source_updated_at = registration_entities.source_updated_at,
    updated_at = now()
from registration_entities
where registration_entities.nation is not null
  and registration_entities.registration_number is not null
  and registration.tenant_key = registration_entities.tenant_key
  and registration.event_source_id = registration_entities.event_source_id
  and (
      registration.source_registration_entity_id = registration_entities.source_registration_entity_id
      or (
          registration.nation = registration_entities.nation
          and registration.registration_number = registration_entities.registration_number
      )
  );

with registration_entities as (
    select tenant_key,
           event_source_id,
           nullif(source_entity_id, '') as source_registration_entity_id,
           coalesce(
               nullif(payload ->> 'registration_nation', ''),
               nullif(split_part(source_external_key, ':', 1), '')
           ) as nation,
           coalesce(
               nullif(payload ->> 'registration_number', ''),
               case
                   when position(':' in source_external_key) > 0
                       then nullif(substring(source_external_key from position(':' in source_external_key) + 1), '')
                   else nullif(source_external_key, '')
               end
           ) as registration_number,
           source_updated_at
    from eventhub.source_master_entity
    where entity_type = 'VEHICLE_REGISTRATION'
)
insert into eventhub.vehicle_registration(
    id, tenant_key, event_source_id, source_registration_entity_id,
    nation, registration_number, source_updated_at, payload
)
select gen_random_uuid(),
       registration_entities.tenant_key,
       registration_entities.event_source_id,
       registration_entities.source_registration_entity_id,
       registration_entities.nation,
       registration_entities.registration_number,
       registration_entities.source_updated_at,
       jsonb_build_object('source', 'master-data')
from registration_entities
where registration_entities.nation is not null
  and registration_entities.registration_number is not null
  and not exists (
      select 1
      from eventhub.vehicle_registration registration
      where registration.tenant_key = registration_entities.tenant_key
        and registration.event_source_id = registration_entities.event_source_id
        and (
            registration.source_registration_entity_id = registration_entities.source_registration_entity_id
            or (
                registration.nation = registration_entities.nation
                and registration.registration_number = registration_entities.registration_number
            )
        )
  );

insert into eventhub.vehicle_registration_assignment(
    id, tenant_key, event_source_id, vehicle_registration_id, vehicle_id,
    valid_from, valid_to, source_updated_at, payload
)
select gen_random_uuid(),
       relation.tenant_key,
       relation.event_source_id,
       registration.id,
       vehicle.id,
       relation.valid_from,
       relation.valid_to,
       relation.source_updated_at,
       jsonb_build_object(
           'source', 'master-data',
           'sourceRelationId', relation.id,
           'relationKey', relation.relation_key
       )
from eventhub.source_master_relation relation
join eventhub.vehicle_registration registration on registration.tenant_key = relation.tenant_key
    and registration.event_source_id = relation.event_source_id
    and registration.source_registration_entity_id = relation.from_source_entity_id
join eventhub.vehicle vehicle on vehicle.tenant_key = relation.tenant_key
    and vehicle.event_source_id = relation.event_source_id
    and vehicle.source_vehicle_entity_id = relation.to_source_entity_id
where relation.relation_type = 'VEHICLE_REGISTRATION_VEHICLE'
  and relation.from_entity_type = 'VEHICLE_REGISTRATION'
  and relation.to_entity_type = 'VEHICLE'
  and not exists (
      select 1
      from eventhub.vehicle_registration_assignment existing
      where existing.vehicle_registration_id = registration.id
        and existing.vehicle_id = vehicle.id
        and existing.valid_from is not distinct from relation.valid_from
        and existing.valid_to is not distinct from relation.valid_to
  );
