import { useEffect, useState } from 'react';

import { supabase } from './supabase';

// Watches the `call-presence:<conversationId>` realtime channel and returns
// the set of userIds currently in that call. Independent of whether the
// viewer is in the room — used to show "Active call · Join" affordances.
//
// Supabase realtime 2.103+ dedupes channels by topic: calling
// `supabase.channel(topic)` returns an existing channel if one already exists.
// That means an observer can't safely register `.on('presence', ...)` because
// the tracker (CallContext) may have already subscribed it. We side-step this
// by polling `presenceState()` on the (shared or fresh) channel.
export function useCallPresence(conversationId: string | undefined): string[] {
  const [activeUserIds, setActiveUserIds] = useState<string[]>([]);

  useEffect(() => {
    if (!conversationId) {
      setActiveUserIds([]);
      return;
    }

    const channel = supabase.channel('call-presence:' + conversationId, {
      config: {
        presence: {
          key: 'observer-' + Math.random().toString(36).slice(2, 8),
          // Supabase realtime only sends presence_state/diff events to a
          // channel that has presence enabled. Without `enabled: true` (and
          // no `.on('presence', ...)` bindings) the server treats the channel
          // as non-presence and `presenceState()` never populates.
          enabled: true,
        },
      },
    });

    // If Supabase returned a fresh (closed) channel, we own it and must
    // subscribe/remove it. If it returned an already-subscribed channel
    // (tracker owns it), we just read state.
    const ownsChannel = channel.state === 'closed';
    if (ownsChannel) {
      void channel.subscribe();
    }

    const resync = () => {
      const state = channel.presenceState() as Record<string, Array<Record<string, unknown>>>;
      const ids = new Set<string>();
      for (const list of Object.values(state)) {
        for (const entry of list) {
          const uid = entry?.userId;
          if (typeof uid === 'string') ids.add(uid);
        }
      }
      setActiveUserIds((prev) => {
        const next = Array.from(ids).sort();
        if (prev.length === next.length && prev.every((v, i) => v === next[i])) return prev;
        return next;
      });
    };

    resync();
    const pollId = window.setInterval(resync, 1500);

    return () => {
      window.clearInterval(pollId);
      if (ownsChannel) {
        void supabase.removeChannel(channel);
      }
    };
  }, [conversationId]);

  return activeUserIds;
}
