-- ============================================================
-- Migration: user_roles_permissions + contributor_invitations
-- Timestamp: 20260321090000
-- ============================================================

-- 1. Add role column to user_profiles
ALTER TABLE public.user_profiles
ADD COLUMN IF NOT EXISTS role TEXT NOT NULL DEFAULT 'reader';

ALTER TABLE public.user_profiles
ADD COLUMN IF NOT EXISTS is_active BOOLEAN NOT NULL DEFAULT true;

-- 2. contributor_invitations table
CREATE TABLE IF NOT EXISTS public.contributor_invitations (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT NOT NULL,
  invited_by UUID REFERENCES public.user_profiles(id) ON DELETE SET NULL,
  role TEXT NOT NULL DEFAULT 'contributor',
  token TEXT NOT NULL UNIQUE,
  status TEXT NOT NULL DEFAULT 'pending',
  message TEXT,
  expires_at TIMESTAMPTZ NOT NULL DEFAULT (CURRENT_TIMESTAMP + INTERVAL '7 days'),
  accepted_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_contributor_invitations_email ON public.contributor_invitations(email);
CREATE INDEX IF NOT EXISTS idx_contributor_invitations_token ON public.contributor_invitations(token);
CREATE INDEX IF NOT EXISTS idx_contributor_invitations_status ON public.contributor_invitations(status);

-- 3. Functions (BEFORE RLS policies)
CREATE OR REPLACE FUNCTION public.is_admin_user()
RETURNS BOOLEAN
LANGUAGE sql
STABLE
SECURITY DEFINER
AS $$
SELECT EXISTS (
  SELECT 1 FROM auth.users au
  WHERE au.id = auth.uid()
  AND (
    au.raw_user_meta_data->>'role' = 'admin'
    OR au.raw_app_meta_data->>'role' = 'admin'
  )
)
$$;

CREATE OR REPLACE FUNCTION public.get_user_role()
RETURNS TEXT
LANGUAGE sql
STABLE
SECURITY DEFINER
AS $$
SELECT COALESCE(
  (SELECT role FROM public.user_profiles WHERE id = auth.uid() LIMIT 1),
  'reader'
)
$$;

-- 4. Enable RLS
ALTER TABLE public.contributor_invitations ENABLE ROW LEVEL SECURITY;

-- 5. RLS Policies for contributor_invitations
DROP POLICY IF EXISTS "admin_manage_invitations" ON public.contributor_invitations;
CREATE POLICY "admin_manage_invitations"
ON public.contributor_invitations
FOR ALL
TO authenticated
USING (public.is_admin_user())
WITH CHECK (public.is_admin_user());

DROP POLICY IF EXISTS "public_read_own_invitation_by_token" ON public.contributor_invitations;
CREATE POLICY "public_read_own_invitation_by_token"
ON public.contributor_invitations
FOR SELECT
TO public
USING (true);

-- 6. RLS Policies for user_profiles (admin can manage all)
DROP POLICY IF EXISTS "admin_manage_all_user_profiles" ON public.user_profiles;
CREATE POLICY "admin_manage_all_user_profiles"
ON public.user_profiles
FOR ALL
TO authenticated
USING (public.is_admin_user())
WITH CHECK (public.is_admin_user());

-- 7. Trigger for updated_at on invitations
DROP TRIGGER IF EXISTS update_contributor_invitations_updated_at ON public.contributor_invitations;
CREATE TRIGGER update_contributor_invitations_updated_at
  BEFORE UPDATE ON public.contributor_invitations
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at();
