import { supabase } from '@/integrations/supabase/client';
import type { RealtimeChannel } from '@supabase/supabase-js';

export type SignalMessage =
  | { type: 'viewer-join'; viewerId: string }
  | { type: 'viewer-leave'; viewerId: string }
  | { type: 'offer'; viewerId: string; sdp: RTCSessionDescriptionInit }
  | { type: 'answer'; viewerId: string; sdp: RTCSessionDescriptionInit }
  | { type: 'ice'; viewerId: string; from: 'broadcaster' | 'viewer'; candidate: RTCIceCandidateInit }
  | { type: 'frame'; dataUrl: string; ts: number };

const readyChannels = new WeakMap<RealtimeChannel, Promise<void>>();

export function joinSignalingChannel(
  code: string,
  onMessage: (msg: SignalMessage) => void,
): RealtimeChannel {
  let resolveReady!: () => void;
  let rejectReady!: (error: Error) => void;
  const ready = new Promise<void>((resolve, reject) => {
    resolveReady = resolve;
    rejectReady = reject;
  });

  const channel = supabase.channel(`share:${code}`, {
    config: { broadcast: { self: false, ack: false } },
  });

  readyChannels.set(channel, ready);

  channel
    .on('broadcast', { event: 'signal' }, ({ payload }) => onMessage(payload as SignalMessage))
    .subscribe((status, err) => {
      if (status === 'SUBSCRIBED') resolveReady();
      if (status === 'CHANNEL_ERROR' || status === 'TIMED_OUT' || status === 'CLOSED') {
        rejectReady(err instanceof Error ? err : new Error(`Canal de sinalização: ${status}`));
      }
    });

  return channel;
}

export async function waitForSignalingReady(channel: RealtimeChannel, timeoutMs = 5000) {
  const ready = readyChannels.get(channel);
  if (!ready) return;
  await Promise.race([
    ready,
    new Promise<void>((_, reject) => {
      window.setTimeout(() => reject(new Error('Tempo esgotado ao conectar sinalização')), timeoutMs);
    }),
  ]);
}

export async function sendSignal(channel: RealtimeChannel, msg: SignalMessage) {
  await waitForSignalingReady(channel);
  const response = await channel.send({ type: 'broadcast', event: 'signal', payload: msg });
  if (response !== 'ok') {
    const restResponse = await channel.httpSend('signal', msg);
    if (restResponse.success === false) throw new Error(restResponse.error);
  }
}

export function generateRoomCode(): string {
  const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // unambiguous
  let out = '';
  for (let i = 0; i < 6; i++) out += chars[Math.floor(Math.random() * chars.length)];
  return out;
}

export const ICE_SERVERS: RTCIceServer[] = [
  { urls: 'stun:stun.l.google.com:19302' },
  { urls: 'stun:stun1.l.google.com:19302' },
];
