CREATE TABLE IF NOT EXISTS gateway_identity_onboarding_exchanges (
  id uuid PRIMARY KEY,
  revision_id uuid NOT NULL UNIQUE REFERENCES gateway_identity_configuration_revisions(id) ON DELETE CASCADE,
  remote_exchange_id uuid NOT NULL UNIQUE,
  exchange_token_ref text NOT NULL CHECK (exchange_token_ref ~ '^[a-z0-9][a-z0-9-]{0,127}$'),
  status text NOT NULL CHECK (status IN (
    'metadata_pending','preparing','ready','credentials_saved','completed','failed','expired','cancelled'
  )),
  cleanup_status text NOT NULL DEFAULT 'none' CHECK (cleanup_status IN ('none','pending','completed')),
  remote_version bigint NOT NULL CHECK (remote_version > 0),
  expires_at timestamptz NOT NULL,
  version bigint NOT NULL DEFAULT 1 CHECK (version > 0),
  last_error_category text,
  auth_center_audit_id text,
  last_trace_id text,
  cancelled_at timestamptz,
  cleanup_completed_at timestamptz,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT gateway_identity_onboarding_cleanup_lifecycle_check CHECK (
    (status <> 'cancelled' AND cleanup_status = 'none' AND cancelled_at IS NULL AND cleanup_completed_at IS NULL) OR
    (status = 'cancelled' AND cancelled_at IS NOT NULL AND (
      (cleanup_status = 'pending' AND cleanup_completed_at IS NULL) OR
      (cleanup_status = 'completed' AND cleanup_completed_at IS NOT NULL)
    ))
  ),
  CONSTRAINT gateway_identity_onboarding_error_category_check CHECK (
    last_error_category IS NULL OR last_error_category IN (
      'metadata_submission_failed','exchange_status_unavailable','credential_delivery_failed',
      'exchange_completion_failed','exchange_expired','remote_exchange_failed','remote_state_invalid',
      'security_event_configuration_invalid','security_event_connection_conflict',
      'security_event_discovery_failed','security_event_management_token_failed',
      'security_event_stream_create_failed','security_event_stream_response_invalid',
      'security_event_receiver_activation_failed','security_event_preparation_failed',
      'security_event_retirement_pending','security_event_credential_handoff_unsafe',
      'security_event_connection_binding_missing','security_event_connection_binding_unavailable',
      'security_event_connection_binding_invalid','security_event_connection_binding_mismatch',
      'pairing_step_failed','cleanup_revision_unavailable','cleanup_security_event_unavailable',
      'cleanup_security_event_configuration_invalid','cleanup_security_event_connection_conflict',
      'cleanup_security_event_discovery_failed','cleanup_security_event_management_token_failed',
      'cleanup_security_event_stream_create_failed','cleanup_security_event_stream_response_invalid',
      'cleanup_security_event_receiver_activation_failed','cleanup_security_event_preparation_failed',
      'cleanup_security_event_retirement_pending','cleanup_security_event_connection_cleanup_failed',
      'cleanup_security_event_secret_cleanup_failed','cleanup_security_event_credential_handoff_unsafe',
      'cleanup_security_event_failed','cleanup_secret_store_failed','cleanup_finalize_failed'
    )
  )
);

CREATE INDEX IF NOT EXISTS idx_gateway_identity_onboarding_status
  ON gateway_identity_onboarding_exchanges(status, updated_at DESC);

CREATE INDEX IF NOT EXISTS idx_gateway_identity_onboarding_cleanup
  ON gateway_identity_onboarding_exchanges(cleanup_status, updated_at)
  WHERE cleanup_status = 'pending';
