// Coletor Mobile PWA
(function(){
  const el = {
    stUrl: document.getElementById('stUrl'),
    stDev: document.getElementById('stDev'),
    stSync: document.getElementById('stSync'),
    scanStatus: document.getElementById('scanStatus'),
    btnEnableCam: document.getElementById('btnEnableCam'),
    btnScanPair: document.getElementById('btnScanPair'),
    pairString: document.getElementById('pairString'),
    btnApplyPair: document.getElementById('btnApplyPair'),
    btnTestPing: document.getElementById('btnTestPing'),
    camera: document.getElementById('camera'),
    modes: document.querySelectorAll('#modes [data-mode]'),
    sections: {
      inv: document.getElementById('inventory'),
      rec: document.getElementById('receiving'),
      ship: document.getElementById('shipping'),
    },
    inv: {
      product: document.getElementById('invProduct'),
      bin: document.getElementById('invBin'),
      qty: document.getElementById('invQty'),
      scan: document.getElementById('invScan'),
      submit: document.getElementById('invSubmit'),
      list: document.getElementById('queueInv'),
    },
    rec: {
      product: document.getElementById('recProduct'),
      qty: document.getElementById('recQty'),
      origin: document.getElementById('recOrigin'),
      scan: document.getElementById('recScan'),
      submit: document.getElementById('recSubmit'),
      list: document.getElementById('queueRec'),
    },
    ship: {
      product: document.getElementById('shipProduct'),
      qty: document.getElementById('shipQty'),
      dest: document.getElementById('shipDest'),
      scan: document.getElementById('shipScan'),
      submit: document.getElementById('shipSubmit'),
      list: document.getElementById('queueShip'),
    },
    syncBtn: document.getElementById('btnSync'),
    clearBtn: document.getElementById('btnClearQueue'),
    syncFb: document.getElementById('syncFeedback'),
    goalRec: document.getElementById('goalRec'),
    goalShip: document.getElementById('goalShip'),
    goalsInfo: document.getElementById('goalsInfo'),
  };

  const store = {
    readCfg(){ try { return JSON.parse(localStorage.getItem('collectorCfg')||'{}'); } catch(e){ return {}; } },
    saveCfg(cfg){ localStorage.setItem('collectorCfg', JSON.stringify(cfg||{})); },
    readQueue(){ try { return JSON.parse(localStorage.getItem('collectorQueue')||'[]'); } catch(e){ return []; } },
    saveQueue(rows){ localStorage.setItem('collectorQueue', JSON.stringify(rows||[])); },
    push(ev){ const q = store.readQueue(); q.push(ev); store.saveQueue(q); renderQueue(); renderDashboard(q); },
    clear(){ store.saveQueue([]); renderQueue(); renderDashboard([]); },
    readStats(){ try { return JSON.parse(localStorage.getItem('collectorStats')||'{}'); } catch(e){ return {}; } },
    saveStats(stats){ localStorage.setItem('collectorStats', JSON.stringify(stats||{})); },
  };

  function setStatus(){
    const cfg = store.readCfg();
    el.stUrl.textContent = cfg.url || '-';
    el.stDev.textContent = cfg.deviceKey || '-';
    el.stSync.textContent = cfg.lastSync ? new Date(cfg.lastSync).toLocaleString('pt-BR') : '-';
  }

  // Camera & scanning
  let mediaStream = null; let scanning = false;
  async function enableCamera(){
    try{
      mediaStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, audio:false });
      el.camera.srcObject = mediaStream; el.camera.play();
      el.scanStatus.textContent = 'Câmera ativa';
    }catch(e){ el.scanStatus.textContent = 'Falha ao ativar câmera: '+ e.message; }
  }

  async function scanCode(onResult){
    if(!mediaStream){ await enableCamera(); }
    const supportedFormats = ['qr_code','code_128','code_39','ean_13','ean_8','upc_e'];
    const Detector = window.BarcodeDetector ? new window.BarcodeDetector({ formats: supportedFormats }) : null;
    if(!Detector){ el.scanStatus.textContent = 'Leitor não suportado neste navegador. Use a entrada manual.'; return; }
    scanning = true; el.scanStatus.textContent = 'Escaneando…';
    const tick = async()=>{
      if(!scanning) return;
      try{
        const results = await Detector.detect(el.camera);
        if(results && results.length){ scanning=false; const code = results[0].rawValue || results[0].value || '';
          onResult(String(code||'')); el.scanStatus.textContent = 'Lido'; return; }
      }catch(_){ /* ignore */ }
      requestAnimationFrame(tick);
    };
    requestAnimationFrame(tick);
  }

  // Pairing
  function applyPairing(str){
    try{
      const cfg = JSON.parse(String(str||'{}'));
      if(!cfg.url){ throw new Error('URL ausente'); }
      const cur = store.readCfg(); const next = { ...cur, url: cfg.url, deviceKey: cfg.deviceKey||cur.deviceKey };
      store.saveCfg(next); setStatus();
    }catch(e){ el.scanStatus.textContent = 'Pareamento inválido: '+ e.message; }
  }
  async function testPing(){
    const cfg = store.readCfg();
    let baseUrl = (cfg.url||'').replace(/\/$/,'');
    if(!baseUrl){ el.scanStatus.textContent = 'Configure a URL'; return; }
    // Se app foi pareado com '/mobile', usar o alias de ping sob /mobile
    const pathPing = baseUrl.endsWith('/mobile') ? '/mobile/ping' : '/ping';
    const makeUrl = (host)=> `${host}${pathPing}?device_key=${encodeURIComponent(cfg.deviceKey||'')}`;
    const hosts = [baseUrl, baseUrl.replace('localhost', '127.0.0.1')];
    let res = null;
    try{
      res = await fetch(makeUrl(hosts[0]));
    }catch(_){
      // Fallback para 127.0.0.1 quando localhost falhar (IPv6 vs IPv4)
      try{ res = await fetch(makeUrl(hosts[1])); }catch(e2){ el.scanStatus.textContent = 'Erro: '+ e2.message; return; }
    }
    try{
      if(res && res.ok){
        let data = {};
        try { data = await res.json(); } catch(_){ /* ignore parse errors */ }
        const valid = !!data.device_valid;
        const validity = data.valid_until || data.expires_at || data.validity || null;
        el.scanStatus.textContent = valid ? 'Conexão OK (dispositivo válido)' : 'Conexão OK (dispositivo não reconhecido)';
        // Atualizar elementos de status
        if (el.stUrl) el.stUrl.textContent = cfg.url || '';
        if (el.stDev) {
          el.stDev.textContent = cfg.deviceKey || '';
          if (validity) {
            el.stDev.textContent = `${cfg.deviceKey || ''} (válido até ${String(validity)})`;
          }
        }
      } else if (res) {
        el.scanStatus.textContent = 'Falha na conexão';
      }
    }catch(e){ el.scanStatus.textContent = 'Erro: '+ e.message; }
  }

  // Queue rendering
  function renderQueue(){
    const q = store.readQueue();
    const inv = q.filter(x=>x.type==='inventory'); const rec = q.filter(x=>x.type==='receiving'); const ship = q.filter(x=>x.type==='shipping');
    const li = (r)=> `<li><span>${new Date(r.ts).toLocaleTimeString('pt-BR')}</span><span>${r.type}</span><span class="mono">${JSON.stringify(r.payload)}</span></li>`;
    el.inv.list.innerHTML = inv.map(li).join('') || '<li class="muted">Vazio</li>';
    el.rec.list.innerHTML = rec.map(li).join('') || '<li class="muted">Vazio</li>';
    el.ship.list.innerHTML = ship.map(li).join('') || '<li class="muted">Vazio</li>';
    renderDashboard(q);
  }

  // Enqueue helpers
  function enqueue(type, payload){ store.push({ ts: Date.now(), type, payload }); }

  async function syncQueue(){
    const cfg = store.readCfg(); let baseUrl = (cfg.url||'').replace(/\/$/,''); if(!baseUrl){ el.syncFb.textContent = 'Configure a URL'; return; }
    const q = store.readQueue(); if(!q.length){ el.syncFb.textContent = 'Fila já está vazia'; return; }
    let ok=0, fail=0;
    const pathEvents = baseUrl.endsWith('/mobile') ? '/mobile/events' : '/events';
    const hosts = [baseUrl, baseUrl.replace('localhost','127.0.0.1')];
    for(const ev of q){
      try{
        let res = null;
        try{
          res = await fetch(`${hosts[0]}${pathEvents}`, { method:'POST', headers: { 'Content-Type':'application/json', 'X-Device-Key': cfg.deviceKey||'' }, body: JSON.stringify(ev) });
        }catch(_){
          // Fallback para 127.0.0.1
          res = await fetch(`${hosts[1]}${pathEvents}`, { method:'POST', headers: { 'Content-Type':'application/json', 'X-Device-Key': cfg.deviceKey||'' }, body: JSON.stringify(ev) });
        }
        if(res.ok) ok++; else fail++;
      }catch(_){ fail++; }
    }
    if(fail===0){ store.clear(); cfg.lastSync = Date.now(); store.saveCfg(cfg); setStatus(); el.syncFb.textContent = `Sincronizado: ${ok}`; }
    else { el.syncFb.textContent = `OK: ${ok} • Falhas: ${fail}`; }
    store.saveStats({ lastSyncAt: Date.now(), lastSyncOk: ok, lastSyncFail: fail });
    renderDashboard(store.readQueue());
  }

  // Mode switching
  function switchMode(mode){
    el.modes.forEach(b=> b.setAttribute('aria-selected', b.getAttribute('data-mode')===mode ? 'true':'false'));
    el.sections.inv.classList.toggle('hidden', mode!=='inventory');
    el.sections.rec.classList.toggle('hidden', mode!=='receiving');
    el.sections.ship.classList.toggle('hidden', mode!=='shipping');
  }

  // Bindings
  el.btnEnableCam?.addEventListener('click', enableCamera);
  el.btnScanPair?.addEventListener('click', ()=> scanCode(applyPairing));
  el.btnApplyPair?.addEventListener('click', ()=> applyPairing(el.pairString.value));
  el.btnTestPing?.addEventListener('click', testPing);
  el.modes.forEach(b=> b.addEventListener('click', ()=> switchMode(b.getAttribute('data-mode'))));

  // Inventory actions
  el.inv.scan?.addEventListener('click', ()=> scanCode(code=> el.inv.product.value = code));
  el.inv.submit?.addEventListener('click', ()=>{
    const payload = { product: el.inv.product.value.trim(), bin: el.inv.bin.value.trim(), qty: parseInt(el.inv.qty.value||'0',10) };
    if(!payload.product || !payload.qty){ el.syncFb.textContent = 'Produto e quantidade são obrigatórios'; return; }
    enqueue('inventory', payload);
    el.inv.product.value = ''; el.inv.bin.value=''; el.inv.qty.value='';
  });

  // Receiving actions
  el.rec.scan?.addEventListener('click', ()=> scanCode(code=> el.rec.product.value = code));
  el.rec.submit?.addEventListener('click', ()=>{
    const payload = { product: el.rec.product.value.trim(), qty: parseInt(el.rec.qty.value||'0',10), origin: el.rec.origin.value.trim() };
    if(!payload.product || !payload.qty){ el.syncFb.textContent = 'Produto e quantidade são obrigatórios'; return; }
    enqueue('receiving', payload);
    el.rec.product.value=''; el.rec.qty.value=''; el.rec.origin.value='';
  });

  // Shipping actions
  el.ship.scan?.addEventListener('click', ()=> scanCode(code=> el.ship.product.value = code));
  el.ship.submit?.addEventListener('click', ()=>{
    const payload = { product: el.ship.product.value.trim(), qty: parseInt(el.ship.qty.value||'0',10), dest: el.ship.dest.value.trim() };
    if(!payload.product || !payload.qty){ el.syncFb.textContent = 'Produto e quantidade são obrigatórios'; return; }
    enqueue('shipping', payload);
    el.ship.product.value=''; el.ship.qty.value=''; el.ship.dest.value='';
  });

  // Sync controls
  el.syncBtn?.addEventListener('click', syncQueue);
  el.clearBtn?.addEventListener('click', ()=> store.clear());

  // Register SW
  if('serviceWorker' in navigator){
    navigator.serviceWorker.register('./sw.js').catch(()=>{});
  }

  // Initial
  setStatus(); renderQueue(); renderDashboard(store.readQueue()); updateWmsGoals(); setInterval(updateWmsGoals, 60000);

  // Dashboard rendering
  function renderDashboard(queue){
    try{
      const q = Array.isArray(queue) ? queue : [];
      const total = q.length;
      const byType = {
        inventory: q.filter(x=>x.type==='inventory').length,
        receiving: q.filter(x=>x.type==='receiving').length,
        shipping: q.filter(x=>x.type==='shipping').length,
      };
      const queueBars = document.getElementById('queueBars');
      const queueInfo = document.getElementById('queueInfo');
      if(queueBars){
        queueBars.innerHTML = '';
        const mkBar = (label, value, color)=>{
          const pct = total ? Math.round((value/total)*100) : 0;
          const wrap = document.createElement('div'); wrap.style.display='flex'; wrap.style.flexDirection='column'; wrap.style.gap='4px';
          const bar = document.createElement('div'); bar.style.height='12px'; bar.style.width='160px'; bar.style.background='#eee'; bar.style.borderRadius='6px';
          const fill = document.createElement('div'); fill.style.height='12px'; fill.style.width=pct+'%'; fill.style.background=color; fill.style.borderRadius='6px';
          bar.appendChild(fill);
          const cap = document.createElement('small'); cap.className='muted'; cap.textContent = `${label}: ${value} (${pct}%)`;
          wrap.appendChild(bar); wrap.appendChild(cap);
          queueBars.appendChild(wrap);
        };
        mkBar('Inventário', byType.inventory, '#6c5ce7');
        mkBar('Recebimento', byType.receiving, '#00b894');
        mkBar('Expedição', byType.shipping, '#fdcb6e');
        if(queueInfo) queueInfo.textContent = `Total na fila: ${total}`;
      }

      const stats = store.readStats();
      const syncBars = document.getElementById('syncBars');
      const syncInfo = document.getElementById('syncInfo');
      if(syncBars){
        syncBars.innerHTML='';
        const ok = stats.lastSyncOk||0; const fail = stats.lastSyncFail||0; const sum = ok+fail;
        const pctOk = sum ? Math.round((ok/sum)*100) : 0;
        const pctFail = sum ? 100-pctOk : 0;
        const mkSimpleBar = (label, pct, color)=>{
          const wrap = document.createElement('div'); wrap.style.display='flex'; wrap.style.flexDirection='column'; wrap.style.gap='4px';
          const bar = document.createElement('div'); bar.style.height='12px'; bar.style.width='160px'; bar.style.background='#eee'; bar.style.borderRadius='6px';
          const fill = document.createElement('div'); fill.style.height='12px'; fill.style.width=pct+'%'; fill.style.background=color; fill.style.borderRadius='6px';
          bar.appendChild(fill);
          const cap = document.createElement('small'); cap.className='muted'; cap.textContent = `${label}: ${pct}%`;
          wrap.appendChild(bar); wrap.appendChild(cap);
          syncBars.appendChild(wrap);
        };
        mkSimpleBar('Sucesso', pctOk, '#00b894');
        mkSimpleBar('Falhas', pctFail, '#d63031');
        const when = stats.lastSyncAt ? new Date(stats.lastSyncAt).toLocaleString('pt-BR') : '—';
        if(syncInfo) syncInfo.textContent = `Última sync: ${when} • Sucesso: ${ok} • Falhas: ${fail}`;
      }

      const chart = document.getElementById('queueChart');
      if(chart){
        chart.innerHTML='';
        const recent = q.slice(-12);
        const colors = { inventory:'#6c5ce7', receiving:'#00b894', shipping:'#fdcb6e' };
        recent.forEach(ev=>{
          const bar = document.createElement('div');
          bar.style.width='12px';
          bar.style.height=(24+Math.floor(Math.random()*60))+'px';
          bar.style.background=colors[ev.type]||'#74b9ff';
          bar.title = `${ev.type} • ${new Date(ev.ts).toLocaleTimeString('pt-BR')}`;
          chart.appendChild(bar);
        });
      }
    }catch(_){ /* ignore */ }
  }

  // WMS metas — progresso diário
  function formatYMD(d){ const pad=(n)=> String(n).padStart(2,'0'); return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`; }
  async function updateWmsGoals(){
    try{
      const today = new Date(); const ymd = formatYMD(today);
      const res = await fetch(`/api/wms/bi/overview?de=${ymd}&ate=${ymd}`, { credentials:'include' });
      if(!res.ok){ if(el.goalsInfo) el.goalsInfo.textContent = 'Metas WMS indisponíveis (sessão ausente)'; return; }
      const data = await res.json();
      const rec = parseInt(data?.totais_hoje?.recebimento||0,10);
      const ship = parseInt(data?.totais_hoje?.expedicao||0,10);
      const metaRec = parseInt(data?.metas?.recebimento_meta||100,10);
      const pctRec = Math.max(0, Math.min(100, Math.round((rec/Math.max(1,metaRec))*100)));
      const pctShip = rec>0 ? Math.max(0, Math.min(100, Math.round((ship/rec)*100))) : 0;
      if(el.goalRec) el.goalRec.style.width = pctRec + '%';
      if(el.goalShip) el.goalShip.style.width = pctShip + '%';
      if(el.goalsInfo) el.goalsInfo.textContent = `Hoje • Recebimento: ${rec}/${metaRec} (${pctRec}%) • Expedição: ${ship}/${rec||1} (${pctShip}%)`;
      // Persistir para renderizações futuras
      const stats = store.readStats()||{}; stats.wmsGoals = { date: ymd, rec, ship, metaRec, pctRec, pctShip }; store.saveStats(stats);
    }catch(e){ if(el.goalsInfo) el.goalsInfo.textContent = 'Metas WMS indisponíveis (erro de rede)'; }
  }
})();