-- v12.1 execution-readiness delta. Prior migrations remain immutable.

alter table building_blocks.outbox_message
    add column if not exists next_attempt_at timestamptz null,
    add column if not exists lease_owner text null,
    add column if not exists lease_until timestamptz null,
    add column if not exists dead_lettered_at timestamptz null,
    add column if not exists last_error_code text null;

create index if not exists ix_outbox_dispatchable
    on building_blocks.outbox_message (coalesce(next_attempt_at, occurred_at), occurred_at, message_id)
    where published_at is null and dead_lettered_at is null;

alter table building_blocks.inbox_message
    add column if not exists processed_at timestamptz null,
    add column if not exists result_hash text null;

create table if not exists building_blocks.projection_checkpoint (
    projection_name text not null,
    projection_version integer not null check (projection_version > 0),
    source_watermark text not null,
    last_event_id uuid null,
    content_hash text not null,
    built_at timestamptz not null,
    primary key (projection_name, projection_version)
);

create table if not exists building_blocks.projection_rebuild_run (
    rebuild_id uuid primary key,
    projection_name text not null,
    target_version integer not null check (target_version > 0),
    through_watermark text not null,
    dry_run boolean not null,
    requested_by text not null,
    requested_at timestamptz not null,
    status text not null,
    source_count bigint null,
    projected_count bigint null,
    result_hash text null,
    finished_at timestamptz null,
    error_code text null
);

create table if not exists building_blocks.audit_event (
    audit_event_id uuid primary key,
    entity_type text not null,
    entity_id text not null,
    event_type text not null,
    actor_id text not null,
    correlation_id text not null,
    payload_json jsonb not null,
    payload_hash text not null,
    corrects_audit_event_id uuid null references building_blocks.audit_event(audit_event_id),
    occurred_at timestamptz not null,
    unique (entity_type, entity_id, event_type, payload_hash)
);

create or replace function building_blocks.prevent_append_only_change()
returns trigger language plpgsql as $$
begin
  raise exception 'append-only row cannot be updated or deleted';
end;
$$;

drop trigger if exists audit_event_append_only on building_blocks.audit_event;
create trigger audit_event_append_only
before update or delete on building_blocks.audit_event
for each row execute function building_blocks.prevent_append_only_change();
