<?php /* Vendas > Pedidos: listagem básica */ ?>
<div class="page-header" style="display:flex;align-items:center;justify-content:space-between;gap:1rem;">
  <div>
    <h1>Pedidos</h1>
    <p class="muted">Gestão de pedidos de venda</p>
  </div>
  <div>
    <div style="display:flex; gap:0.5rem; align-items:center;">
      <button id="btnNewOrder" class="btn" onclick="newOrder()">Novo Pedido</button>
      <a href="/dashboard" class="btn btn-secondary">Voltar</a>
    </div>
  </div>
  
</div>

<div class="card">
  <div style="display:flex;align-items:center;gap:0.75rem; margin-bottom:0.75rem; flex-wrap:wrap;">
    <input id="q" class="input" type="text" placeholder="Buscar por número ou status..." style="max-width:280px;" />
    <select id="status" class="input" style="min-width:160px;">
      <option value="">Status (todos)</option>
      <option value="aberto">Aberto</option>
      <option value="confirmado">Confirmado</option>
      <option value="faturado">Faturado</option>
      <option value="cancelado">Cancelado</option>
    </select>
    <input id="start" class="input" type="date" />
    <input id="end" class="input" type="date" />
    <button id="btnReload" class="btn">Recarregar</button>
    <select id="csvSep" class="input" style="width:120px;">
      <option value=";">CSV ;</option>
      <option value=",">CSV ,</option>
      <option value="\t">CSV Tab</option>
    </select>
    <button id="btnExportCsv" class="btn btn-secondary">Exportar CSV</button>
  </div>
  <div class="table-responsive">
    <table class="table">
      <thead>
        <tr>
          <th>#</th>
          <th>Número</th>
          <th>Cliente</th>
          <th>Status</th>
          <th>Valor Bruto</th>
          <th>Valor Total</th>
          <th>Criado em</th>
          <th style="width:120px;">Ações</th>
        </tr>
      </thead>
      <tbody id="tbody"></tbody>
    </table>
  </div>
  <div id="pager" style="display:flex;align-items:center;gap:0.5rem;justify-content:flex-end;margin-top:0.5rem;"></div>
</div>

<style>
/* Menu de ações por linha (kebab ⋮) */
.action-menu-wrap { position: relative; display:inline-block; }
.action-menu-btn { width:32px; height:32px; display:flex; align-items:center; justify-content:center; padding:0; font-size:18px; line-height:1; }
.action-menu { position:absolute; right:0; top:100%; background:var(--color-white, #fff); border:1px solid var(--border-muted, #ddd); border-radius:6px; box-shadow:0 4px 12px rgba(0,0,0,.1); min-width:180px; padding:4px; z-index:20; display:none; }
.action-menu.open { display:block; }
.action-menu .menu-item { display:block; width:100%; text-align:left; padding:6px 10px; background:none; border:none; cursor:pointer; font: inherit; }
.action-menu .menu-item:hover { background:#f3f4f6; }
.action-menu .menu-item:disabled { opacity:0.5; cursor:default; }
/* Submenu de etiquetas estável ao passar o mouse */
.action-menu .menu-item:hover .action-submenu { display: block; }
</style>

<script>
let currentPage = 1; const perPage = 20; let currentRows = [];

async function loadOrders() {
  const token = (typeof getAuthToken==='function'?getAuthToken():null) || (typeof getAdminToken==='function'?getAdminToken():null);
  if (!token) { console.log('Sem token, não carregando pedidos'); return; }
  const q = document.getElementById('q').value.trim();
  const status = (document.getElementById('status')?.value || '').trim();
  const start = (document.getElementById('start')?.value || '').trim();
  const end = (document.getElementById('end')?.value || '').trim();
  const qs = new URLSearchParams({ page: String(currentPage), per_page: String(perPage) });
  if (q) qs.set('q', q);
  if (status) qs.set('status', status);
  if (start) qs.set('start', start);
  if (end) qs.set('end', end);
  const resp = await apiRequest(`/api/vendas/pedidos?${qs.toString()}`);
  if (!resp || !resp.ok) return;
  const json = await resp.json();
  let rows = (json.data || []);
  currentRows = rows;
  renderRows(rows);
  renderPager(json.page, json.total_pages || 1);
}

function exportOrdersCsv(){
  const q = document.getElementById('q').value.trim();
  const status = (document.getElementById('status')?.value || '').trim();
  const start = (document.getElementById('start')?.value || '').trim();
  const end = (document.getElementById('end')?.value || '').trim();
  const sep = document.getElementById('csvSep').value || ';';
  const qs = new URLSearchParams({ sep });
  if (q) qs.set('q', q);
  if (status) qs.set('status', status);
  if (start) qs.set('start', start);
  if (end) qs.set('end', end);
  const url = `/api/vendas/pedidos/export.csv?${qs.toString()}`;
  const a = document.createElement('a'); a.href = url; a.download = `vendas-pedidos-${Date.now()}.csv`; a.click();
}

function renderRows(rows){
  const tb = document.getElementById('tbody'); tb.innerHTML = '';
  if (!rows || rows.length === 0) {
    tb.innerHTML = '<tr><td colspan="8" style="text-align:center;">Nenhum pedido encontrado</td></tr>';
    return;
  }
  rows.forEach((r, idx) => {
    const tr = document.createElement('tr');
    const canInvoice = (String(r.status||'') !== 'faturado' && String(r.status||'') !== 'cancelado');
    tr.innerHTML = `
      <td>${idx+1}</td>
      <td>${r.numero||'-'}</td>
      <td>${r.cliente_id||'-'}</td>
      <td><span class="badge">${r.status||'-'}</span></td>
      <td>R$ ${(Number(r.valor_bruto||r.valor_total||0)).toFixed(2)}</td>
      <td>R$ ${(Number(r.valor_total||0)).toFixed(2)}</td>
      <td>${(r.created_at||'').replace('T',' ').substring(0,19)}</td>
      <td style="text-align:right;">
        <div class="action-menu-wrap">
          <button class="btn btn-secondary action-menu-btn" onclick="toggleActionMenu(this)" aria-haspopup="true" aria-expanded="false" title="Ações">⋮</button>
                <div class="action-menu" role="menu" data-order-id="${r.id}" data-client-id="${r.cliente_id||''}" data-status="${r.status||''}">
            <button class="menu-item" role="menuitem" onclick="editOrder(${r.id})">${rowIcon('Editar')} Editar</button>
            <button class="menu-item" role="menuitem" onclick="checkoutOrder(${r.id})" ${String(r.status)==='cancelado'?'disabled':''}>${rowIcon('Conferência de pedido (Checkout)')} Conferência de pedido (Checkout)</button>
            <hr />
            <button class="menu-item" role="menuitem" onclick="pickingReport(${r.id})">${rowIcon('Relatório para separação')} Relatório para separação</button>
            <div class="menu-item" style="position:relative;" aria-haspopup="true">
              ${rowIcon('Etiquetas dos volumes')} Etiquetas dos volumes ▸
              <div class="action-submenu" role="menu" style="position:absolute; right:100%; top:0; background:#fff; border:1px solid #ddd; border-radius:6px; box-shadow:0 4px 12px rgba(0,0,0,.1); min-width:200px; padding:4px; display:none;">
                <button class="menu-item" role="menuitem" onclick="labelsVolumes(${r.id}, 'a4')">${rowIcon('Etiqueta A4')} A4 (folha)</button>
                <button class="menu-item" role="menuitem" onclick="labelsVolumes(${r.id}, '58')">${rowIcon('Etiqueta 58mm')} Térmica 58mm</button>
                <button class="menu-item" role="menuitem" onclick="labelsVolumes(${r.id}, '80')">${rowIcon('Etiqueta 80mm')} Térmica 80mm</button>
              </div>
            </div>
            <button class="menu-item" role="menuitem" onclick="deliveryReport(${r.id})">${rowIcon('Relatório de entrega')} Relatório de entrega</button>
            <hr />
            <button class="menu-item" role="menuitem" onclick="generateNFe(${r.id})" data-required-perm="fiscal.nfe.emitir">${rowIcon('Gerar NF-e')} Gerar NF-e</button>
            <button class="menu-item" role="menuitem" onclick="generateNFeGrouped(${r.cliente_id||0})" data-required-perm="fiscal.nfe.emitir">${rowIcon('Gerar NF-e agrupada por cliente')} Gerar NF-e agrupada por cliente</button>
            <button class="menu-item" role="menuitem" onclick="generateNFCe(${r.id})" data-required-perm="vendas.create">${rowIcon('Gerar NFC-e')} Gerar NFC-e</button>
            ${String(r.status)==='faturado' ? `<button class="menu-item" role="menuitem" onclick="showFiscalStatus(${r.id})">${rowIcon('Exibir status NF-e do pedido')} Exibir status NF-e/NFC-e</button>` : ''}
            <hr />
            <button class="menu-item" role="menuitem" onclick="duplicateOrder(${r.id})" data-required-perm="vendas.create">${rowIcon('Duplicar o pedido')} Duplicar o pedido</button>
            <button class="menu-item" role="menuitem" onclick="copyOrderThermal(${r.id}, 'normal')">${rowIcon('Cópia do pedido')} Cópia do pedido</button>
            <button class="menu-item" role="menuitem" onclick="copyOrderThermal(${r.id}, '58')">${rowIcon('Cópia do pedido (impressora térmica 58/80mm)')} Cópia (térmica 58mm)</button>
            <button class="menu-item" role="menuitem" onclick="copyOrderThermal(${r.id}, '80')">${rowIcon('Cópia do pedido (impressora térmica 58/80mm)')} Cópia (térmica 80mm)</button>
            <button class="menu-item" role="menuitem" onclick="window.location.href='/vendas/pedidos/${r.id}/imprimir'">${rowIcon('Imprimir')} Imprimir</button>
            <hr />
            <button class="menu-item" role="menuitem" onclick="generateCharge(${r.id})">${rowIcon('Gerar cobrança do pedido')} Gerar cobrança do pedido</button>
            <button class="menu-item" role="menuitem" onclick="openPayments(${r.id})">${rowIcon('Cobranças do pedido')} Cobranças do pedido</button>
            <hr />
            <button class="menu-item" role="menuitem" onclick="openClientCadastro(${r.cliente_id||0})">${rowIcon('Cadastro do cliente')} Cadastro do cliente</button>
            <button class="menu-item" role="menuitem" onclick="openClientCrm(${r.cliente_id||0})">${rowIcon('Agendas (CRM) do cliente')} Agendas (CRM) do cliente</button>
            <hr />
                <button class="menu-item" role="menuitem" onclick="exportOrderCsv(${r.id})">${rowIcon('Exportar em CSV')} Exportar em CSV</button>
                <button class="menu-item" role="menuitem" onclick="emailOrder(${r.id})">${rowIcon('Enviar por e-mail')} Enviar por e-mail</button>
                <button class="menu-item" role="menuitem" onclick="markOrderRead(${r.id})">${rowIcon('Marcar como lido')} Marcar como lido</button>
                <button class="menu-item" role="menuitem" onclick="markOrderUnread(${r.id})">${rowIcon('Marcar como não lido')} Marcar como não lido</button>
            <hr />
            <button class="menu-item" role="menuitem" onclick="deleteOrder(${r.id})" data-required-perm="vendas.delete" ${String(r.status)==='faturado'?'disabled':''}>${rowIcon('Excluir')} Excluir</button>
          </div>
        </div>
      </td>
    `;
    tb.appendChild(tr);
  });
}

function renderPager(page, totalPages){
  const p = document.getElementById('pager'); p.innerHTML = '';
  const prev = document.createElement('button'); prev.className = 'btn btn-secondary'; prev.textContent = 'Anterior'; prev.disabled = page<=1; prev.onclick = () => { currentPage = Math.max(1, page-1); loadOrders(); };
  const next = document.createElement('button'); next.className = 'btn btn-secondary'; next.textContent = 'Próximo'; next.disabled = page>=totalPages; next.onclick = () => { currentPage = Math.min(totalPages, page+1); loadOrders(); };
  const info = document.createElement('span'); info.className = 'muted'; info.textContent = `Página ${page} de ${totalPages}`;
  p.appendChild(info); p.appendChild(prev); p.appendChild(next);
}

// Abrir/fechar menu de ações por linha e fechar ao clicar fora
function toggleActionMenu(btn){
  try {
    const wrap = btn.closest('.action-menu-wrap');
    const menu = wrap.querySelector('.action-menu');
    const openMenus = document.querySelectorAll('.action-menu.open');
    openMenus.forEach(m => { if (m !== menu) m.classList.remove('open'); m?.previousElementSibling?.setAttribute('aria-expanded','false'); });
    const isOpen = menu.classList.contains('open');
    if (isOpen) {
      menu.classList.remove('open');
      btn.setAttribute('aria-expanded','false');
    } else {
      menu.classList.add('open');
      btn.setAttribute('aria-expanded','true');
    }
  } catch (e) { console.warn('toggleActionMenu error', e); }
}

document.addEventListener('click', (ev) => {
  const target = ev.target;
  const inMenu = !!(target.closest && target.closest('.action-menu-wrap'));
  if (!inMenu) {
    document.querySelectorAll('.action-menu.open').forEach(m => { m.classList.remove('open'); m?.previousElementSibling?.setAttribute('aria-expanded','false'); });
  }
});

async function viewOrder(id){
  try {
    showLoading();
    const resp = await apiRequest(`/api/vendas/pedidos/${id}`);
    hideLoading();
    if (!resp || !resp.ok) { showAlert('Falha ao carregar pedido', 'error'); return; }
    const js = await resp.json();
    const { order, items } = js.data || {};
    const itensHtml = (items||[]).map(it => `
      <tr>
        <td>${it.product_id}</td>
        <td style="text-align:right;">${Number(it.quantidade||0)}</td>
        <td style="text-align:right;">R$ ${(Number(it.preco||0)).toFixed(2)}</td>
        <td style="text-align:right;">R$ ${(Number(it.total||0)).toFixed(2)}</td>
      </tr>
    `).join('');
    const canInvoice = (String(order.status||'') !== 'faturado' && String(order.status||'') !== 'cancelado');
    const content = `
      <div class="card">
        <h3 style="margin-top:0;">Pedido ${order.numero}</h3>
        <p class="muted">Status: <strong>${order.status}</strong> • Cliente: ${order.cliente_id}</p>
        <p><strong>Total:</strong> R$ ${(Number(order.valor_total||0)).toFixed(2)}</p>
        <div class="table-responsive" style="margin-top:0.5rem;">
          <table class="table">
            <thead><tr><th>Produto</th><th style="text-align:right;">Qtd</th><th style="text-align:right;">Preço</th><th style="text-align:right;">Total</th></tr></thead>
            <tbody>${itensHtml || '<tr><td colspan="4" style="text-align:center;">Sem itens</td></tr>'}</tbody>
          </table>
        </div>
        <div style="display:flex; gap:0.5rem; justify-content:flex-end; margin-top:0.75rem;">
          <button class="btn btn-secondary" onclick="openPayments(${order.id})">Pagamentos</button>
          <button class="btn btn-secondary" onclick="generateAsaasLink(${order.id})">Cobrar com link Asaas</button>
          <button class="btn" ${canInvoice?'':'disabled'} onclick="invoiceOrder(${order.id}, true)">Faturar</button>
          <button class="btn btn-secondary" onclick="closeModal()">Fechar</button>
        </div>
      </div>`;
    openModal(`Detalhes do Pedido #${order.id}`, content);
  } catch (e) {
    hideLoading(); showAlert('Erro ao carregar pedido', 'error');
  }
}

// Geração de link Asaas por Pedido
async function generateAsaasLink(orderId){
  try {
    const defaultDue = new Date(Date.now() + 7*24*60*60*1000).toISOString().substring(0,10);
    const dueDate = prompt('Data de vencimento (YYYY-MM-DD):', defaultDue) || defaultDue;
    const billingType = prompt('Tipo de cobrança (BOLETO, PIX, CREDIT_CARD):', 'BOLETO') || 'BOLETO';
    showLoading();
    const resp = await apiRequest(`/api/addons/asaas/orders/${orderId}/payment-link`, { method: 'POST', body: JSON.stringify({ due_date: dueDate, billing_type: billingType }) });
    hideLoading();
    if (!resp || !resp.ok) {
      let msg = 'Falha ao gerar link Asaas';
      try { const er = await resp.json(); msg = er.error?.message || er.error || msg; } catch(_){ }
      showAlert(msg, 'error');
      return;
    }
    const js = await resp.json();
    const d = js.data || {};
    const url = d.link_url || '';
    const info = `Link gerado com sucesso.\nURL: ${url || '(sem URL)'}\nStatus: ${d.status || '-'}`;
    showAlert('Link Asaas criado', 'success');
    openModal('Cobrança Asaas', `<div class="card"><p><strong>URL:</strong> ${url ? `<a href="${url}" target="_blank">${url}</a>` : '(sem URL)'}</p><p><strong>Status:</strong> ${d.status||'-'}</p><p><small>Pagamento Asaas: ${d.asaas_payment_id||'-'} • Link ID: ${d.asaas_link_id||'-'}</small></p><div style="display:flex;justify-content:flex-end;gap:0.5rem;"><button class="btn btn-secondary" onclick="closeModal()">Fechar</button></div></div>`);
  } catch (e) {
    hideLoading();
    showAlert('Erro ao gerar link Asaas', 'error');
  }
}

async function invoiceOrder(id, fromModal=false){
  if (!confirm('Confirmar faturamento do pedido? Isto dará baixa no estoque.')) return;
  try {
    showLoading();
    const resp = await apiRequest(`/api/vendas/pedidos/${id}/faturar`, { method: 'POST' });
    hideLoading();
    if (!resp || !resp.ok) {
      let msg = 'Falha ao faturar pedido';
      try { const er = await resp.json(); msg = er.error?.message || msg; } catch(_){}
      showAlert(msg, 'error');
      return;
    }
    showAlert('Pedido faturado com sucesso', 'success');
    if (fromModal) closeModal();
    loadOrders();
  } catch (e) {
    hideLoading(); showAlert('Erro ao faturar pedido', 'error');
  }
}

async function openPayments(orderId){
  try {
    showLoading();
    const resp = await apiRequest(`/api/vendas/pedidos/${orderId}/pagamentos`);
    hideLoading();
    if (!resp || !resp.ok) { showAlert('Falha ao carregar pagamentos', 'error'); return; }
    const js = await resp.json();
    const rows = js.data || [];
    const s = js.summary || {};
    const listHtml = rows.map(p => `
      <tr>
        <td>${p.metodo}</td>
        <td style="text-align:right;">R$ ${(Number(p.valor||0)).toFixed(2)}</td>
        <td style="text-align:right;">${p.troco != null ? 'R$ '+(Number(p.troco||0)).toFixed(2) : '-'}</td>
        <td>${(p.created_at||'').replace('T',' ').substring(0,19)}</td>
        <td style="text-align:right;"><button class="btn btn-secondary" onclick="deletePayment(${p.id}, ${orderId})">Excluir</button></td>
      </tr>
    `).join('');
    const content = `
      <div class="card">
        <h3 style="margin-top:0;">Pagamentos do Pedido #${s.order_id||orderId}</h3>
        <div class="grid" style="grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap:0.75rem;">
          <div class="card"><div class="muted">Valor Total</div><div><strong>R$ ${(Number(s.valor_total||0)).toFixed(2)}</strong></div></div>
          <div class="card"><div class="muted">Total Pago</div><div><strong>R$ ${(Number(s.total_pago||0)).toFixed(2)}</strong></div></div>
          <div class="card"><div class="muted">Troco</div><div><strong>R$ ${(Number(s.total_troco||0)).toFixed(2)}</strong></div></div>
          <div class="card"><div class="muted">Restante</div><div><strong>R$ ${(Number(s.restante||0)).toFixed(2)}</strong></div></div>
        </div>
        <div class="table-responsive" style="margin-top:0.5rem;">
          <table class="table">
            <thead><tr><th>Método</th><th style="text-align:right;">Valor</th><th style="text-align:right;">Troco</th><th>Criado</th><th style="text-align:right;">Ações</th></tr></thead>
            <tbody>${listHtml || '<tr><td colspan="5" style="text-align:center;">Sem pagamentos</td></tr>'}</tbody>
          </table>
        </div>
        <div class="card" style="margin-top:0.5rem;">
          <h4 style="margin-top:0;">Adicionar pagamento</h4>
          <div style="display:flex; gap:0.5rem; flex-wrap:wrap;">
            <select id="payMetodo" class="input" style="min-width:160px;">
              <option value="">Selecione método</option>
              <option value="dinheiro">Dinheiro</option>
              <option value="cartao_credito">Cartão de Crédito</option>
              <option value="cartao_debito">Cartão de Débito</option>
              <option value="pix">PIX</option>
              <option value="boleto">Boleto</option>
            </select>
            <input id="payValor" class="input" type="number" step="0.01" placeholder="Valor" style="width:140px;" />
            <input id="payTroco" class="input" type="number" step="0.01" placeholder="Troco (opcional)" style="width:160px;" />
            <button class="btn" onclick="createPayment(${orderId})">Adicionar</button>
          </div>
        </div>
        <div style="display:flex; gap:0.5rem; justify-content:flex-end; margin-top:0.75rem;">
          <button class="btn btn-secondary" onclick="closeModal()">Fechar</button>
        </div>
      </div>`;
    openModal('Pagamentos', content);
  } catch(e) {
    hideLoading(); showAlert('Erro ao carregar pagamentos', 'error');
  }
}

async function createPayment(orderId){
  const metodo = document.getElementById('payMetodo')?.value || '';
  const valor = Number(document.getElementById('payValor')?.value || 0);
  const trocoRaw = document.getElementById('payTroco')?.value;
  const troco = trocoRaw === '' ? null : Number(trocoRaw);
  if (!metodo) { showAlert('Selecione o método de pagamento', 'error'); return; }
  if (!valor || valor <= 0) { showAlert('Informe um valor válido', 'error'); return; }
  try {
    showLoading();
    const resp = await apiRequest(`/api/vendas/pedidos/${orderId}/pagamentos`, { method: 'POST', body: JSON.stringify({ metodo, valor, troco }) });
    hideLoading();
    if (!resp || !resp.ok) {
      let msg = 'Falha ao criar pagamento';
      try { const er = await resp.json(); msg = er.error?.message || msg; } catch(_){}
      showAlert(msg, 'error');
      return;
    }
    showAlert('Pagamento adicionado', 'success');
    openPayments(orderId);
    loadOrders();
  } catch(e) {
    hideLoading(); showAlert('Erro ao criar pagamento', 'error');
  }
}

async function deletePayment(paymentId, orderId){
  if (!confirm('Excluir este pagamento?')) return;
  try {
    showLoading();
    const resp = await apiRequest(`/api/vendas/pagamentos/${paymentId}`, { method: 'DELETE' });
    hideLoading();
    if (!resp || !resp.ok) { showAlert('Falha ao excluir pagamento', 'error'); return; }
    showAlert('Pagamento excluído', 'success');
    openPayments(orderId);
    loadOrders();
  } catch(e) {
    hideLoading(); showAlert('Erro ao excluir pagamento', 'error');
  }
}

function openModal(title, innerHtml){
  closeModal();
  const overlay = document.createElement('div');
  overlay.id = 'modalOverlay';
  overlay.style.position = 'fixed';
  overlay.style.inset = '0';
  overlay.style.background = 'rgba(0,0,0,0.35)';
  overlay.style.zIndex = '9999';
  overlay.addEventListener('click', (e) => { if (e.target === overlay) closeModal(); });
  const wrap = document.createElement('div');
  wrap.style.position = 'absolute';
  wrap.style.top = '5%'; wrap.style.left = '50%'; wrap.style.transform = 'translateX(-50%)';
  wrap.style.width = 'min(920px, 94vw)';
  wrap.innerHTML = `
    <div class="card" style="max-height:90vh; overflow:auto;">
      <div style="display:flex; align-items:center; justify-content:space-between; gap:0.75rem;">
        <h2 style="margin:0;">${title||''}</h2>
        <button class="btn btn-secondary" onclick="closeModal()">Fechar</button>
      </div>
      <div style="margin-top:0.5rem;">
        ${innerHtml||''}
      </div>
    </div>`;
  overlay.appendChild(wrap);
  document.body.appendChild(overlay);
  document.addEventListener('keydown', escCloseOnce);
}

function escCloseOnce(ev){ if (ev.key === 'Escape') { closeModal(); } }
function closeModal(){
  const ov = document.getElementById('modalOverlay'); if (ov) ov.remove();
  document.removeEventListener('keydown', escCloseOnce);
}

// Print Order PDF function
async function printOrderPDF(orderId) {
  try {
    // Show loading state
    const button = event.target;
    const originalText = button.textContent;
    button.textContent = 'Gerando...';
    button.disabled = true;

    // Fetch order details
    const orderResponse = await apiRequest(`/api/vendas/pedidos/${orderId}`);
    if (!orderResponse.ok) {
      throw new Error('Erro ao carregar dados do pedido');
    }
    const orderData = await orderResponse.json();
    const order = orderData.data.order;
    const items = orderData.data.items;

    // Fetch client details
    const clientResponse = await apiRequest(`/api/clientes/${order.cliente_id}`);
    let client = { nome: 'Cliente não encontrado' };
    if (clientResponse.ok) {
      const clientData = await clientResponse.json();
      client = clientData.data;
    }

    // Fetch company details (tenant info)
    let company = {
      razao_social: 'Empresa Exemplo Ltda',
      cnpj: '00.000.000/0001-00',
      logradouro: 'Rua Exemplo, 123',
      bairro: 'Centro',
      cidade: 'Cidade Exemplo',
      estado: 'SP',
      cep: '00000-000'
    };

    try {
      const companyResponse = await apiRequest('/api/admin/tenants/summary');
      if (companyResponse.ok) {
        const companyData = await companyResponse.json();
        company = companyData.data;
      }
    } catch (e) {
      console.warn('Não foi possível carregar dados da empresa, usando dados padrão');
    }

    // Fetch product details for each item
    const itemsWithProducts = [];
    for (const item of items) {
      try {
        const productResponse = await apiRequest(`/api/produtos/${item.product_id}`);
        if (productResponse.ok) {
          const productData = await productResponse.json();
          itemsWithProducts.push({
            ...item,
            product: productData.data
          });
        } else {
          // Fallback if product not found
          itemsWithProducts.push({
            ...item,
            product: {
              nome: `Produto ${item.product_id}`,
              codigo: `PROD${item.product_id}`,
              unidade: 'UN'
            }
          });
        }
      } catch (e) {
        // Fallback if product fetch fails
        itemsWithProducts.push({
          ...item,
          product: {
            nome: `Produto ${item.product_id}`,
            codigo: `PROD${item.product_id}`,
            unidade: 'UN'
          }
        });
      }
    }

    // Prepare PDF data (compatível com helper NFePDF)
    const pdfData = {
      company: { ...company, name: company.razao_social || company.name || 'Empresa' },
      client: { ...client },
      details: {
        numero: order.numero || order.id,
        emissao: order.created_at,
        pagamento: 'A combinar'
      },
      items: itemsWithProducts.map(item => ({
        codigo: item.product.codigo || `PROD${item.product_id}`,
        descricao: item.product.nome || `Produto ${item.product_id}`,
        un: item.product.unidade || 'UN',
        quantidade: item.quantidade,
        preco: item.preco,
        total: item.total
      })),
      totals: {
        subtotal: itemsWithProducts.reduce((s, it) => s + Number(it.total||0), 0),
        total: Number(order.valor_total || itemsWithProducts.reduce((s, it) => s + Number(it.total||0), 0))
      },
      observacoes: `Pedido de Venda #${order.numero || order.id}\nStatus: ${order.status || 'Pendente'}`
    };

    // Generate PDF via jsPDF + helper
    if (!window.jspdf || typeof window.jspdf.jsPDF !== 'function') {
      throw new Error('jsPDF não está carregado');
    }
    if (typeof window.NFePDF === 'undefined' || typeof window.NFePDF.draw !== 'function') {
      throw new Error('Biblioteca NFePDF não encontrada');
    }

    const { jsPDF } = window.jspdf;
    const doc = new jsPDF({ unit: 'mm', format: 'a4' });
    window.NFePDF.draw(doc, pdfData);
    const nomeArquivo = `pedido_${String(order.numero || order.id)}.pdf`;
    doc.save(nomeArquivo);

  } catch (error) {
    console.error('Erro ao gerar PDF:', error);
    showAlert('Erro ao gerar PDF: ' + error.message, 'error');
  } finally {
    // Restore button state
    if (typeof button !== 'undefined' && button) {
      button.textContent = originalText;
      button.disabled = false;
    }
  }
}

// ================= NOVAS AÇÕES E UTILITÁRIOS =================
let __userPerms = null; let __userRoles = null;
async function ensureUserContext(){
  if (__userPerms && __userRoles) return;
  try {
    const meRes = await apiRequest('/api/auth/me');
    if (meRes && meRes.ok) {
      const me = await meRes.json();
      const user = me.user || {};
      __userRoles = Array.isArray(user.roles) ? user.roles : [];
      __userPerms = Array.isArray(user.permissions) ? user.permissions : (Array.isArray(user.perms) ? user.perms : []);
    }
  } catch(_){ __userPerms = []; __userRoles = []; }
}
function hasPerm(p){ return (__userRoles||[]).includes('admin') || (__userPerms||[]).includes(p); }

function rowIcon(name){
  const svg = (paths) => `<span class="menu-icon" aria-hidden="true"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${paths.map(p=>`<path d="${p}"/>`).join('')}</svg></span>`;
  switch(name){
    case 'Editar': return svg(['M12 2l3 5 5 3-5 3-3 5-3-5-5-3 5-3 3-5z']);
    case 'Conferência de pedido (Checkout)': return svg(['M3 12l5 5 6-6 7 7']);
    case 'Relatório para separação': return svg(['M4 19V9','M9 19V5','M14 19V12','M19 19V7']);
    case 'Etiquetas dos volumes': return svg(['M4 6h16','M4 12h16','M4 18h16']);
    case 'Etiqueta A4': return svg(['M6 2h12v16H6z']);
    case 'Etiqueta 58mm': return svg(['M4 6h12','M4 12h12','M4 18h12']);
    case 'Etiqueta 80mm': return svg(['M4 6h16','M4 12h16','M4 18h16']);
    case 'Relatório de entrega': return svg(['M4 4h16v6H4z','M4 12h10v8H4z','M16 12h4v8h-4z']);
    case 'Gerar NF-e': return svg(['M6 2h9l5 5v15H6z','M14 2v6h6']);
    case 'Gerar NF-e agrupada por cliente': return svg(['M6 2h9l5 5v15H6z','M14 2v6h6']);
    case 'Gerar NFC-e': return svg(['M6 2h9l5 5v15H6z']);
    case 'Duplicar o pedido': return svg(['M4 4h12v12H4z','M8 8h8']);
    case 'Cópia do pedido': return svg(['M4 4h12v12H4z','M8 8h8']);
    case 'Cópia do pedido (impressora térmica 58/80mm)': return svg(['M4 7h16v10H4z']);
    case 'Gerar cobrança do pedido': return svg(['M12 3v18','M7 8l5-5 5 5']);
    case 'Cadastro do cliente': return svg(['M12 12a5 5 0 1 0-5-5 5 5 0 0 0 5 5z','M2 22c0-5.523 4.477-10 10-10']);
    case 'Agendas (CRM) do cliente': return svg(['M16 11c1.657 0 3-1.79 3-4s-1.343-4-3-4-3 1.79-3 4 1.343 4 3 4z','M2 20c0-4 4-7 9-7']);
    case 'Cobranças do pedido': return svg(['M12 3v18','M7 8l5-5 5 5']);
    case 'Exibir status NF-e do pedido': return svg(['M3 12l5 5 6-6 7 7']);
    case 'Exportar em CSV': return svg(['M3 12l5 5 6-6 7 7']);
    case 'Marcar como lido': return svg(['M4 6h16','M4 12h16','M4 18h16']);
    case 'Marcar como não lido': return svg(['M4 6h16','M4 12h16','M4 18h16']);
    case 'Excluir': return svg(['M3 6h18','M6 6v12','M18 6v12']);
    default: return svg(['M4 6h16']);
  }
}

// Abrir submenu de etiquetas ao passar o mouse/clicar
// Impressão apenas do conteúdo do modal (evita múltiplas folhas)
function printModalContent(){
  try {
    const ov = document.getElementById('modalOverlay');
    const card = ov ? ov.querySelector('.card') : null;
    const html = card ? card.innerHTML : '';
    const w = window.open('', 'PRINT', 'width=900,height=700');
    w.document.write('<html><head><title>Imprimir</title><style>@media print { body{margin:0; } }</style></head><body>' + html + '</body></html>');
    w.document.close();
    w.focus();
    w.print();
    w.close();
  } catch(e) {
    console.warn('printModalContent fallback', e);
    try { PrintControl.safePrint({ copies: 1 }); } catch(_){ try{ window.print(); }catch(__){} }
  }
}

// ==== Novo Pedido ====
async function newOrder(){
  // Redireciona para a nova tela de criação de pedido
  await ensureUserContext(); if (!hasPerm('vendas.create')) { showAlert('Sem permissão para criar pedido', 'error'); return; }
  window.location.href = '/vendas/pedidos/novo';
}
function addNewItemRow(){
  const cont = document.getElementById('newOrderItems'); if (!cont) return;
  const row = document.createElement('div');
  row.className = 'card';
  row.style.display = 'grid';
  row.style.gridTemplateColumns = '1fr 1fr auto';
  row.style.gap = '0.5rem';
  row.innerHTML = `
    <div>
      <label>Produto ID</label>
      <input class="input" type="number" placeholder="ID do produto" data-name="product_id" />
    </div>
    <div>
      <label>Quantidade</label>
      <input class="input" type="number" step="0.001" placeholder="0" data-name="quantidade" />
    </div>
    <div style="display:flex; align-items:flex-end;">
      <button class="btn btn-secondary" type="button" onclick="this.closest('.card').remove()">Remover</button>
    </div>`;
  cont.appendChild(row);
}
async function submitNewOrder(){
  const clienteId = parseInt((document.getElementById('newOrderClienteId')?.value||'0'), 10);
  if (!clienteId || clienteId <= 0) { showAlert('Informe um cliente válido', 'error'); return; }
  const cont = document.getElementById('newOrderItems');
  const rows = Array.from(cont?.children||[]);
  const items = rows.map(r => {
    const pid = parseInt((r.querySelector('[data-name="product_id"]')?.value||'0'), 10);
    const qtd = parseFloat((r.querySelector('[data-name="quantidade"]')?.value||'0'));
    return { product_id: pid, quantidade: qtd };
  }).filter(it => (it.product_id>0 && it.quantidade>0));
  try {
    showLoading();
    const resp = await apiRequest('/api/vendas/pedidos', { method:'POST', body: JSON.stringify({ cliente_id: clienteId, items }) });
    hideLoading();
    if (!resp || !resp.ok) {
      let msg = 'Falha ao criar pedido';
      try { const er = await resp.json(); msg = er.error?.message || msg; } catch(_){}
      showAlert(msg, 'error'); return;
    }
    showAlert('Pedido criado', 'success');
    closeModal();
    loadOrders();
  } catch(e) { hideLoading(); showAlert('Erro ao criar pedido', 'error'); }
}

async function editOrder(id){
  await ensureUserContext(); if (!hasPerm('vendas.update')) { showAlert('Sem permissão para editar', 'error'); return; }
  try {
    showLoading(); const resp = await apiRequest(`/api/vendas/pedidos/${id}`);
    hideLoading(); if (!resp || !resp.ok) { showAlert('Falha ao carregar pedido', 'error'); return; }
    const js = await resp.json(); const order = (js.data||{}).order||{}; const items = (js.data||{}).items||[];
    const disabled = ['faturado','cancelado'].includes(String(order.status||''));
    const itensRows = items.map((it, idx)=>
      `<tr>
        <td><input class="input" type="number" value="${it.product_id}" min="1" step="1" ${disabled?'disabled':''} /></td>
        <td><input class="input" type="number" value="${Number(it.quantidade||0)}" min="0.01" step="0.01" ${disabled?'disabled':''} /></td>
        <td><input class="input" type="number" value="${Number(it.preco||0)}" min="0" step="0.01" ${disabled?'disabled':''} /></td>
        <td style="text-align:right;">R$ ${(Number(it.total||0)).toFixed(2)}</td>
        <td>${disabled?'' : `<button class="btn btn-secondary" type="button" onclick="removeEditItemRow(${idx})">Remover</button>`}</td>
      </tr>`
    ).join('');
    const content = `
      <div class="card">
        <div class="grid" style="grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:0.5rem;">
          <div><label>Status</label><select id="editStatus" class="input" ${disabled?'disabled':''}><option value="aberto">Aberto</option><option value="confirmado">Confirmado</option><option value="faturado">Faturado</option><option value="cancelado">Cancelado</option></select></div>
          <div><label>Observações</label><textarea id="editObs" class="input" rows="3" placeholder="Observações" ${disabled?'disabled':''}></textarea></div>
        </div>
        <div class="table-responsive" style="margin-top:0.75rem;">
          <table class="table" id="editItemsTable"><thead><tr><th>Produto</th><th style="text-align:right;">Qtd</th><th style="text-align:right;">Preço</th><th style="text-align:right;">Total</th><th>Ações</th></tr></thead><tbody>${itensRows||''}</tbody></table>
        </div>
        ${disabled? '<div class="alert alert-error">Pedido não pode ser editado no status atual.</div>' : '<div style="display:flex; gap:0.5rem; margin-top:0.5rem;"><button class="btn btn-secondary" type="button" onclick="addEditItemRow()">Adicionar item</button></div>'}
        <div style="display:flex; gap:0.5rem; justify-content:flex-end; margin-top:0.75rem;">
          <button class="btn" ${disabled?'disabled':''} onclick="saveOrderEdits(${id})">Salvar</button>
          <button class="btn btn-secondary" onclick="closeModal()">Fechar</button>
        </div>
      </div>`;
    openModal(`Editar Pedido #${order.numero||id}`, content);
    setTimeout(() => { const st = document.getElementById('editStatus'); if (st) st.value = String(order.status||'aberto'); }, 50);
    window.__editItemsOrderId = id; window.__editItemsOriginal = items;
  } catch(e){ hideLoading(); showAlert('Erro ao abrir edição', 'error'); }
}
function addEditItemRow(){
  const tb = document.querySelector('#editItemsTable tbody'); if (!tb) return;
  const tr = document.createElement('tr'); tr.innerHTML = `<td><input class="input" type="number" min="1" step="1" /></td><td><input class="input" type="number" min="0.01" step="0.01" /></td><td><input class="input" type="number" min="0" step="0.01" /></td><td></td><td><button class="btn btn-secondary" type="button" onclick="this.closest('tr').remove()">Remover</button></td>`; tb.appendChild(tr);
}
function removeEditItemRow(idx){ const rows = document.querySelectorAll('#editItemsTable tbody tr'); if (rows[idx]) rows[idx].remove(); }
async function saveOrderEdits(id){
  try { const chk = await apiRequest(`/api/vendas/pedidos/${id}`); if (!chk || !chk.ok) { showAlert('Falha ao validar status', 'error'); return; }
    const cj = await chk.json(); const curStatus = String(((cj.data||{}).order||{}).status||'');
    if (['faturado','cancelado'].includes(curStatus)) { showAlert('Pedido não pode ser editado no status atual', 'error'); return; }
  } catch(_){ }
  const status = document.getElementById('editStatus')?.value || 'aberto';
  const observacoes = document.getElementById('editObs')?.value || '';
  const rows = Array.from(document.querySelectorAll('#editItemsTable tbody tr'));
  const items = rows.map(r => {
    const inputs = r.querySelectorAll('input');
    const product_id = Number(inputs[0]?.value||0);
    const quantidade = Number(inputs[1]?.value||0);
    const preco = Number(inputs[2]?.value||0);
    return { product_id, quantidade, preco };
  }).filter(it => it.product_id>0 && it.quantidade>0);
  try {
    showLoading(); const resp = await apiRequest(`/api/vendas/pedidos/${id}`, { method: 'PUT', body: JSON.stringify({ status, observacoes, items }) });
    hideLoading(); if (!resp || !resp.ok) { let msg='Falha ao salvar alterações'; try{ const er=await resp.json(); msg = er.error?.message||msg;}catch(_){ } showAlert(msg, 'error'); return; }
    showAlert('Pedido atualizado', 'success'); closeModal(); loadOrders();
  } catch(e){ hideLoading(); showAlert('Erro ao salvar alterações', 'error'); }
}

async function checkoutOrder(id){
  await ensureUserContext(); if (!hasPerm('vendas.update')) { showAlert('Sem permissão para checkout', 'error'); return; }
  try {
    showLoading(); const resp = await apiRequest(`/api/vendas/pedidos/${id}`); hideLoading(); if (!resp || !resp.ok) { showAlert('Falha ao carregar pedido', 'error'); return; }
    const js = await resp.json(); const order = (js.data||{}).order||{}; const items = (js.data||{}).items||[];
    const itensHtml = items.map((it)=>`<tr><td>${it.product_id}</td><td style="text-align:right;">${Number(it.quantidade||0)}</td><td><input type="checkbox" aria-label="Confirmar" data-product-id="${it.product_id}" /></td></tr>`).join('');
    const content = `
      <div class="card">
        <h3 style="margin-top:0;">Conferência do Pedido ${order.numero||id}</h3>
        <div class="table-responsive"><table class="table"><thead><tr><th>Produto</th><th style="text-align:right;">Qtd</th><th>Confirmar</th></tr></thead><tbody>${itensHtml||'<tr><td colspan="3" style="text-align:center;">Sem itens</td></tr>'}</tbody></table></div>
        <div style="margin-top:0.75rem;">
          <label>Particularidades</label>
          <div id="particularidadesList" style="display:flex; gap:0.5rem; flex-wrap:wrap;"></div>
          <div style="display:flex; gap:0.5rem; margin-top:0.5rem;">
            <input id="novaParticularidade" class="input" type="text" placeholder="Nova particularidade" />
            <button class="btn btn-secondary" type="button" onclick="addParticularidade()">Adicionar</button>
          </div>
        </div>
        <div style="display:flex; gap:0.5rem; justify-content:flex-end; margin-top:0.75rem;">
          <button class="btn" onclick="submitCheckout(${id})">Confirmar Checkout</button>
          <button class="btn btn-secondary" onclick="closeModal()">Fechar</button>
        </div>
      </div>`;
    openModal('Conferência de Pedido', content);
    window.__particularidades = [];
  } catch(e){ hideLoading(); showAlert('Erro ao abrir checkout', 'error'); }
}
function addParticularidade(){
  const inp = document.getElementById('novaParticularidade'); const v = (inp?.value||'').trim(); if (!v) return; window.__particularidades.push(v); inp.value = '';
  const wrap = document.getElementById('particularidadesList'); if (!wrap) return; const tag = document.createElement('span'); tag.className = 'badge'; tag.textContent = v; wrap.appendChild(tag);
}
async function submitCheckout(id){
  const checks = Array.from(document.querySelectorAll('input[type="checkbox"][data-product-id]'));
  const items_confirmed = checks.filter(c => c.checked).map(c => ({ product_id: Number(c.getAttribute('data-product-id')||'0') }));
  const particularidades = Array.isArray(window.__particularidades) ? window.__particularidades : [];
  try { showLoading(); const resp = await apiRequest(`/api/vendas/pedidos/${id}/checkout`, { method:'POST', body: JSON.stringify({ items_confirmed, particularidades }) }); hideLoading(); if (!resp || !resp.ok) { let msg='Falha no checkout'; try{ const er=await resp.json(); msg=er.error?.message||msg;}catch(_){ } showAlert(msg,'error'); return; }
    showAlert('Checkout confirmado', 'success'); closeModal(); loadOrders();
  } catch(e){ hideLoading(); showAlert('Erro no checkout', 'error'); }
}

async function pickingReport(id){
  try {
    showLoading(); const resp = await apiRequest(`/api/vendas/pedidos/${id}`); hideLoading();
    if (!resp || !resp.ok) { showAlert('Falha ao carregar itens', 'error'); return; }
    const js = await resp.json(); const items = (js.data||{}).items||[]; const order = (js.data||{}).order||{};
    let checkout = {}; try { checkout = JSON.parse(order.checkout_json||'{}'); } catch(_){ checkout = {}; }
    const confirmedIds = new Set(((checkout||{}).items_confirmed||[]).map(i => Number(i.product_id||0)));
    const itensHtml = items.map(it => `<tr><td>${it.product_id}</td><td style="text-align:right;">${Number(it.quantidade||0)}</td><td>${(it.localizacao||'-')}</td><td>${confirmedIds.has(Number(it.product_id)) ? '✔️' : '—'}</td></tr>`).join('');
    const content = `
      <div class="card">
        <h3 style="margin-top:0;">Relatório de Separação — Pedido ${order.numero||id}</h3>
        <div class="table-responsive"><table class="table"><thead><tr><th>Produto</th><th style="text-align:right;">Qtd</th><th>Localização</th><th>Conf.</th></tr></thead><tbody>${itensHtml||'<tr><td colspan="4" style="text-align:center;">Sem itens</td></tr>'}</tbody></table></div>
        <div style="margin-top:0.75rem;">
          <label>Assinatura do responsável</label>
          <canvas id="sigCanvasSep" width="600" height="150" style="border:1px dashed #cbd5e1; border-radius:6px; background:#fff;"></canvas>
        </div>
        <div style="display:flex; gap:0.5rem; justify-content:flex-end; margin-top:0.75rem;">
          <button class="btn btn-secondary" onclick="printModalContent()">Imprimir</button>
          <button class="btn btn-secondary" onclick="closeModal()">Fechar</button>
        </div>
      </div>`;
    openModal('Relatório de Separação', content);
    initCanvasSignature('sigCanvasSep');
  } catch(e){ hideLoading(); showAlert('Erro ao gerar relatório de separação', 'error'); }
}

async function labelsVolumes(id, tipo){
  try {
    const resp = await apiRequest(`/api/vendas/pedidos/${id}`);
    if (!resp || !resp.ok) { showAlert('Falha ao carregar pedido', 'error'); return; }
    const js = await resp.json(); const order = (js.data||{}).order||{};
    const volStr = prompt('Quantidade de volumes:', '1'); const vols = Math.max(1, parseInt(volStr||'1',10));
    const labelsHtml = Array.from({length: vols}).map((_,i)=>`
      <div class="card" style="padding:1rem; margin-bottom:0.5rem; border:1px dashed #cbd5e1;">
        <div><strong>Pedido:</strong> ${order.numero||id}</div>
        <div><strong>Cliente:</strong> ${order.cliente_id||'-'}</div>
        <div><strong>Volume:</strong> ${i+1} / ${vols}</div>
        <div><strong>Data:</strong> ${(order.created_at||'').substring(0,10)}</div>
      </div>`).join('');
const content = `<div id="labelsOut" style="${tipo==='58'?'width:58mm':(tipo==='80'?'width:80mm':'width:210mm')};">${labelsHtml}</div><div style="display:flex;justify-content:flex-end;gap:0.5rem;margin-top:0.75rem;"><button class="btn btn-secondary" onclick="safePrint(1)">Imprimir</button><button class="btn btn-secondary" onclick="closeModal()">Fechar</button></div>`;
    openModal('Etiquetas de Volumes', content);
  } catch(e){ showAlert('Erro ao gerar etiquetas', 'error'); }
}

async function deliveryReport(id){
  try {
    showLoading(); const resp = await apiRequest(`/api/vendas/pedidos/${id}`); const orderJs = await resp.json();
    const order = (orderJs.data||{}).order||{}; const clientRes = await apiRequest(`/api/clientes/${order.cliente_id}`); hideLoading();
    let client = {}; if (clientRes && clientRes.ok) { const cj = await clientRes.json(); client = cj.data||{}; }
    const addr = (client.enderecos && client.enderecos.entrega) ? client.enderecos.entrega : (client.enderecos && client.enderecos.principal) ? client.enderecos.principal : {};
    const now = new Date().toISOString().substring(0,19).replace('T',' ');
    const content = `
      <div class="card">
        <h3 style="margin-top:0;">Relatório de Entrega — Pedido ${order.numero||id}</h3>
        <p><strong>Cliente:</strong> ${client.nome||order.cliente_id}</p>
        <p><strong>Endereço:</strong> ${(addr.logradouro||'')} ${(addr.numero||'')} ${(addr.bairro||'')} ${(addr.cidade||'')} ${(addr.estado||'')}</p>
        <p><strong>Contato:</strong> ${(client.telefone||'-')}</p>
        <div class="grid" style="grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:0.5rem; margin-top:0.5rem;">
          <div><label>Data/hora da entrega</label><input id="entregaTs" class="input" type="text" value="${now}" /></div>
          <div><label>Observações</label><textarea id="entregaObs" class="input" rows="3" placeholder="Observações"></textarea></div>
        </div>
        <div style="margin-top:0.75rem;">
          <label>Assinatura do destinatário</label>
          <canvas id="sigCanvasDest" width="600" height="150" style="border:1px dashed #cbd5e1; border-radius:6px; background:#fff;"></canvas>
        </div>
        <div style="display:flex; gap:0.5rem; justify-content:flex-end; margin-top:0.75rem;">
          <button class="btn" onclick="submitDelivery(${id})">Registrar Entrega</button>
          <button class="btn btn-secondary" onclick="printModalContent()">Imprimir</button>
          <button class="btn btn-secondary" onclick="closeModal()">Fechar</button>
        </div>
      </div>`;
    openModal('Relatório de Entrega', content);
    initCanvasSignature('sigCanvasDest');
  } catch(e){ hideLoading(); showAlert('Erro ao montar relatório de entrega', 'error'); }
}
async function submitDelivery(id){
  const obs = document.getElementById('entregaObs')?.value||''; const ts = document.getElementById('entregaTs')?.value||new Date().toISOString();
  const sig = getCanvasSignatureBase64('sigCanvasDest'); if (!sig) { showAlert('Assinatura obrigatória', 'error'); return; }
  try { showLoading(); const resp = await apiRequest(`/api/vendas/pedidos/${id}/entrega`, { method:'POST', body: JSON.stringify({ assinatura_base64: sig, observacoes: obs, data_hora: ts }) }); hideLoading(); if (!resp || !resp.ok) { let msg='Falha ao registrar entrega'; try{ const er=await resp.json(); msg=er.error?.message||msg;}catch(_){ } showAlert(msg,'error'); return; }
    showAlert('Entrega registrada', 'success'); closeModal();
  } catch(e){ hideLoading(); showAlert('Erro ao registrar entrega', 'error'); }
}

async function generateNFe(orderId){
  await ensureUserContext(); if (!hasPerm('fiscal.nfe.emitir')) { showAlert('Sem permissão para NF-e', 'error'); return; }
  if (!confirm('Confirmar emissão de NF-e para este pedido?')) return;
  try {
    showLoading(); const resp = await apiRequest('/api/fiscal/nfe/autorizar', { method:'POST', body: JSON.stringify({ order_id: orderId.toString() }) }); hideLoading();
    const js = await resp.json(); if (!resp.ok) { const msg = js.error?.message || 'Erro na emissão da NF-e'; showAlert(msg, 'error'); return; }
    openModal('NF-e', `<div class="card"><p><strong>Número:</strong> ${js.numero||'-'}</p><p><strong>Chave:</strong> ${js.chave||'-'}</p><p><strong>Data:</strong> ${js.data_emissao||'-'}</p><div style="display:flex;gap:0.5rem;justify-content:flex-end;margin-top:0.75rem;"><button class="btn btn-secondary" onclick="closeModal()">Fechar</button></div></div>`);
    showAlert('NF-e autorizada', 'success');
  } catch(e){ hideLoading(); showAlert('Erro ao emitir NF-e', 'error'); }
}
async function generateNFeGrouped(clientId){
  await ensureUserContext(); if (!hasPerm('fiscal.nfe.emitir')) { showAlert('Sem permissão para NF-e', 'error'); return; }
  const idsStr = prompt('IDs de pedidos para agrupar (separados por vírgula):', (currentRows||[]).filter(r=>Number(r.cliente_id)===Number(clientId)).map(r=>r.id).join(','))||'';
  const order_ids = idsStr.split(',').map(s=>parseInt(s.trim(),10)).filter(n=>n>0);
  if (order_ids.length===0) { showAlert('Nenhum pedido selecionado', 'error'); return; }
  try {
    showLoading(); const resp = await apiRequest('/api/fiscal/nfe/autorizar-agrupada', { method:'POST', body: JSON.stringify({ cliente_id: clientId, order_ids }) }); hideLoading();
    const js = await resp.json(); if (!resp.ok) { const msg = js.error?.message || 'Erro na NF-e agrupada'; showAlert(msg, 'error'); return; }
    openModal('NF-e Agrupada', `<div class="card"><p><strong>Número:</strong> ${js.numero||'-'}</p><p><strong>Chave:</strong> ${js.chave||'-'}</p><p><strong>Data:</strong> ${js.data_emissao||'-'}</p><p><strong>Pedidos:</strong> ${(js.orders||[]).join(', ')}</p><div style="display:flex;gap:0.5rem;justify-content:flex-end;margin-top:0.75rem;"><button class="btn btn-secondary" onclick="closeModal()">Fechar</button></div></div>`);
    showAlert('NF-e agrupada autorizada', 'success');
  } catch(e){ hideLoading(); showAlert('Erro ao emitir NF-e agrupada', 'error'); }
}

async function generateNFCe(orderId){
  await ensureUserContext(); if (!hasPerm('vendas.create')) { showAlert('Sem permissão para NFC-e', 'error'); return; }
  if (!confirm('Confirmar emissão de NFC-e para este pedido?')) return;
  try {
    showLoading(); const resp = await apiRequest('/api/fiscal/nfce/autorizar', { method:'POST', body: JSON.stringify({ sale_id: orderId.toString() }) });
    hideLoading(); const js = await resp.json(); if (!resp.ok) {
      const msgs = (js && js.messages) || (js.error && js.error.message) || 'Erro na emissão da NFC-e';
      const rej = (js && js.rejection_code) ? ` (cód. ${js.rejection_code})` : '';
      showAlert(`Rejeição na NFC-e${rej}: ${Array.isArray(msgs)?msgs.join(' • '):msgs}`, 'error'); return;
    }
    showAlert('NFC-e autorizada', 'success');
    try { window.open('/fiscal/nfce/preview', '_blank'); } catch(_){}
    openModal('NFC-e', `<div class="card"><p><strong>Status:</strong> ${js.status||'-'}</p><p><strong>Chave:</strong> ${js.chave||'-'}</p><p><strong>Protocolo:</strong> ${js.protocolo||'-'}</p><div style="display:flex;gap:0.5rem;justify-content:flex-end;margin-top:0.75rem;"><button class="btn btn-secondary" onclick="closeModal()">Fechar</button></div></div>`);
    loadOrders();
  } catch(e){ hideLoading(); showAlert('Erro ao emitir NFC-e', 'error'); }
}

async function showFiscalStatus(orderId){
  try {
    showLoading();
    // Tentar achar a última emissão vinculada ao pedido
    const resList = await apiRequest(`/api/fiscal/nfce/emissions?sale_id=${orderId}`);
    hideLoading(); if (!resList || !resList.ok) { showAlert('Não foi possível localizar emissão fiscal', 'error'); return; }
    const js = await resList.json(); const row = (js.data && js.data[0]) ? js.data[0] : null;
    if (!row || !row.chave) { showAlert('Pedido sem emissão fiscal vinculada', 'error'); return; }
    const st = await apiRequest(`/api/fiscal/nfce/status/${row.chave}`); if (!st || !st.ok) { showAlert('Falha ao consultar status fiscal', 'error'); return; }
    const sj = await st.json(); const d = sj.data || {};
    openModal('Status Fiscal', `<div class="card"><p><strong>Status:</strong> ${d.status||'-'}</p><p><strong>Chave:</strong> ${d.chave||'-'}</p><p><strong>Protocolo:</strong> ${d.protocolo||'-'}</p><p><strong>Ambiente:</strong> ${d.environment||'-'}</p><div style="display:flex;gap:0.5rem;justify-content:flex-end;margin-top:0.75rem;"><button class="btn btn-secondary" onclick="closeModal()">Fechar</button></div></div>`);
  } catch(e){ hideLoading(); showAlert('Erro ao consultar status fiscal', 'error'); }
}

async function duplicateOrder(id){
  await ensureUserContext(); if (!hasPerm('vendas.create')) { showAlert('Sem permissão para duplicar', 'error'); return; }
  try { showLoading(); const crt = await apiRequest(`/api/vendas/pedidos/${id}/duplicar`, { method:'POST' }); hideLoading(); if (!crt || !crt.ok) { showAlert('Falha ao duplicar pedido', 'error'); return; }
    const nj = await crt.json(); showAlert(`Pedido duplicado (novo ID ${nj.id})`, 'success'); loadOrders();
  } catch(e){ hideLoading(); showAlert('Erro ao duplicar pedido', 'error'); }
}

async function copyOrderThermal(id, tipo){
  try {
    const resp = await apiRequest(`/api/vendas/pedidos/${id}`); if (!resp || !resp.ok) { showAlert('Falha ao carregar pedido', 'error'); return; }
    const js = await resp.json(); const order = (js.data||{}).order||{}; const items = (js.data||{}).items||[];
    if (!window.jspdf || typeof window.jspdf.jsPDF !== 'function') { showAlert('jsPDF não está carregado', 'error'); return; }
    const { jsPDF } = window.jspdf; const format = (tipo==='58' ? [58, 200] : (tipo==='80' ? [80, 200] : 'a4'));
    const doc = new jsPDF({ unit: 'mm', format }); let y = 5;
    doc.setFontSize(10);
    doc.text(`Pedido ${order.numero||id} — Cópia`, 5, y); y+=5; doc.text(`Cliente: ${order.cliente_id}`, 5, y); y+=5;
    items.forEach(it => { doc.text(`${it.product_id} x${it.quantidade} — R$ ${(Number(it.total||0)).toFixed(2)}`, 5, y); y+=5; });
    doc.text(`Total: R$ ${(Number(order.valor_total||0)).toFixed(2)}`, 5, y+2);
    doc.save(`copia_pedido_${order.numero||id}_${tipo}.pdf`);
  } catch(e){ showAlert('Erro ao gerar cópia do pedido', 'error'); }
}

async function generateCharge(orderId){
  // Aponta para integração existente (Asaas)
  generateAsaasLink(orderId);
}

function openClientCadastro(clientId){ if (!clientId) { showAlert('Cliente não informado', 'error'); return; } window.location.href = `/clientes/${clientId}`; }
function openClientCrm(clientId){ if (!clientId) { showAlert('Cliente não informado', 'error'); return; } window.location.href = `/vendas/crm?cliente_id=${clientId}`; }

async function exportOrderCsv(id){
  try {
    const resp = await apiRequest(`/api/vendas/pedidos/${id}`); if (!resp || !resp.ok) { showAlert('Falha ao carregar pedido', 'error'); return; }
    const js = await resp.json(); const order = (js.data||{}).order||{}; const items = (js.data||{}).items||[];
    const rows = [ ['numero','cliente_id','status','valor_total','created_at'], [order.numero||id, order.cliente_id||'', order.status||'', String(order.valor_total||0), (order.created_at||'').replace('T',' ').substring(0,19)] ];
    rows.push(['item_product_id','item_qtd','item_preco','item_total']);
    items.forEach(it => rows.push([it.product_id, String(it.quantidade||0), String(it.preco||0), String(it.total||0)]));
    const csv = rows.map(r => r.map(v => typeof v==='string' && /[,;\t"\n]/.test(v) ? '"'+v.replace(/"/g,'""')+'"' : v).join(';')).join('\n');
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob);
    const a = document.createElement('a'); a.href = url; a.download = `pedido_${order.numero||id}.csv`; a.click(); URL.revokeObjectURL(url);
  } catch(e){ showAlert('Erro ao exportar CSV do pedido', 'error'); }
}

function markOrderRead(id){ try { const s = JSON.parse(localStorage.getItem('orders_read')||'{}'); s[id] = true; localStorage.setItem('orders_read', JSON.stringify(s)); showAlert('Marcado como lido', 'success'); } catch(_){} }
function markOrderUnread(id){ try { const s = JSON.parse(localStorage.getItem('orders_read')||'{}'); delete s[id]; localStorage.setItem('orders_read', JSON.stringify(s)); showAlert('Marcado como não lido', 'success'); } catch(_){} }

async function deleteOrder(id){
  await ensureUserContext(); if (!hasPerm('vendas.delete')) { showAlert('Sem permissão para excluir', 'error'); return; }
  if (!confirm('Excluir este pedido?')) return;
  try { showLoading(); const resp = await apiRequest(`/api/vendas/pedidos/${id}`, { method:'DELETE' }); hideLoading();
    if (!resp || !resp.ok) { showAlert('Falha ao excluir', 'error'); return; }
    showAlert('Pedido excluído', 'success'); loadOrders();
  } catch(e){ hideLoading(); showAlert('Erro ao excluir pedido', 'error'); }
}

// Utilidades de assinatura em Canvas
function initCanvasSignature(id){
  const c = document.getElementById(id); if (!c) return; const ctx = c.getContext('2d'); let drawing = false; let last = null;
  c.addEventListener('mousedown', e => { drawing = true; last = { x: e.offsetX, y: e.offsetY }; });
  c.addEventListener('mouseup', () => { drawing = false; last = null; });
  c.addEventListener('mouseleave', () => { drawing = false; last = null; });
  c.addEventListener('mousemove', e => { if (!drawing) return; const cur = { x: e.offsetX, y: e.offsetY }; ctx.beginPath(); ctx.moveTo(last.x, last.y); ctx.lineTo(cur.x, cur.y); ctx.strokeStyle = '#111827'; ctx.lineWidth = 2; ctx.stroke(); last = cur; });
}
function getCanvasSignatureBase64(id){ const c = document.getElementById(id); if (!c) return ''; try { return c.toDataURL('image/png'); } catch(_){ return ''; } }

document.addEventListener('DOMContentLoaded', () => {
  document.getElementById('btnReload').addEventListener('click', () => { currentPage = 1; loadOrders(); });
  const btnExp = document.getElementById('btnExportCsv'); if (btnExp) btnExp.addEventListener('click', exportOrdersCsv);
  ensureUserContext();
  setTimeout(loadOrders, 80);
});
</script>
<script>
// Envio por e-mail de pedido
async function emailOrder(id){
  try {
    showLoading?.();
    const resp = await apiRequest(`/api/vendas/pedidos/${id}`);
    if (!resp.ok) { hideLoading?.(); showAlert?.('Falha ao carregar pedido', 'error'); return; }
    const js = await resp.json();
    const order = js.data?.order || js.data || {};
    let clientEmail = '';
    let clientName = '';
    if (order.cliente_id) {
      try {
        const cr = await apiRequest(`/api/clientes/${order.cliente_id}`);
        if (cr.ok) { const cd = await cr.json(); clientEmail = cd.data?.email||''; clientName = cd.data?.nome||cd.data?.razao_social||''; }
      } catch(e) {}
    }
    hideLoading?.();
    const defaultSubject = `Pedido ${order.numero || order.id}`;
    const defaultBody = `Olá${clientName? ' ' + clientName : ''},\n\nSegue o resumo do pedido ${order.numero || order.id}.`;
    openModal?.('Enviar por e-mail', `
      <div class="card">
        <div><label>Para</label><input id="emailTo" class="input" type="email" placeholder="email@cliente.com" value="${clientEmail}" /></div>
        <div><label>Assunto</label><input id="emailSubject" class="input" type="text" value="${defaultSubject}" /></div>
        <div><label>Mensagem</label><textarea id="emailBody" class="input" rows="6">${defaultBody}\n\nValor total: R$ ${Number(order.valor_total||0).toLocaleString('pt-BR', { minimumFractionDigits:2 })}\nStatus: ${order.status||''}\nCriado em: ${order.created_at||''}\n\nItens: consulte o anexo ou resumo gerado no sistema.</textarea></div>
        <div style="display:flex;justify-content:flex-end;gap:0.5rem;margin-top:0.75rem;">
          <button class="btn" onclick="submitEmailOrder(${id})">Enviar</button>
          <button class="btn btn-secondary" onclick="closeModal()">Fechar</button>
        </div>
      </div>
    `);
  } catch(e){ hideLoading?.(); showAlert?.('Erro ao preparar envio de e-mail', 'error'); }
}

async function submitEmailOrder(id){
  try {
    showLoading?.();
    const to = document.getElementById('emailTo')?.value?.trim()||'';
    const subject = document.getElementById('emailSubject')?.value?.trim()||'';
    const body = document.getElementById('emailBody')?.value||'';
    const resp = await apiRequest(`/api/vendas/pedidos/${id}/email`, { method: 'POST', body: JSON.stringify({ to, subject, body }) });
    hideLoading?.();
    if (!resp.ok) { let msg='Falha ao enviar e-mail'; try{ const er=await resp.json(); msg = er.error?.message||msg;}catch(_){ } showAlert?.(msg, 'error'); return; }
    showAlert?.('E-mail enviado (gravado para auditoria).', 'success');
    closeModal?.();
  } catch(e){ hideLoading?.(); showAlert?.('Erro ao enviar e-mail', 'error'); }
}
</script>