-- Migration 015: SaaS Onboarding + Auth (Stripe, Refresh Tokens, MFA, SSO, Passkeys)
-- Adds tables for refresh tokens, stripe event tracking, invite tokens,
-- onboarding progress, and WebAuthn passkeys.

-- ============================================================================
-- 1. Modify shared.organizations — add Stripe billing columns
-- ============================================================================
ALTER TABLE shared.organizations ADD COLUMN IF NOT EXISTS stripe_customer_id VARCHAR(255) UNIQUE;
ALTER TABLE shared.organizations ADD COLUMN IF NOT EXISTS stripe_subscription_id VARCHAR(255) UNIQUE;
ALTER TABLE shared.organizations ADD COLUMN IF NOT EXISTS trial_ends_at TIMESTAMPTZ;

-- Update plan_level CHECK constraint to include new SaaS plan tiers
-- (Drop and re-add since ALTER CHECK is not supported in PG)
ALTER TABLE shared.organizations DROP CONSTRAINT IF EXISTS organizations_plan_level_check;
ALTER TABLE shared.organizations ADD CONSTRAINT organizations_plan_level_check
  CHECK (plan_level IN ('standard', 'premium', 'enterprise', 'starter', 'professional'));

-- ============================================================================
-- 2. New table: shared.refresh_tokens
-- ============================================================================
CREATE TABLE IF NOT EXISTS shared.refresh_tokens (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    user_id UUID NOT NULL REFERENCES shared.users(id) ON DELETE CASCADE,
    token_hash VARCHAR(255) UNIQUE NOT NULL,
    expires_at TIMESTAMPTZ NOT NULL,
    revoked_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user ON shared.refresh_tokens(user_id);
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_hash ON shared.refresh_tokens(token_hash);
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_expires ON shared.refresh_tokens(expires_at);

-- ============================================================================
-- 3. New table: shared.stripe_events (idempotency for webhook processing)
-- ============================================================================
CREATE TABLE IF NOT EXISTS shared.stripe_events (
    id VARCHAR(255) PRIMARY KEY,
    type VARCHAR(100) NOT NULL,
    processed_at TIMESTAMPTZ DEFAULT NOW(),
    payload JSONB
);

-- ============================================================================
-- 4. New table: shared.invite_tokens (magic link activation)
-- ============================================================================
CREATE TABLE IF NOT EXISTS shared.invite_tokens (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    organization_id UUID NOT NULL REFERENCES shared.organizations(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES shared.users(id) ON DELETE CASCADE,
    token_hash VARCHAR(255) UNIQUE NOT NULL,
    expires_at TIMESTAMPTZ NOT NULL,
    used_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_invite_tokens_hash ON shared.invite_tokens(token_hash);
CREATE INDEX IF NOT EXISTS idx_invite_tokens_user ON shared.invite_tokens(user_id);

-- ============================================================================
-- 5. New table: shared.onboarding_progress
-- ============================================================================
CREATE TABLE IF NOT EXISTS shared.onboarding_progress (
    organization_id UUID PRIMARY KEY REFERENCES shared.organizations(id) ON DELETE CASCADE,
    completed_steps TEXT[] DEFAULT '{}',
    completed_at TIMESTAMPTZ,
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- ============================================================================
-- 6. New table: shared.user_passkeys (WebAuthn)
-- ============================================================================
CREATE TABLE IF NOT EXISTS shared.user_passkeys (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    user_id UUID NOT NULL REFERENCES shared.users(id) ON DELETE CASCADE,
    credential_id TEXT UNIQUE NOT NULL,
    public_key TEXT NOT NULL,
    counter BIGINT DEFAULT 0,
    device_name VARCHAR(255),
    transports TEXT[],
    created_at TIMESTAMPTZ DEFAULT NOW(),
    last_used_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS idx_user_passkeys_user ON shared.user_passkeys(user_id);
CREATE INDEX IF NOT EXISTS idx_user_passkeys_cred ON shared.user_passkeys(credential_id);

-- ============================================================================
-- 7. Modify shared.users — add MFA/WebAuthn columns
-- ============================================================================
ALTER TABLE shared.users ADD COLUMN IF NOT EXISTS totp_verified_at TIMESTAMPTZ;
ALTER TABLE shared.users ADD COLUMN IF NOT EXISTS recovery_codes TEXT;
ALTER TABLE shared.users ADD COLUMN IF NOT EXISTS webauthn_challenge TEXT;
ALTER TABLE shared.users ADD COLUMN IF NOT EXISTS has_seen_intro BOOLEAN DEFAULT FALSE;

-- ============================================================================
-- 8. Stubbed email log table (for development — replaces real email sends)
-- ============================================================================
CREATE TABLE IF NOT EXISTS shared.email_log (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    to_email VARCHAR(255) NOT NULL,
    subject VARCHAR(500) NOT NULL,
    body TEXT,
    template VARCHAR(100),
    metadata JSONB,
    sent_at TIMESTAMPTZ DEFAULT NOW()
);
