ALTER TABLE public.portal_function_visibility
ADD COLUMN IF NOT EXISTS association_id UUID REFERENCES public.associations(id) ON DELETE CASCADE;

DROP INDEX IF EXISTS idx_portal_function_visibility_unique_scope;

CREATE UNIQUE INDEX IF NOT EXISTS idx_portal_function_visibility_unique_scope
ON public.portal_function_visibility (
  portal,
  function_key,
  COALESCE(association_id, '00000000-0000-0000-0000-000000000000'::uuid),
  COALESCE(owner_user_id, '00000000-0000-0000-0000-000000000000'::uuid)
);

CREATE INDEX IF NOT EXISTS idx_portal_function_visibility_association_id
ON public.portal_function_visibility (association_id);

CREATE OR REPLACE FUNCTION public.can_view_portal_function(
  _portal text,
  _function_key text,
  _user_id uuid DEFAULT auth.uid(),
  _association_id uuid DEFAULT NULL
)
RETURNS boolean
LANGUAGE sql
STABLE SECURITY DEFINER
SET search_path TO 'public'
AS $function$
  SELECT COALESCE((
    SELECT pfv.enabled
    FROM public.portal_function_visibility pfv
    WHERE pfv.portal = _portal
      AND pfv.function_key = _function_key
      AND (pfv.owner_user_id = _user_id OR pfv.owner_user_id IS NULL)
      AND (pfv.association_id = _association_id OR pfv.association_id IS NULL)
    ORDER BY
      (pfv.owner_user_id = _user_id) DESC,
      (pfv.association_id = _association_id) DESC
    LIMIT 1
  ), true)
$function$;