-- 990_beta_invites.sql
-- v1.0.10 polish (Cluster 3.4) — soft-launch beta cohort tracking.
--
-- Records each individual invitation sent for the v2.0.0 soft-launch
-- bêta. Tracks (a) the invite code used in the registration link,
-- (b) when the recipient redeemed it (NULL until redemption), and
-- (c) which cohort segment (creator / listener / community-member /
-- press) the recipient belongs to so the post-launch report can
-- attribute feedback by audience.
--
-- The associated email template + send script live at
-- scripts/soft-launch/send-invitations.sh and reference this table
-- via INSERT … RETURNING code.
--
-- Privacy : the email column is the only PII here ; no behavioural
-- data is stored. used_at is the redemption signal. After v2.0.0
-- public launch, run the cleanup migration in 991 (TBD) to anonymise
-- the email column for invites that haven't been redeemed in 30+ days.

CREATE TABLE IF NOT EXISTS public.beta_invites (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    -- The invite code is what the recipient pastes into the signup
    -- form. 16 random characters from a base32 alphabet (no 0/1/I/L
    -- to avoid eyestrain). Generated by send-invitations.sh.
    code        VARCHAR(32) NOT NULL UNIQUE,
    email       VARCHAR(320) NOT NULL,
    -- Free-text label so the cohort generator can carry whatever
    -- segmentation the operator wants (e.g. "creator-vinyl-pressing",
    -- "listener-jazz-mailing-list", "press-pitchfork"). Index below
    -- is for the post-launch report grouping.
    cohort      VARCHAR(64) NOT NULL,
    -- NULL until the recipient signs up. Set by the auth handler
    -- when /auth/register is hit with a valid invite code.
    used_at     TIMESTAMPTZ,
    -- Hard expiry so unredeemed invites can't accumulate forever.
    -- Default 30 days from creation ; soft-launch is short-window.
    expires_at  TIMESTAMPTZ NOT NULL DEFAULT (NOW() + INTERVAL '30 days'),
    -- Operator who sent the invite — useful when reconciling "who
    -- gave their friend a code" during the audit.
    sent_by     UUID REFERENCES public.users(id) ON DELETE SET NULL,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

COMMENT ON TABLE public.beta_invites IS
    'v2.0.0 soft-launch beta invitation tracking. v1.0.10 Cluster 3.4.';
COMMENT ON COLUMN public.beta_invites.code IS
    '16-char base32 invite code (no 0/1/I/L). Pasted into signup form.';
COMMENT ON COLUMN public.beta_invites.cohort IS
    'Free-text cohort label (creator-* / listener-* / press-* / etc.).';
COMMENT ON COLUMN public.beta_invites.used_at IS
    'Redemption timestamp. NULL means the invite is still pending.';

-- Lookup by code (signup path) — every /auth/register call reads it.
CREATE UNIQUE INDEX IF NOT EXISTS idx_beta_invites_code
    ON public.beta_invites(code);

-- Cohort grouping for the post-launch attribution query.
CREATE INDEX IF NOT EXISTS idx_beta_invites_cohort
    ON public.beta_invites(cohort);

-- Pending-invitations sweep — cron job that expires unused invites
-- after expires_at. Partial index keeps it small.
CREATE INDEX IF NOT EXISTS idx_beta_invites_pending_expiry
    ON public.beta_invites(expires_at)
    WHERE used_at IS NULL;
