-- Fix infinite recursion in members RLS.
--
-- The original "Admins can read all members" and "Admins can manage all members"
-- policies check role by querying members itself, which causes infinite recursion
-- when any authenticated user accesses the members table.
--
-- Solution: SECURITY DEFINER helper functions that bypass RLS to check the caller's
-- role, then reference those functions from the policies.

create or replace function public.current_user_role()
  returns text
  language sql
  security definer
  stable
  set search_path = public
as $$
  select role from public.members where user_id = auth.uid() limit 1;
$$;

create or replace function public.current_user_has_role(roles text[])
  returns boolean
  language sql
  security definer
  stable
  set search_path = public
as $$
  select exists (
    select 1 from public.members
    where user_id = auth.uid() and role = any(roles)
  );
$$;

-- Drop the recursive policies on members
drop policy if exists "Admins can read all members" on public.members;
drop policy if exists "Admins can manage all members" on public.members;

-- Replace with non-recursive equivalents using the SECURITY DEFINER helper
create policy "Admins can read all members" on public.members
  for select using (public.current_user_has_role(array['admin', 'boatswain', 'instructor']));

create policy "Admins can manage all members" on public.members
  for all using (public.current_user_has_role(array['admin']));

-- Also fix all other tables that query members inline (same recursion risk)
drop policy if exists "Admins can manage boats" on public.boats;
create policy "Admins can manage boats" on public.boats
  for all using (public.current_user_has_role(array['admin', 'boatswain']));

drop policy if exists "Admins can manage interval templates" on public.interval_templates;
create policy "Admins can manage interval templates" on public.interval_templates
  for all using (public.current_user_has_role(array['admin', 'boatswain']));

drop policy if exists "Admins can manage intervals" on public.intervals;
create policy "Admins can manage intervals" on public.intervals
  for all using (public.current_user_has_role(array['admin', 'boatswain']));

drop policy if exists "Admins can read all reservations" on public.reservations;
create policy "Admins can read all reservations" on public.reservations
  for select using (public.current_user_has_role(array['admin', 'boatswain']));

drop policy if exists "Admins can manage all reservations" on public.reservations;
create policy "Admins can manage all reservations" on public.reservations
  for all using (public.current_user_has_role(array['admin', 'boatswain']));

drop policy if exists "Admins can manage reference docs" on public.reference_docs;
create policy "Admins can manage reference docs" on public.reference_docs
  for all using (public.current_user_has_role(array['admin']));

-- booking_config and holidays policies (added in later migration, same pattern)
drop policy if exists "Admins can manage booking config" on public.booking_config;
create policy "Admins can manage booking config" on public.booking_config
  for all using (public.current_user_has_role(array['admin']));

drop policy if exists "Admins can manage holidays" on public.holidays;
create policy "Admins can manage holidays" on public.holidays
  for all using (public.current_user_has_role(array['admin']));
