-- Random Video Chat schema
-- Tables: waiting_users (queue), rooms (active sessions)
-- RPC: match_user(p_user_id) - atomically pairs waiting users

create extension if not exists "pgcrypto";

create table if not exists public.waiting_users (
  user_id   uuid primary key,
  created_at timestamptz not null default now()
);

create index if not exists idx_waiting_users_created_at
  on public.waiting_users (created_at);

create table if not exists public.rooms (
  id         uuid primary key default gen_random_uuid(),
  user_a     uuid not null,  -- the waiter (offerer)
  user_b     uuid not null,  -- the joiner (answerer)
  created_at timestamptz not null default now()
);

create index if not exists idx_rooms_user_a on public.rooms (user_a);
create index if not exists idx_rooms_user_b on public.rooms (user_b);

-- Atomically match a user. If a waiter exists, pair them and create a room.
-- Otherwise, enqueue the user.
create or replace function public.match_user(p_user_id uuid)
returns table(status text, room_id uuid, partner_id uuid, role text)
language plpgsql
as $$
declare
  v_partner uuid;
  v_room_id uuid;
begin
  -- Find the oldest waiter that isn't us, locking the row so no one else can grab it
  select user_id into v_partner
  from public.waiting_users
  where user_id <> p_user_id
  order by created_at asc
  for update skip locked
  limit 1;

  if v_partner is null then
    -- Nobody waiting: enqueue us (refresh timestamp if already present)
    insert into public.waiting_users (user_id) values (p_user_id)
    on conflict (user_id) do update set created_at = now();
    return query select 'waiting'::text, null::uuid, null::uuid, null::text;
  else
    -- Pair up
    delete from public.waiting_users where user_id in (v_partner, p_user_id);
    insert into public.rooms (user_a, user_b)
    values (v_partner, p_user_id)
    returning id into v_room_id;

    -- The caller (p_user_id) is the answerer; the waiter is the offerer
    return query select 'matched'::text, v_room_id, v_partner, 'answer'::text;
  end if;
end;
$$;

-- Check if a waiting user has been picked up into a room (polled by the waiter)
create or replace function public.check_match(p_user_id uuid)
returns table(status text, room_id uuid, partner_id uuid, role text)
language plpgsql
as $$
declare
  v_room_id uuid;
  v_partner uuid;
begin
  select id, user_b into v_room_id, v_partner
  from public.rooms
  where user_a = p_user_id
  order by created_at desc
  limit 1;

  if v_room_id is null then
    -- also check user_b side (shouldn't happen for waiters, but safe)
    select id, user_a into v_room_id, v_partner
    from public.rooms
    where user_b = p_user_id
    order by created_at desc
    limit 1;
    if v_room_id is null then
      return query select 'waiting'::text, null::uuid, null::uuid, null::text;
      return;
    end if;
    return query select 'matched'::text, v_room_id, v_partner, 'answer'::text;
  else
    return query select 'matched'::text, v_room_id, v_partner, 'offer'::text;
  end if;
end;
$$;

-- Clean up a user's presence: remove from queue + delete any rooms they're in
create or replace function public.leave_session(p_user_id uuid)
returns void
language plpgsql
as $$
begin
  delete from public.waiting_users where user_id = p_user_id;
  delete from public.rooms where user_a = p_user_id or user_b = p_user_id;
end;
$$;

-- Periodic cleanup helper (optional - removes stale queue entries > 2 min old)
create or replace function public.cleanup_stale()
returns void
language plpgsql
as $$
begin
  delete from public.waiting_users where created_at < now() - interval '2 minutes';
  delete from public.rooms where created_at < now() - interval '30 minutes';
end;
$$;
