-- Phase 3: per-device revocation. Adds a revoked_at flag, an RPC that lets
-- the device's owner flip it, and publishes the devices table to realtime
-- so every signed-in install can react to its own row being revoked.

alter table public.devices
  add column if not exists revoked_at timestamptz null;

create index if not exists devices_user_revoked_idx
  on public.devices(user_id, revoked_at);

-- RLS: existing policy on devices already gates by user_id; an UPDATE done
-- via the RPC runs with SECURITY DEFINER so we don't widen the RLS surface.

create or replace function public.revoke_device(p_device_id uuid)
returns void
language plpgsql
security definer
set search_path = public
as $$
declare
  v_owner uuid;
begin
  if auth.uid() is null then
    raise exception 'not authenticated' using errcode = '28000';
  end if;

  select user_id into v_owner
    from public.devices
    where id = p_device_id;

  if v_owner is null then
    raise exception 'device not found' using errcode = 'P0002';
  end if;

  if v_owner <> auth.uid() then
    raise exception 'not authorized' using errcode = '42501';
  end if;

  update public.devices
    set revoked_at = now()
    where id = p_device_id
      and revoked_at is null;
end;
$$;

revoke all on function public.revoke_device(uuid) from public;
grant execute on function public.revoke_device(uuid) to authenticated;

-- Replica identity full so UPDATE events deliver the full new row (including
-- revoked_at) to subscribers; default REPLICA IDENTITY DEFAULT only sends
-- the primary key columns, which would force a refetch on every event.
alter table public.devices replica identity full;

-- Add devices to the supabase_realtime publication if not already present.
do $$
begin
  if not exists (
    select 1
      from pg_publication_tables
      where pubname = 'supabase_realtime'
        and schemaname = 'public'
        and tablename = 'devices'
  ) then
    execute 'alter publication supabase_realtime add table public.devices';
  end if;
end
$$;
