ALTER TABLE gateway_identity_configuration_revisions
  DROP CONSTRAINT IF EXISTS gateway_identity_configuration_revisions_schema_version_check;

ALTER TABLE gateway_identity_configuration_revisions
  ADD COLUMN IF NOT EXISTS tenant_mode text NOT NULL DEFAULT 'single_tenant',
  ADD COLUMN IF NOT EXISTS tenant_context_endpoint text,
  ADD COLUMN IF NOT EXISTS tenant_context_audience text,
  ADD COLUMN IF NOT EXISTS tenant_context_scope text,
  ADD CONSTRAINT gateway_identity_configuration_revisions_schema_version_check
    CHECK (schema_version IN (1,2)),
  ADD CONSTRAINT gateway_identity_configuration_revisions_tenant_mode_check
    CHECK (tenant_mode IN ('single_tenant','multi_tenant')),
  ADD CONSTRAINT gateway_identity_configuration_revisions_manifest_mode_check
    CHECK (
      (state='draft' AND issuer IS NULL)
      OR
      (schema_version=1 AND tenant_mode='single_tenant' AND tenant_id IS NOT NULL AND local_tenant_key <> ''
        AND tenant_context_endpoint IS NULL AND tenant_context_audience IS NULL AND tenant_context_scope IS NULL)
      OR
      (schema_version=2 AND tenant_mode='multi_tenant' AND tenant_id IS NULL AND local_tenant_key=''
        AND tenant_context_endpoint IS NOT NULL AND tenant_context_audience='urn:easyai:auth-center:tenant-context'
        AND tenant_context_scope='tenant.context.read')
    ) NOT VALID;

CREATE TABLE IF NOT EXISTS gateway_oidc_tenant_bindings (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  issuer text NOT NULL,
  application_id text NOT NULL,
  external_tenant_id text NOT NULL,
  gateway_tenant_id uuid NOT NULL REFERENCES gateway_tenants(id) ON DELETE CASCADE,
  access_status text NOT NULL DEFAULT 'active'
    CHECK (access_status IN ('active','disabled')),
  metadata_status text NOT NULL DEFAULT 'metadata_pending'
    CHECK (metadata_status IN ('metadata_pending','synced','rejected')),
  display_name text,
  slug text,
  metadata_version text,
  metadata_etag text,
  metadata_updated_at timestamptz,
  last_sync_at timestamptz,
  next_sync_at timestamptz NOT NULL DEFAULT now(),
  sync_failure_count integer NOT NULL DEFAULT 0 CHECK (sync_failure_count >= 0),
  last_error_category text,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now(),
  UNIQUE(issuer,application_id,external_tenant_id),
  UNIQUE(id,gateway_tenant_id)
);

CREATE INDEX IF NOT EXISTS idx_gateway_oidc_tenant_bindings_sync
  ON gateway_oidc_tenant_bindings(next_sync_at)
  WHERE access_status='active';

CREATE TABLE IF NOT EXISTS gateway_oidc_user_bindings (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_binding_id uuid NOT NULL REFERENCES gateway_oidc_tenant_bindings(id) ON DELETE CASCADE,
  subject text NOT NULL,
  gateway_user_id uuid NOT NULL REFERENCES gateway_users(id) ON DELETE CASCADE,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now(),
  UNIQUE(tenant_binding_id,subject),
  UNIQUE(id,gateway_user_id)
);

ALTER TABLE gateway_oidc_sessions
  ADD COLUMN IF NOT EXISTS oidc_user_binding_id uuid
    REFERENCES gateway_oidc_user_bindings(id) ON DELETE CASCADE,
  ADD COLUMN IF NOT EXISTS oidc_client_id text;

CREATE INDEX IF NOT EXISTS idx_gateway_oidc_sessions_user_binding
  ON gateway_oidc_sessions(oidc_user_binding_id,created_at DESC)
  WHERE oidc_user_binding_id IS NOT NULL;

ALTER TABLE gateway_security_event_receipts
  ADD COLUMN IF NOT EXISTS application_id text,
  ADD COLUMN IF NOT EXISTS subject_type text
    CHECK (subject_type IS NULL OR subject_type IN ('principal','tenant'));

ALTER TABLE gateway_oidc_revocation_watermarks
  ADD COLUMN IF NOT EXISTS application_id text NOT NULL DEFAULT '',
  ADD COLUMN IF NOT EXISTS subject_type text NOT NULL DEFAULT 'principal'
    CHECK (subject_type IN ('principal','tenant'));

ALTER TABLE gateway_oidc_revocation_watermarks
  DROP CONSTRAINT IF EXISTS gateway_oidc_revocation_watermarks_pkey;

ALTER TABLE gateway_oidc_revocation_watermarks
  ADD PRIMARY KEY (issuer,application_id,tenant_id,subject_type,subject);

DROP INDEX IF EXISTS idx_gateway_oidc_revocation_watermarks_lookup;
CREATE INDEX idx_gateway_oidc_revocation_watermarks_lookup
  ON gateway_oidc_revocation_watermarks(issuer,application_id,tenant_id,subject_type,subject,revoked_at);
