-- KBX v9 production runtime projections.
-- These tables hold operational state, not domain truth.
create schema if not exists kbx;

create table if not exists kbx.operation_runs (
  id uuid primary key,
  tenant_id uuid not null,
  user_id uuid,
  operation_type varchar(80) not null,
  title varchar(200) not null,
  source_screen_id varchar(60),
  status varchar(30) not null,
  requested_at timestamptz not null default now(),
  started_at timestamptz,
  completed_at timestamptz,
  processed bigint not null default 0 check(processed >= 0),
  total bigint check(total is null or total >= 0),
  succeeded bigint not null default 0 check(succeeded >= 0),
  failed bigint not null default 0 check(failed >= 0),
  correlation_id varchar(100),
  idempotency_key varchar(160),
  result_message varchar(1000),
  result jsonb,
  expires_at timestamptz,
  unique(tenant_id, idempotency_key)
);
create index if not exists ix_kbx_operation_runs_user_recent on kbx.operation_runs(tenant_id, user_id, requested_at desc);
create index if not exists ix_kbx_operation_runs_status on kbx.operation_runs(tenant_id, status, requested_at desc);

create table if not exists kbx.user_notifications (
  id uuid primary key,
  tenant_id uuid not null,
  user_id uuid not null,
  severity varchar(20) not null,
  category varchar(50) not null,
  title varchar(200) not null,
  message varchar(1000),
  screen_id varchar(60),
  entity_type varchar(80),
  entity_id varchar(120),
  action jsonb,
  created_at timestamptz not null default now(),
  read_at timestamptz,
  expires_at timestamptz
);
create index if not exists ix_kbx_user_notifications_unread on kbx.user_notifications(tenant_id, user_id, created_at desc) where read_at is null;

create table if not exists kbx.runtime_incidents (
  id uuid primary key,
  tenant_id uuid,
  mode varchar(20) not null,
  title varchar(200) not null,
  message varchar(1000),
  started_at timestamptz not null,
  ended_at timestamptz,
  correlation_id varchar(100),
  metadata jsonb
);
create index if not exists ix_kbx_runtime_incidents_active on kbx.runtime_incidents(started_at desc) where ended_at is null;
