-- Step 1: Add columns, backfill, build indexes.
-- This migration does the heavy work but avoids ACCESS EXCLUSIVE during index build
-- by creating the unique index first, then using it for the PK swap in the next migration.

-- Add new columns (instant metadata change)
ALTER TABLE token ADD COLUMN token_hash VARCHAR(64);
ALTER TABLE token ADD COLUMN token_prefix VARCHAR(10);

-- Backfill existing tokens using built-in sha256() (no extension needed).
-- Takes ROW EXCLUSIVE lock — concurrent reads and non-token writes proceed normally.
UPDATE token
SET token_hash = encode(sha256(token::bytea), 'hex'),
    token_prefix = substring(token for 10)
WHERE token_hash IS NULL;

-- Mark NOT NULL (instant on PG 12+ when all rows already satisfy the constraint)
ALTER TABLE token ALTER COLUMN token_hash SET NOT NULL;
ALTER TABLE token ALTER COLUMN token_prefix SET NOT NULL;

-- Build the unique index that the next migration will promote to PK.
-- Takes SHARE lock (reads OK, writes wait) but only for the duration of the build,
-- which is fast since token tables are typically small.
CREATE UNIQUE INDEX token_hash_unique ON token (token_hash);

-- Index on prefix for deletion/listing
CREATE INDEX idx_token_prefix ON token (token_prefix);

-- Keep old workers fast during rolling upgrades: they query WHERE token = $1
-- after the PK swap drops the old primary key index on token.
-- Can be dropped once all workers are past MIN_VERSION_SUPPORTS_TOKEN_HASH.
CREATE INDEX idx_token_plaintext ON token (token) WHERE token IS NOT NULL;
