-- Fix-up for failed 20260515000002: dropping NOT NULL on a PK column requires
-- dropping the PK first. Replace the natural PK (conversation_id,
-- recipient_device_id, key_version) with a synthetic row_id and re-establish
-- uniqueness via two partial unique indexes — one per recipient mode.
--
-- Also re-runs the policies + indexes from 20260515000002 that were skipped
-- when migration 2 errored out at the ALTER COLUMN step.

alter table public.conversation_keys
  drop constraint if exists conversation_keys_pkey;

alter table public.conversation_keys
  add column if not exists row_id bigserial primary key;

alter table public.conversation_keys
  alter column recipient_device_id drop not null,
  alter column sender_device_id    drop not null;

-- Partial unique constraints: device-mode and user-mode rows can coexist for
-- the same (conv, version) but each mode is unique on its own.
create unique index if not exists conversation_keys_device_recipient_uniq
  on public.conversation_keys(conversation_id, recipient_device_id, key_version)
  where recipient_device_id is not null;

create unique index if not exists conversation_keys_user_recipient_uniq
  on public.conversation_keys(conversation_id, recipient_user_id, key_version)
  where recipient_user_id is not null;

create index if not exists conversation_keys_recipient_user_idx
  on public.conversation_keys(recipient_user_id);

-- Re-apply the policies from migration 20260515000002 (those didn't run
-- because the failing ALTER stopped the file).
drop policy if exists conversation_keys_select_owner on public.conversation_keys;
create policy conversation_keys_select_owner
  on public.conversation_keys
  for select
  to authenticated
  using (
    recipient_user_id = auth.uid()
    or exists (
      select 1
        from public.devices d
       where d.id = recipient_device_id
         and d.user_id = auth.uid()
    )
  );

drop policy if exists conversation_keys_insert_member on public.conversation_keys;
create policy conversation_keys_insert_member
  on public.conversation_keys
  for insert
  to authenticated
  with check (
    exists (
      select 1
        from public.conversation_members m
       where m.conversation_id = conversation_keys.conversation_id
         and m.user_id = auth.uid()
         and m.accepted = true
    )
    and (
      sender_user_id = auth.uid()
      or exists (
        select 1
          from public.devices d
         where d.id = sender_device_id
           and d.user_id = auth.uid()
      )
    )
    and (
      (recipient_user_id is not null and exists (
        select 1
          from public.conversation_members m
         where m.conversation_id = conversation_keys.conversation_id
           and m.user_id = recipient_user_id
           and m.accepted = true
      ))
      or (recipient_device_id is not null and exists (
        select 1
          from public.devices d
          join public.conversation_members m
            on m.user_id = d.user_id
           and m.conversation_id = conversation_keys.conversation_id
         where d.id = recipient_device_id
           and m.accepted = true
      ))
    )
  );
