// Popup controller: login, dashboard com quota, navegação básica.

import * as api from '../lib/api.js';
import { qrCodeImgUrl } from '../lib/qrcode.js';
import { FREE_DAILY_LIMIT, EXTENSION_ONLY_PLAN, DEFAULT_SETTINGS, STORAGE_KEYS } from '../lib/config.js';

const $ = (id) => document.getElementById(id);
const show = (id) => { $(id).style.display = ''; };
const hide = (id) => { $(id).style.display = 'none'; };

// Mostra versão no header
try {
  const v = chrome.runtime.getManifest().version;
  const el = document.getElementById('hd-version');
  if (el && v) el.textContent = 'v' + v;
} catch (_) {}

// ── Switch ON/OFF global ────────────────────────────────────────────────
// Settings.extension_enabled controla:
//  - content scripts (panel) ignoram items capturados
//  - inject scripts param de postar items
//  - SW pula o worker loop (não pega jobs novos)
// A flag não cancela jobs já em andamento — só impede novos.
(async () => {
  try {
    const s = await chrome.storage.local.get(STORAGE_KEYS.SETTINGS);
    const enabled = (s[STORAGE_KEYS.SETTINGS]?.extension_enabled) !== false;
    const cb = document.getElementById('ext-onoff');
    const lbl = document.getElementById('ext-onoff-label');
    const banner = document.getElementById('ext-off-banner');
    if (cb) {
      cb.checked = enabled;
      if (lbl) lbl.textContent = enabled ? 'ON' : 'OFF';
      if (banner) banner.style.display = enabled ? 'none' : '';
      cb.addEventListener('change', async () => {
        const on = cb.checked;
        if (lbl) lbl.textContent = on ? 'ON' : 'OFF';
        if (banner) banner.style.display = on ? 'none' : '';
        const cur = (await chrome.storage.local.get(STORAGE_KEYS.SETTINGS))[STORAGE_KEYS.SETTINGS] || {};
        await chrome.storage.local.set({ [STORAGE_KEYS.SETTINGS]: { ...cur, extension_enabled: on } });
        // Avisa todas as abas TT/IG abertas pra mostrar/esconder o painel
        try {
          const tabs = await chrome.tabs.query({ url: ['https://*.tiktok.com/*', 'https://*.instagram.com/*'] });
          for (const t of tabs) {
            chrome.tabs.sendMessage(t.id, { type: 'IS_EXT_ENABLED_CHANGED', enabled: on }).catch(() => {});
          }
        } catch (_) {}
      });
    }
  } catch (_) {}
})();

const VIEWS = ['view-login', 'view-home', 'view-settings', 'view-checkout'];
function showView(name) {
  for (const v of VIEWS) {
    document.getElementById(v).style.display = (v === name) ? '' : 'none';
  }
}

// ── Login ────────────────────────────────────────────────────────────────
$('form-login').addEventListener('submit', async (e) => {
  e.preventDefault();
  const btn = $('btn-login');
  const err = $('login-err');
  err.style.display = 'none';
  btn.disabled = true;
  btn.textContent = 'Entrando...';
  try {
    const email = $('in-email').value.trim();
    const pw = $('in-password').value;
    const r = await api.login(email, pw);
    if (!r.ok) {
      err.textContent = r.data?.error || `Erro ao entrar (HTTP ${r.status})`;
      err.style.display = '';
      return;
    }
    await loadHome();
  } catch (e) {
    err.textContent = 'Erro de rede. Tente de novo.';
    err.style.display = '';
  } finally {
    btn.disabled = false;
    btn.textContent = 'Entrar';
  }
});

// ── Home (dashboard) ────────────────────────────────────────────────────
function planLabel(user, quota) {
  if (quota?.unlimited) {
    if (quota.plan === 'instascheduler') return 'ScaleReels Pro · ilimitado';
    if (quota.plan === 'extension_only') return 'Extensão Pro · ilimitado';
    return 'Plano ativo';
  }
  return 'Grátis · 10 + 10 vídeos/dia';
}

function updateQuotaBar(barId, numId, used, limit, unlimited) {
  const bar = $(barId);
  const num = $(numId);
  if (unlimited) {
    bar.style.width = '100%';
    bar.className = 'quota-fill';
    bar.style.background = 'var(--grn)';
    num.textContent = '∞';
    return;
  }
  const pct = Math.min(100, Math.round((used / Math.max(1, limit)) * 100));
  bar.style.width = pct + '%';
  bar.style.background = '';
  bar.className = 'quota-fill' + (pct >= 100 ? ' danger' : pct >= 70 ? ' warn' : '');
  num.textContent = `${used} / ${limit}`;
}

async function loadHome() {
  showView('view-home');
  $('hd-status').textContent = 'carregando...';

  // 1) Render imediato com cache pra não mostrar "?" / "—" enquanto fetch roda.
  const cached = await api.getCachedUser();
  if (cached) {
    renderUserCard(cached);
    const hasAddonC = !!(cached?.has_addon_tools || cached?.role === 'admin');
    $('user-plan').textContent = hasAddonC
      ? '✓ Plano Premium · Moldura + Watermark liberados'
      : 'Grátis · Downloads ilimitados (Moldura/Watermark requerem Pro/Anual)';
  }

  // 2) Refresh /me em background. Só volta pro login se for 401 explícito.
  // Outros erros (network, 5xx, JSON ruim) preservam o cache na tela.
  const meR = await api.getMe();
  if (meR.status === 401) {
    showView('view-login');
    $('hd-status').textContent = '';
    return;
  }
  // Se request falhou mas não é 401 (servidor fora, JSON malformado, etc),
  // mantemos o cache renderizado em vez de zerar a tela.
  if (!meR.ok || !meR.data) {
    if (!cached) {
      // Sem cache nem resposta — pelo menos mostra algo informativo
      $('user-name').textContent = 'Conta carregada';
      $('user-plan').textContent = 'Sem conexão com o servidor — tente recarregar';
    }
    $('hd-status').textContent = 'offline';
    return;
  }
  renderUserCard(meR.data);

  // Download é ilimitado pra todos agora — não mostra mais barra de quota.
  const hasAddon = !!(meR.data?.has_addon_tools || meR.data?.role === 'admin');
  const quotaCard = document.querySelector('.quota-card');
  if (quotaCard) quotaCard.style.display = 'none';
  $('user-plan').textContent = hasAddon
    ? '✓ Plano Premium · Moldura + Watermark liberados'
    : 'Grátis · Downloads ilimitados (Moldura/Watermark requerem Pro/Anual)';
  $('hd-status').textContent = '';
}

function renderUserCard(user) {
  $('user-name').textContent = user?.name || user?.email || 'Usuário';
  $('user-initial').textContent = (user?.name || user?.email || '?').charAt(0).toUpperCase();
}

// ── Actions ──────────────────────────────────────────────────────────────
$('btn-logout').addEventListener('click', async () => {
  await api.logout();
  showView('view-login');
});

$('btn-open-tt').addEventListener('click', () => {
  chrome.tabs.create({ url: 'https://www.tiktok.com/' });
});

$('btn-open-ig').addEventListener('click', () => {
  chrome.tabs.create({ url: 'https://www.instagram.com/' });
});

$('btn-settings').addEventListener('click', async () => {
  await loadSettings();
  showView('view-settings');
});

$('btn-back').addEventListener('click', () => {
  showView('view-home');
});

// ── Settings (persistidos em chrome.storage.local sob STORAGE_KEYS.SETTINGS)
async function loadSettings() {
  const s = await chrome.storage.local.get(STORAGE_KEYS.SETTINGS);
  const settings = { ...DEFAULT_SETTINGS, ...(s[STORAGE_KEYS.SETTINGS] || {}) };

  // Destino (radio)
  const dest = settings.destination === 'local' ? 'local' : 'drive';
  $('dest-drive').checked = dest === 'drive';
  $('dest-local').checked = dest === 'local';
  $('set-drive-root').value = settings.drive_root_folder || 'ScaleReels Downloader';
  toggleSelectRow('drive-folder-wrap', dest === 'drive');

  $('set-anti-detect').checked = !!settings.anti_detect;
  // Transcode foi removido da UI em v1.0.27 — sempre off pra evitar double-encode
  // (moldura/watermark já re-codificam IG-safe). Se ficou true salvo, força false.
  if (settings.transcode_h264) {
    saveSettings({ transcode_h264: false });
  }
  $('set-transcode').checked = false;
  $('set-auto-scroll').checked = !!settings.auto_scroll;

  // Moldura e marca d'água são features premium (requerem plano Pro/Yearly/Extension_only
  // ou liberação manual). Se o user não tem addon, desabilita os checkboxes e mostra
  // mensagem de upgrade. Download + Anti-detect continuam grátis pra todos.
  const cachedUser = await api.getCachedUser();
  const hasAddon = !!(cachedUser?.has_addon_tools || cachedUser?.role === 'admin');
  applyPremiumGate(hasAddon, settings);

  toggleSelectRow('frame-select-wrap', settings.apply_frame && hasAddon);
  toggleSelectRow('watermark-select-wrap', settings.apply_watermark && hasAddon);

  // Detecta se os binários ffmpeg.wasm estão instalados
  const ffmpegUrl = chrome.runtime.getURL('public/ffmpeg/ffmpeg-core.js');
  try {
    const r = await fetch(ffmpegUrl, { method: 'HEAD' });
    const info = $('ffmpeg-status');
    if (r.ok) {
      info.textContent = '✓ ffmpeg.wasm instalado — anti-detect, transcode, moldura e watermark funcionando.';
      info.className = 'setting-info ok';
    } else throw new Error('not found');
  } catch (_) {
    const info = $('ffmpeg-status');
    info.innerHTML = '⚠ Binários do ffmpeg.wasm não encontrados. As opções de processamento vão falhar até você baixar e colocar em <code>public/ffmpeg/</code>. Veja o <code>README.md</code> da pasta na extensão.';
    info.className = 'setting-info warn';
  }

  // Carrega presets (lazy — só quando abre Settings)
  loadFramePresets(settings.frame_preset_id);
  loadWatermarkPresets(settings.watermark_preset_id);
}

function toggleSelectRow(wrapId, on) {
  const el = $(wrapId);
  if (el) el.style.display = on ? '' : 'none';
}

// Aplica gating das features premium (Moldura + Marca d'água). Se hasAddon=false,
// força os checkboxes off, desabilita, e adiciona badge "PRO" ao lado do título.
function applyPremiumGate(hasAddon, settings) {
  const frameChk = $('set-apply-frame');
  const wmChk = $('set-apply-watermark');
  if (hasAddon) {
    frameChk.checked = !!settings.apply_frame;
    wmChk.checked = !!settings.apply_watermark;
    frameChk.disabled = false;
    wmChk.disabled = false;
    document.querySelectorAll('.is-premium-tag, .is-premium-msg').forEach(el => el.remove());
    return;
  }
  // Sem addon — força off, desabilita, mostra mensagem
  frameChk.checked = false;
  wmChk.checked = false;
  frameChk.disabled = true;
  wmChk.disabled = true;
  if (settings.apply_frame || settings.apply_watermark) {
    saveSettings({ apply_frame: false, apply_watermark: false });
  }
  // Adiciona aviso visual em cada setting-group
  for (const groupSelector of [
    '#set-apply-frame', '#set-apply-watermark'
  ]) {
    const chk = document.querySelector(groupSelector);
    const group = chk?.closest('.setting-group');
    if (!group || group.querySelector('.is-premium-msg')) continue;
    // Tag PRO no head
    const head = group.querySelector('.setting-head');
    if (head && !head.querySelector('.is-premium-tag')) {
      const tag = document.createElement('span');
      tag.className = 'is-premium-tag';
      tag.textContent = 'PRO';
      head.appendChild(tag);
    }
    // Mensagem de upsell
    const msg = document.createElement('div');
    msg.className = 'is-premium-msg';
    msg.innerHTML = `🔒 Feature do plano <strong>Pro/Anual</strong>. <a href="#" class="is-premium-link">Ver plano</a>`;
    msg.querySelector('a').addEventListener('click', (e) => {
      e.preventDefault();
      openCheckoutView();
    });
    group.appendChild(msg);
  }
}

async function loadFramePresets(selectedId) {
  const sel = $('set-frame-id');
  if (!sel) return;
  const r = await api.listFramePresets();
  if (!r.ok || !Array.isArray(r.data)) {
    sel.innerHTML = '<option value="">— não foi possível carregar —</option>';
    return;
  }
  const opts = ['<option value="">Selecione uma moldura...</option>']
    .concat(r.data.map(p => `<option value="${escapeAttr(p.id)}"${p.id === selectedId ? ' selected' : ''}>${escapeHtml(p.name)}</option>`));
  if (!r.data.length) {
    sel.innerHTML = '<option value="">— sem molduras cadastradas —</option>';
  } else {
    sel.innerHTML = opts.join('');
  }
}

async function loadWatermarkPresets(selectedId) {
  const sel = $('set-watermark-id');
  if (!sel) return;
  const r = await api.listWatermarkPresets();
  if (!r.ok || !Array.isArray(r.data)) {
    sel.innerHTML = '<option value="">— não foi possível carregar —</option>';
    return;
  }
  if (!r.data.length) {
    sel.innerHTML = '<option value="">— nenhuma marca cadastrada no painel —</option>';
    return;
  }
  // Mostra TODAS as marcas cadastradas — as de texto aparecem disabled com aviso
  // pra o user entender que precisa de IMAGEM pra extensão.
  const usable = r.data.filter(w => (w.kind || 'image') === 'image' && w.image_data);
  const textOnly = r.data.filter(w => !((w.kind || 'image') === 'image' && w.image_data));
  const opts = ['<option value="">Selecione uma marca...</option>'];
  for (const w of usable) {
    opts.push(`<option value="${escapeAttr(w.id)}"${w.id === selectedId ? ' selected' : ''}>${escapeHtml(w.name)}</option>`);
  }
  for (const w of textOnly) {
    opts.push(`<option value="" disabled>${escapeHtml(w.name)} (texto — só imagem funciona na extensão)</option>`);
  }
  if (!usable.length) {
    // Tem marcas mas só de texto — instrução clara
    opts.push('<option value="" disabled>— cadastre uma marca do tipo IMAGEM no painel —</option>');
  }
  sel.innerHTML = opts.join('');
}

function escapeAttr(s) { return String(s ?? '').replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c])); }

async function saveSettings(patch) {
  const cur = await chrome.storage.local.get(STORAGE_KEYS.SETTINGS);
  const merged = { ...DEFAULT_SETTINGS, ...(cur[STORAGE_KEYS.SETTINGS] || {}), ...patch };
  await chrome.storage.local.set({ [STORAGE_KEYS.SETTINGS]: merged });
}

['set-anti-detect', 'set-transcode', 'set-auto-scroll', 'set-apply-frame', 'set-apply-watermark'].forEach(id => {
  $(id).addEventListener('change', (e) => {
    const map = {
      'set-anti-detect': 'anti_detect',
      'set-transcode': 'transcode_h264',
      'set-auto-scroll': 'auto_scroll',
      'set-apply-frame': 'apply_frame',
      'set-apply-watermark': 'apply_watermark'
    };
    const key = map[id];
    saveSettings({ [key]: e.target.checked });

    // Mostra/esconde o select de preset
    if (id === 'set-apply-frame') toggleSelectRow('frame-select-wrap', e.target.checked);
    if (id === 'set-apply-watermark') toggleSelectRow('watermark-select-wrap', e.target.checked);
  });
});

// Refresh manual: invalida cache de presets no SW + recarrega selects.
// Útil quando o usuário cadastra moldura/watermark nova no painel e quer ver na extensão
// sem esperar os 5min do TTL do cache.
async function refreshPresets(kind) {
  const btn = document.getElementById(kind === 'frames' ? 'btn-refresh-frames' : 'btn-refresh-watermarks');
  if (!btn) return;
  btn.classList.add('spinning');
  btn.disabled = true;
  try {
    // Pede pro SW limpar o cache em memória
    await chrome.runtime.sendMessage({ type: 'INVALIDATE_PRESETS_CACHE', kind });
    // Recarrega o select preservando seleção atual
    const cur = (await chrome.storage.local.get(STORAGE_KEYS.SETTINGS))[STORAGE_KEYS.SETTINGS] || {};
    if (kind === 'frames') await loadFramePresets(cur.frame_preset_id);
    else await loadWatermarkPresets(cur.watermark_preset_id);
  } catch (err) {
    console.error('[popup] refresh presets err:', err);
  } finally {
    setTimeout(() => { btn.classList.remove('spinning'); btn.disabled = false; }, 600);
  }
}
$('btn-refresh-frames')?.addEventListener('click', () => refreshPresets('frames'));
$('btn-refresh-watermarks')?.addEventListener('click', () => refreshPresets('watermarks'));

$('set-frame-id').addEventListener('change', (e) => {
  saveSettings({ frame_preset_id: e.target.value || null });
});
$('set-watermark-id').addEventListener('change', (e) => {
  saveSettings({ watermark_preset_id: e.target.value || null });
});

// Radio destino (Drive vs Local)
['dest-drive', 'dest-local'].forEach(id => {
  $(id).addEventListener('change', (e) => {
    if (!e.target.checked) return;
    const value = e.target.value;
    saveSettings({ destination: value });
    toggleSelectRow('drive-folder-wrap', value === 'drive');
  });
});

// Input de pasta Drive root
$('set-drive-root').addEventListener('input', (e) => {
  const v = String(e.target.value || '').trim() || 'ScaleReels Downloader';
  saveSettings({ drive_root_folder: v });
});

$('btn-upgrade').addEventListener('click', () => {
  openCheckoutView();
});

// ── Queue widget ────────────────────────────────────────────────────────
let _queuePollHandle = null;

function escapeHtml(s) {
  return String(s ?? '').replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
}

function renderQueue(r) {
  const card = $('queue-card');
  if (!card) return;
  if (!r?.ok || (r.counts?.total || 0) === 0) {
    card.style.display = 'none';
    return;
  }
  card.style.display = '';
  const c = r.counts || {};
  $('queue-count').textContent = String(c.total || 0);

  const activeCount = (c.downloading || 0) + (c.uploading || 0);
  const queuedCount = c.queued || 0;
  const doneCount = c.done || 0;
  const failedCount = c.failed || 0;
  const blockedCount = c.blocked || 0;

  let statusTxt = '';
  if (activeCount > 0) statusTxt = `Processando ${activeCount} agora...`;
  else if (queuedCount > 0) statusTxt = `${queuedCount} aguardando começar.`;
  else if (failedCount > 0 || blockedCount > 0) statusTxt = 'Alguns jobs falharam — veja abaixo.';
  else if (doneCount > 0) statusTxt = `${doneCount} concluído${doneCount === 1 ? '' : 's'} hoje.`;
  $('queue-status').textContent = statusTxt;

  // Pills com contadores por status
  const pills = [];
  if (queuedCount) pills.push(`<span class="q-pill q-queued">${queuedCount} fila</span>`);
  if (c.downloading) pills.push(`<span class="q-pill q-downloading">${c.downloading} baixando</span>`);
  if (c.uploading) pills.push(`<span class="q-pill q-uploading">${c.uploading} enviando</span>`);
  if (doneCount) pills.push(`<span class="q-pill q-done">${doneCount} ok</span>`);
  if (failedCount) pills.push(`<span class="q-pill q-failed">${failedCount} erro</span>`);
  if (blockedCount) pills.push(`<span class="q-pill q-blocked">${blockedCount} cota</span>`);
  $('queue-counts').innerHTML = pills.join('');

  // Lista (top 8 mais relevantes)
  const items = (r.items || []).slice(0, 8);
  $('queue-items').innerHTML = items.map(j => {
    const name = `${j.platform === 'tiktok' ? '🎵' : '📷'} @${escapeHtml(j.author || '?')} — ${escapeHtml((j.source_id || '').slice(0, 16))}`;
    return `<div class="qi">
      <span class="qi-dot ${j.status}"></span>
      <span class="qi-name" title="${escapeHtml(j.error || '')}">${name}</span>
      <span class="qi-status">${j.status}</span>
    </div>`;
  }).join('');

  $('btn-retry-failed').style.display = (failedCount + blockedCount) > 0 ? '' : 'none';
  $('btn-clear-done').style.display = (doneCount + failedCount + blockedCount) > 0 ? '' : 'none';
}

async function refreshQueue() {
  return new Promise((resolve) => {
    chrome.runtime.sendMessage({ type: 'GET_QUEUE' }, (r) => {
      if (chrome.runtime.lastError) { resolve(); return; }
      renderQueue(r);
      resolve();
    });
  });
}

function startQueuePolling() {
  if (_queuePollHandle) return;
  _queuePollHandle = setInterval(refreshQueue, 1500);
}

function stopQueuePolling() {
  if (_queuePollHandle) { clearInterval(_queuePollHandle); _queuePollHandle = null; }
}

window.addEventListener('unload', stopQueuePolling);

$('btn-grant-drive').addEventListener('click', () => {
  const btn = $('btn-grant-drive');
  const original = btn.textContent;
  btn.disabled = true;
  btn.textContent = 'Abrindo Google...';
  chrome.runtime.sendMessage({ type: 'GRANT_DRIVE' }, (r) => {
    btn.disabled = false;
    btn.textContent = original;
    if (r?.ok) {
      toast('✓ Google Drive conectado! Próximos downloads vão direto pra lá.');
      refreshQueue();
    } else {
      const err = r?.error || 'desconhecida';
      if (err.includes('OAuth') || err.includes('client_id') || err.includes('bad client')) {
        toast('⚠️ Google Drive não disponível nessa instalação. Use "Baixar no computador" nas Configurações.', 'error', 7000);
      } else {
        toast('Falha ao conectar Drive: ' + err, 'error');
      }
    }
  });
});

// Toast simples no canto do popup
function toast(msg, type = 'info', duration = 3000) {
  let el = document.getElementById('_is_toast');
  if (!el) {
    el = document.createElement('div');
    el.id = '_is_toast';
    el.style.cssText = `
      position: fixed; bottom: 14px; left: 14px; right: 14px;
      background: rgba(0,0,0,0.86); color: #fff;
      padding: 10px 12px; border-radius: 8px;
      font-size: 0.78rem; line-height: 1.4; text-align: center;
      z-index: 99999; opacity: 0; transition: opacity 0.2s;
      backdrop-filter: blur(8px);
    `;
    document.body.appendChild(el);
  }
  el.textContent = msg;
  if (type === 'error') el.style.background = 'rgba(244,63,94,0.96)';
  else if (type === 'ok') el.style.background = 'rgba(34,197,94,0.96)';
  else el.style.background = 'rgba(0,0,0,0.86)';
  el.style.opacity = '1';
  clearTimeout(el._t);
  el._t = setTimeout(() => { el.style.opacity = '0'; }, duration);
}

$('btn-retry-failed').addEventListener('click', () => {
  chrome.runtime.sendMessage({ type: 'RETRY_FAILED' }, () => refreshQueue());
});

$('btn-clear-done').addEventListener('click', () => {
  chrome.runtime.sendMessage({ type: 'CLEAR_DONE' }, () => refreshQueue());
});

// ── Checkout (plano extension_only — R$ 25/mês PIX) ─────────────────────
const CHECKOUT_STATE_KEY = 'is_checkout_state';
let _checkoutPoll = null;

function setCheckoutBlock(stage) {
  $('checkout-loading').style.display = stage === 'loading' ? '' : 'none';
  $('checkout-pix').style.display = stage === 'pix' ? '' : 'none';
  $('checkout-success').style.display = stage === 'success' ? '' : 'none';
  $('checkout-error').style.display = stage === 'error' ? '' : 'none';
}

async function openCheckoutView() {
  showView('view-checkout');
  setCheckoutBlock('loading');

  // Se já tem checkout pendente salvo, retoma sem criar outro
  const saved = await chrome.storage.local.get(CHECKOUT_STATE_KEY);
  const cur = saved[CHECKOUT_STATE_KEY];
  if (cur && cur.subscription_id && (Date.now() - cur.created_at) < 30 * 60 * 1000) {
    renderCheckoutPix(cur);
    return;
  }

  // Cria nova cobrança PIX
  const r = await api.createCheckout('extension_only');
  if (!r.ok || !r.data?.pix_code || !r.data?.subscription_id) {
    showCheckoutError(r.data?.error || `Erro ao criar PIX (HTTP ${r.status})`);
    return;
  }
  const state = {
    subscription_id: r.data.subscription_id,
    identifier: r.data.identifier,
    pix_code: r.data.pix_code,
    amount: r.data.amount,
    created_at: Date.now()
  };
  await chrome.storage.local.set({ [CHECKOUT_STATE_KEY]: state });
  renderCheckoutPix(state);
}

function renderCheckoutPix(state) {
  setCheckoutBlock('pix');
  $('pix-code').value = state.pix_code;
  // QR code via qrserver.com (host autorizado no manifest)
  $('pix-qr-img').src = qrCodeImgUrl(state.pix_code, { size: 240 });
  startCheckoutPolling(state.subscription_id);
}

function showCheckoutError(msg) {
  setCheckoutBlock('error');
  $('checkout-error-msg').textContent = msg || 'Erro desconhecido';
}

async function startCheckoutPolling(subscription_id) {
  stopCheckoutPolling();
  // Polling a cada 3s. Backend consulta SyncPay e retorna {status: pending|active|cancelled}.
  // Avisa o SW também (RUN_CHECKOUT_POLL) pra continuar mesmo se o popup fechar.
  chrome.runtime.sendMessage({ type: 'RUN_CHECKOUT_POLL', subscription_id }).catch(() => {});

  _checkoutPoll = setInterval(async () => {
    const r = await api.getCheckoutStatus(subscription_id);
    if (!r.ok) return;
    const status = r.data?.status;
    if (status === 'active') {
      stopCheckoutPolling();
      await chrome.storage.local.remove(CHECKOUT_STATE_KEY);
      // Atualiza /me pra refletir plan=extension_only
      await api.getMe();
      setCheckoutBlock('success');
    } else if (status === 'cancelled') {
      stopCheckoutPolling();
      await chrome.storage.local.remove(CHECKOUT_STATE_KEY);
      showCheckoutError('Pagamento cancelado ou expirado. Tente de novo.');
    }
  }, 3000);
}

function stopCheckoutPolling() {
  if (_checkoutPoll) { clearInterval(_checkoutPoll); _checkoutPoll = null; }
}

$('btn-checkout-back').addEventListener('click', () => {
  stopCheckoutPolling();
  showView('view-home');
  refreshQueue();
});

$('btn-checkout-done').addEventListener('click', async () => {
  showView('view-home');
  await loadHome();   // re-render com plano novo
});

$('btn-checkout-retry').addEventListener('click', async () => {
  await chrome.storage.local.remove(CHECKOUT_STATE_KEY);
  openCheckoutView();
});

$('btn-copy-pix').addEventListener('click', async () => {
  try {
    await navigator.clipboard.writeText($('pix-code').value);
    const btn = $('btn-copy-pix');
    const old = btn.textContent;
    btn.textContent = '✓ Copiado!';
    setTimeout(() => { btn.textContent = old; }, 1500);
  } catch (_) {
    // fallback
    $('pix-code').select();
    document.execCommand('copy');
  }
});

window.addEventListener('unload', stopCheckoutPolling);

// ── Init ────────────────────────────────────────────────────────────────
(async function init() {
  let cached = await api.getCachedUser();

  // RENDER IMEDIATO do cache (antes mesmo do SSO/getMe) pra evitar tela vazia.
  // O loadHome refresca depois com dados do servidor, mas o user já vê algo na hora.
  if (cached) {
    try {
      document.getElementById('view-home').style.display = '';
      document.getElementById('view-login').style.display = 'none';
      $('user-name').textContent = cached.name || cached.email || 'Usuário';
      $('user-initial').textContent = (cached.name || cached.email || '?').charAt(0).toUpperCase();
      const hasAddonC = !!(cached.has_addon_tools || cached.role === 'admin');
      $('user-plan').textContent = hasAddonC
        ? '✓ Plano Premium · Moldura + Watermark liberados'
        : 'Grátis · Downloads ilimitados (Moldura/Watermark requerem Pro/Anual)';
    } catch (_) {}
  }

  // Se não tem user salvo, tenta SSO via cookie do scalereels.com.br.
  // Se o user já tá logado no site (cookie is_token presente), entra direto.
  if (!cached) {
    const sso = await api.trySSO();
    if (sso.ok) {
      console.log('[Popup] auto-login via cookie do site OK:', sso.user?.email);
      cached = sso.user;
    }
  }

  if (cached) {
    await loadHome();
    await refreshQueue();
    startQueuePolling();
  } else {
    showView('view-login');
  }
})();
