;(function () {
  const VCAM_DEV_ID = 'livecam-vcam-video';
  const VCAM_MIC_ID = 'livecam-vcam-audio';

  let config = {
    enabled: true,
    videoUrl: '',
    loop: true,
    loopIntervalSec: 0,
    clockEnabled: false
  };

  let vEl = null;
  let curStream = null;
  let audioCtx = null;
  let mediaSrcNode = null;
  let keepAliveGain = null;
  let wakeLock = null;
  let deveTocar = false;

  async function ensureWakeLock() {
    try {
      if (!config.enabled || !config.videoUrl) return;
      if (wakeLock && !wakeLock.released) return;
      if (navigator.wakeLock && document.visibilityState === 'visible') {
        wakeLock = await navigator.wakeLock.request('screen');
      }
    } catch (_) {}
  }
  document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'visible') ensureWakeLock();
  });

  window.addEventListener('message', (ev) => {
    if (ev.source !== window || !ev.data || !ev.data.__livecam_vcam) return;
    const { cmd, payload } = ev.data;

    if (cmd === 'UPDATE_CONFIG') {
      const rebuild = payload.videoUrl !== config.videoUrl;
      config = { ...config, ...payload };
      if (config.enabled && config.videoUrl) {
        ensureVideo(rebuild);
      } else {
        teardown();
      }
    } else if (cmd === 'RESTART_VIDEO') {
      deveTocar = true;
      if (vEl) {
         vEl.currentTime = 0;
         vEl.play().catch(()=>{});
      }
    } else if (cmd === 'PLAY') {
      deveTocar = true;
      if (vEl) vEl.play().catch(() => {});
    } else if (cmd === 'PAUSE') {
      deveTocar = false;
      if (vEl) vEl.pause();
    }
  });

  function ensureVideo(rebuild) {
    if (vEl && !rebuild) { 
      vEl.loop = config.loop && (!config.loopIntervalSec || config.loopIntervalSec <= 0);
      return; 
    }
    teardown();
    vEl = document.createElement('video');
    vEl.id = 'livecam_vcam_source';
    vEl.src = config.videoUrl;
    vEl.loop = config.loop && (!config.loopIntervalSec || config.loopIntervalSec <= 0);
    vEl.autoplay = false; 
    vEl.playsInline = true;
    vEl.setAttribute('playsinline', '');
    // ANTI-THROTTLE CSS:
    vEl.style.cssText = 'position:fixed;left:0;bottom:0;width:80px;height:80px;opacity:0.06;pointer-events:none;z-index:-2147483647;';
    (document.documentElement || document.body).appendChild(vEl);

    const start = () => { buildCurStream(); };
    if (vEl.readyState >= 2) start();
    else vEl.addEventListener('loadeddata', start, { once: true });

    vEl.onended = () => {
      window.postMessage({ __livecam_vcam_event: 'ended' }, '*');
      if (!config.loop) return;
      const intervalMs = (config.loopIntervalSec || 0) * 1000;
      if (intervalMs > 0) {
        setTimeout(() => {
          if (vEl) vEl.play().catch(() => {});
        }, intervalMs);
      } else {
        if (vEl) vEl.play().catch(() => {});
      }
    };

    vEl.ontimeupdate = () => {
      if (vEl.duration && vEl.currentTime >= vEl.duration - 0.2) {
         if (!vEl._hasEndedEventFired) {
            vEl._hasEndedEventFired = true;
            window.postMessage({ __livecam_vcam_event: 'ended' }, '*');
         }
      } else if (vEl.currentTime < vEl.duration - 1) {
         vEl._hasEndedEventFired = false;
      }
    };
  }

  function buildCurStream() {
    if (!vEl) return;
    const out = new MediaStream();
    
    if (config.clockEnabled) {
      if (!window.__livecam_canvas) {
        window.__livecam_canvas = document.createElement('canvas');
        window.__livecam_ctx = window.__livecam_canvas.getContext('2d');
      }
      const cvs = window.__livecam_canvas;
      const ctx = window.__livecam_ctx;
      
      // Definição estática inicial (será ajustada no requestAnimationFrame)
      cvs.width = vEl.videoWidth || 1280;
      cvs.height = vEl.videoHeight || 720;
      
      let renderLoop = true;
      function drawFrame() {
        if (!renderLoop || !vEl || vEl.paused || vEl.ended) {
          if (renderLoop) requestAnimationFrame(drawFrame);
          return;
        }
        
        if (cvs.width !== vEl.videoWidth && vEl.videoWidth > 0) {
          cvs.width = vEl.videoWidth;
          cvs.height = vEl.videoHeight;
        }
        
        // Desenha o vídeo
        ctx.drawImage(vEl, 0, 0, cvs.width, cvs.height);
        
        // Desenha o Relógio
        const now = new Date();
        const timeStr = now.toLocaleTimeString('pt-BR');
        
        ctx.save();
        const fontSize = Math.max(32, Math.floor(cvs.height * 0.05));
        ctx.font = `bold ${fontSize}px Arial, sans-serif`;
        
        // Fundo semi-transparente para dar contraste
        const padding = 10;
        const textWidth = ctx.measureText(timeStr).width;
        ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
        ctx.fillRect(cvs.width - textWidth - (padding*3), padding, textWidth + (padding*2), fontSize + padding);
        
        // Texto branco
        ctx.fillStyle = '#FFFFFF';
        ctx.textAlign = 'right';
        ctx.textBaseline = 'top';
        ctx.fillText(timeStr, cvs.width - (padding*2), padding*1.5);
        ctx.restore();
        
        requestAnimationFrame(drawFrame);
      }
      
      // Inicia o loop
      vEl.addEventListener('play', () => { renderLoop = true; drawFrame(); }, { once: false });
      if (!vEl.paused) drawFrame();
      
      const csCanvas = cvs.captureStream(30);
      csCanvas.getVideoTracks().forEach(t => out.addTrack(t));
      
      // Limpeza do loop anterior
      if (window.__livecam_render_cleanup) window.__livecam_render_cleanup();
      window.__livecam_render_cleanup = () => { renderLoop = false; };
      
    } else {
      let cs = null;
      try { cs = vEl.captureStream ? vEl.captureStream() : (vEl.mozCaptureStream ? vEl.mozCaptureStream() : null); } catch (_) {}
      if (cs) cs.getVideoTracks().forEach((t) => out.addTrack(t));
    }

    let gotAudio = false;
    try {
      if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();
      if (!mediaSrcNode) mediaSrcNode = audioCtx.createMediaElementSource(vEl);
      const dest = audioCtx.createMediaStreamDestination();
      mediaSrcNode.connect(dest);
      
      // tap ANTI-THROTTLE
      if (!keepAliveGain) {
        keepAliveGain = audioCtx.createGain();
        keepAliveGain.gain.value = 0.0006;
        keepAliveGain.connect(audioCtx.destination);
      }
      if (!mediaSrcNode.__alsKeepAlive) { mediaSrcNode.connect(keepAliveGain); mediaSrcNode.__alsKeepAlive = true; }
      dest.stream.getAudioTracks().forEach((t) => { out.addTrack(t); gotAudio = true; });
    } catch (_) {}
    ensureWakeLock();
    
    // fallback para áudio nativo se WebAudio falhar (não funciona bem com canvas)
    if (!gotAudio && !config.clockEnabled) {
      let cs = null;
      try { cs = vEl.captureStream ? vEl.captureStream() : null; } catch (_) {}
      if (cs) cs.getAudioTracks().forEach((t) => out.addTrack(t)); 
    }
    
    curStream = out;
  }

  function teardown() {
    if (window.__livecam_render_cleanup) window.__livecam_render_cleanup();
    if (vEl) { try { vEl.pause(); vEl.removeAttribute('src'); vEl.load(); vEl.remove(); } catch (_) {} vEl = null; }
    try { if (mediaSrcNode) mediaSrcNode.disconnect(); } catch (_) {}
    mediaSrcNode = null;
    curStream = null;
    try { if (wakeLock) { wakeLock.release(); } } catch (_) {}
    wakeLock = null;
  }

  // WATCHDOG anti-travamento (1.0s)
  let wLastCt = -1, wLastAt = 0;
  setInterval(() => {
    try { reporFaixasMortas(); } catch (_) {}
    try { if (audioCtx && audioCtx.state !== 'running' && curStream) audioCtx.resume(); } catch (_) {}
    try { if (curStream) ensureWakeLock(); } catch (_) {}
    if (!vEl) { wLastCt = -1; return; }
    if (deveTocar && vEl.paused && !vEl.ended) { try { vEl.play().catch(() => {}); } catch (_) {} }
    if (vEl.paused) { wLastCt = -1; return; }
    const ct = vEl.currentTime, now = Date.now();
    if (ct === wLastCt) {
      if (wLastAt && now - wLastAt > 2000) { try { vEl.play().catch(() => {}); } catch (_) {} wLastAt = now; }
    } else { wLastCt = ct; wLastAt = now; }
  }, 1000);

  // FAIXAS CLONADAS + AUTO-REPARO
  const nossasFaixas = new WeakSet();
  const streamsEntregues = new Set();
  function novaFaixa(kind) {
    if (!curStream) return null;
    const src = (kind === 'video' ? curStream.getVideoTracks() : curStream.getAudioTracks())[0];
    if (!src) return null;
    let t = src;
    try { t = src.clone(); } catch (_) { t = src; }
    nossasFaixas.add(t);
    return t;
  }
  function reporFaixasMortas() {
    if (!curStream || !streamsEntregues.size) return;
    for (const s of streamsEntregues) {
      let vivo = false;
      for (const kind of ['video', 'audio']) {
        const atuais = kind === 'video' ? s.getVideoTracks() : s.getAudioTracks();
        const mortas = atuais.filter((t) => nossasFaixas.has(t) && t.readyState === 'ended');
        if (atuais.some((t) => t.readyState === 'live')) vivo = true;
        if (!mortas.length) continue;
        mortas.forEach((t) => { try { s.removeTrack(t); } catch (_) {} });
        const nova = novaFaixa(kind);
        if (nova) { try { s.addTrack(nova); vivo = true; } catch (_) {} }
      }
      if (!vivo) streamsEntregues.delete(s);
    }
  }

  function buildStream(constraints) {
    const out = new MediaStream();
    if (!curStream) return out;
    const querVideo = !!(constraints && constraints.video);
    const querAudio = !!(constraints && constraints.audio);
    if (querVideo) { const t = novaFaixa('video'); if (t) out.addTrack(t); }
    if (querAudio) { const t = novaFaixa('audio'); if (t) out.addTrack(t); }
    if (out.getTracks().length) streamsEntregues.add(out);
    return out;
  }

  function esperaStream(ms) {
    return new Promise((resolve) => {
      const t0 = Date.now();
      (function tick() {
        if (curStream || Date.now() - t0 > ms) return resolve(!!curStream);
        setTimeout(tick, 100);
      })();
    });
  }

  const md = navigator.mediaDevices;
  if (md && md.getUserMedia) {
    const origGUM = md.getUserMedia.bind(md);

    const wrapped = async function (constraints) {
      let isOurVideo = false;
      let isOurAudio = false;

      if (constraints && constraints.video) {
        if (constraints.video === true) isOurVideo = config.enabled;
        else if (constraints.video.deviceId) {
          const id = constraints.video.deviceId.exact || constraints.video.deviceId;
          if (id === VCAM_DEV_ID) isOurVideo = true;
        } else isOurVideo = config.enabled;
      }
      
      if (constraints && constraints.audio) {
        if (constraints.audio === true) isOurAudio = config.enabled;
        else if (constraints.audio.deviceId) {
          const id = constraints.audio.deviceId.exact || constraints.audio.deviceId;
          if (id === VCAM_MIC_ID) isOurAudio = true;
        } else isOurAudio = config.enabled;
      }

      if (config.enabled && config.videoUrl && (isOurVideo || isOurAudio)) {
         try { if (audioCtx && audioCtx.state === 'suspended') audioCtx.resume(); } catch (_) {}
         if (vEl && vEl.paused) { try { vEl.play().catch(() => {}); } catch (_) {} }
         ensureWakeLock();
         if (!curStream) { try { ensureVideo(false); } catch (_) {} await esperaStream(3000); }
         const s = buildStream(constraints);
         if (s.getTracks().length) return s;
      }

      // Remover deviceId fake se caiu aqui
      let cleanConstraints = constraints;
      try {
        cleanConstraints = JSON.parse(JSON.stringify(constraints || {}));
        for (const k of ['video', 'audio']) {
          if (cleanConstraints[k] && cleanConstraints[k].deviceId) {
             const id = cleanConstraints[k].deviceId.exact || cleanConstraints[k].deviceId;
             if (id === VCAM_DEV_ID || id === VCAM_MIC_ID) {
                delete cleanConstraints[k].deviceId;
                if (!Object.keys(cleanConstraints[k]).length) cleanConstraints[k] = true;
             }
          }
        }
      } catch(e) {}

      return origGUM(cleanConstraints);
    };

    try { md.getUserMedia = wrapped; }
    catch (_) { try { Object.defineProperty(md, 'getUserMedia', { value: wrapped, configurable: true, writable: true }); } catch (__) {} }

    if (md.enumerateDevices) {
      const origEnum = md.enumerateDevices.bind(md);

      const fakeDev = (deviceId, kind, label) => ({
        deviceId, kind, label, groupId: 'livecam',
        toJSON() { return { deviceId, kind, label, groupId: 'livecam' }; },
        getCapabilities() {
          if (kind !== 'videoinput') return { deviceId, groupId: 'livecam' };
          const w = (vEl && vEl.videoWidth) ? vEl.videoWidth : 1080;
          const h = (vEl && vEl.videoHeight) ? vEl.videoHeight : 1920;
          return { deviceId, groupId: 'livecam', facingMode: [], width: { min: 1, max: w }, height: { min: 1, max: h }, frameRate: { min: 1, max: 30 } };
        },
        getSettings() { return { deviceId, groupId: 'livecam' }; },
      });

      const wrappedEnum = function () {
        return origEnum().then((lista) => {
          try {
            if (!config.enabled || !config.videoUrl) return lista;
            const reais = (Array.isArray(lista) ? lista : []).filter((d) => d && d.deviceId !== VCAM_DEV_ID && d.deviceId !== VCAM_MIC_ID);
            
            const nossos = [fakeDev(VCAM_DEV_ID, 'videoinput', 'LiveCam Pro — câmera virtual')];
            if (curStream && curStream.getAudioTracks().length) {
              nossos.push(fakeDev(VCAM_MIC_ID, 'audioinput', 'LiveCam Pro — microfone virtual'));
            }
            return nossos.concat(reais);
          } catch (_) { return lista; }
        }).catch((e) => {
          if (config.enabled && config.videoUrl) {
            return [
              fakeDev(VCAM_DEV_ID, 'videoinput', 'LiveCam Pro — câmera virtual'),
              fakeDev(VCAM_MIC_ID, 'audioinput', 'LiveCam Pro — microfone virtual')
            ];
          }
          throw e;
        });
      };
      
      try { md.enumerateDevices = wrappedEnum; }
      catch (_) { try { Object.defineProperty(md, 'enumerateDevices', { value: wrappedEnum, configurable: true, writable: true }); } catch (__) {} }
    }
  }

  // Mock Permissions API
  if (navigator.permissions && navigator.permissions.query) {
    const originalQuery = navigator.permissions.query.bind(navigator.permissions);
    navigator.permissions.query = async function (descriptor) {
      if (descriptor && (descriptor.name === 'camera' || descriptor.name === 'microphone')) {
        return { state: 'granted', status: 'granted', onchange: null };
      }
      return originalQuery(descriptor);
    };
  }

  document.addEventListener('click', () => {
    if (audioContext && audioContext.state === 'suspended') {
      audioContext.resume().catch(() => {});
    }
    if (vEl && deveTocar && vEl.paused) {
      vEl.play().catch(() => {});
    }
  });

})();