/*
 * Member Portal Auth + Invitations
 * Links members to auth.users, adds invitation system
 */

-- Add user_id to members (links to Supabase Auth)
ALTER TABLE public.members ADD COLUMN IF NOT EXISTS user_id uuid REFERENCES auth.users(id) ON DELETE SET NULL;
CREATE INDEX IF NOT EXISTS ix_members_user ON public.members(user_id);

-- Member portal invitations
CREATE TABLE IF NOT EXISTS public.member_portal_invitations (
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
  member_id uuid NOT NULL REFERENCES public.members(id) ON DELETE CASCADE,
  email text NOT NULL,
  invite_token text NOT NULL DEFAULT gen_random_uuid()::text,
  status text NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','accepted','expired','revoked')),
  invited_by uuid REFERENCES auth.users(id),
  accepted_at timestamptz,
  expires_at timestamptz NOT NULL DEFAULT (now() + interval '30 days'),
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS ix_portal_invitations_token ON public.member_portal_invitations(invite_token);
CREATE INDEX IF NOT EXISTS ix_portal_invitations_member ON public.member_portal_invitations(member_id);

ALTER TABLE public.member_portal_invitations ENABLE ROW LEVEL SECURITY;
REVOKE ALL ON public.member_portal_invitations FROM authenticated, service_role;
GRANT SELECT, INSERT, UPDATE ON public.member_portal_invitations TO authenticated;
GRANT ALL ON public.member_portal_invitations TO service_role;

-- Admins can manage invitations for their account
CREATE POLICY portal_invitations_admin ON public.member_portal_invitations
  FOR ALL TO authenticated
  USING (public.has_permission(auth.uid(), account_id, 'members.write'::public.app_permissions));

-- Anon can read invitation by token (for the accept flow)
GRANT SELECT ON public.member_portal_invitations TO anon;
CREATE POLICY portal_invitations_anon_read ON public.member_portal_invitations
  FOR SELECT TO anon
  USING (status = 'pending' AND expires_at > now());

-- RLS: Members can read their own portal data
-- Allow authenticated users to read their own member record via user_id
CREATE POLICY members_portal_self_read ON public.members
  FOR SELECT TO authenticated
  USING (user_id = auth.uid());

-- Allow members to update their own contact/gdpr fields
CREATE POLICY members_portal_self_update ON public.members
  FOR UPDATE TO authenticated
  USING (user_id = auth.uid());

-- Add is_members_only flag to site_pages for member-only content
ALTER TABLE public.site_pages ADD COLUMN IF NOT EXISTS is_members_only boolean NOT NULL DEFAULT false;

-- Function: Link member to auth user after signup
CREATE OR REPLACE FUNCTION public.link_member_to_user(
  p_invite_token text,
  p_user_id uuid
) RETURNS uuid
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = ''
AS $$
DECLARE
  v_member_id uuid;
  v_account_id uuid;
BEGIN
  -- Find and validate invitation
  SELECT member_id, account_id INTO v_member_id, v_account_id
  FROM public.member_portal_invitations
  WHERE invite_token = p_invite_token
    AND status = 'pending'
    AND expires_at > now();

  IF v_member_id IS NULL THEN
    RAISE EXCEPTION 'Invalid or expired invitation';
  END IF;

  -- Link member to user
  UPDATE public.members SET user_id = p_user_id WHERE id = v_member_id;

  -- Mark invitation as accepted
  UPDATE public.member_portal_invitations
  SET status = 'accepted', accepted_at = now()
  WHERE invite_token = p_invite_token;

  RETURN v_member_id;
END;
$$;

GRANT EXECUTE ON FUNCTION public.link_member_to_user(text, uuid) TO authenticated, service_role;
