/** AURA FARMING — Etapa 6: transmissão P2P do jogador */
(() => {
  'use strict';
  const root = document.querySelector('#farm-game');
  if (!root) return;
  const baseUrl = document.querySelector('meta[name="app-base-url"]')?.content || '';
  const csrf = document.querySelector('meta[name="csrf-token"]')?.content || '';
  const token = root.dataset.publicToken || '';
  const webrtcEnabled = root.dataset.webrtc !== '0';
  if (!token || !webrtcEnabled) return;
  const peers = new Map();
  const pendingIce = new Map();
  let localStream = null;
  let pollTimer = null;
  let stopped = false;
  let iceServers = [];
  try { iceServers = JSON.parse(root.dataset.iceServers || '[]'); } catch (_) { iceServers = []; }
  const maxViewers = Number(root.dataset.maxViewers || 8);

  async function request(url, options = {}) {
    const response = await fetch(url, { credentials: 'same-origin', ...options });
    const data = await response.json().catch(() => ({}));
    if (!response.ok || !data.ok) throw new Error(data.erro || 'Falha de sinalização.');
    return data;
  }
  async function send(tipo, payload, destinatarioId) {
    if (stopped) return;
    return request(`${baseUrl}/api/v1/live/signal.php`, {
      method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf },
      body: JSON.stringify({ s: token, tipo, payload, destinatario_id: destinatarioId }),
    });
  }
  function closePeer(id) {
    const pc = peers.get(id);
    if (pc) pc.close();
    peers.delete(id); pendingIce.delete(id);
  }
  async function ensurePeer(viewerId) {
    if (peers.has(viewerId)) return peers.get(viewerId);
    if (peers.size >= maxViewers) throw new Error('Limite de espectadores P2P atingido.');
    const pc = new RTCPeerConnection({ iceServers });
    localStream.getVideoTracks().forEach(track => pc.addTrack(track, localStream));
    pc.onicecandidate = event => {
      if (event.candidate) send('ice', event.candidate.toJSON ? event.candidate.toJSON() : event.candidate, viewerId).catch(console.warn);
    };
    pc.onconnectionstatechange = () => {
      if (['failed', 'closed'].includes(pc.connectionState)) closePeer(viewerId);
    };
    peers.set(viewerId, pc);
    pendingIce.set(viewerId, []);
    return pc;
  }
  async function flushIce(viewerId, pc) {
    const queue = pendingIce.get(viewerId) || [];
    while (queue.length) await pc.addIceCandidate(queue.shift()).catch(() => {});
  }
  async function handleSignal(signal) {
    const viewerId = Number(signal.remetente_id || 0);
    if (!viewerId) return;
    if (signal.tipo === 'offer') {
      const pc = await ensurePeer(viewerId);
      await pc.setRemoteDescription(signal.payload);
      await flushIce(viewerId, pc);
      const answer = await pc.createAnswer();
      await pc.setLocalDescription(answer);
      await send('answer', { type: answer.type, sdp: answer.sdp }, viewerId);
    } else if (signal.tipo === 'ice') {
      const pc = await ensurePeer(viewerId);
      if (pc.remoteDescription) await pc.addIceCandidate(signal.payload).catch(() => {});
      else pendingIce.get(viewerId).push(signal.payload);
    } else if (signal.tipo === 'bye') closePeer(viewerId);
  }
  async function poll() {
    if (stopped || !localStream) return;
    try {
      const data = await request(`${baseUrl}/api/v1/live/signal.php?s=${encodeURIComponent(token)}`);
      for (const signal of data.sinais || []) await handleSignal(signal);
    } catch (error) { console.warn('Transmissão P2P', error); }
  }
  function start(stream) {
    if (localStream || stopped) return;
    localStream = stream;
    poll();
    pollTimer = window.setInterval(poll, 800);
  }
  function stop() {
    if (stopped) return;
    for (const [viewerId] of peers) send('bye', {}, viewerId).catch(() => {});
    stopped = true;
    clearInterval(pollTimer);
    peers.forEach(pc => pc.close()); peers.clear();
  }
  window.addEventListener('aura:camera-ready', event => start(event.detail?.stream));
  window.addEventListener('pagehide', stop);
})();
