<?php /* Movimentos de Estoque */ ?>
<div class="card">
  <h1><?= htmlspecialchars($title ?? 'Movimentos de Estoque') ?></h1>
  <div style="display:flex; gap:0.5rem; align-items:center; margin-bottom:1rem;">
    <input id="q" type="text" placeholder="Buscar por produto" style="flex:1; padding:0.5rem;">
    <label for="sepSelect" class="muted">Separador:</label>
    <select id="sepSelect" style="padding:0.4rem;">
      <option value=";">;</option>
      <option value=",">,</option>
      <option value="\t">Tabulação</option>
    </select>
    <label for="typeFilter" class="muted">Tipo</label>
    <select id="typeFilter" style="padding:0.4rem;">
      <option value="">Todos</option>
      <option value="in">Entradas</option>
      <option value="out">Saídas</option>
    </select>
    <label for="startDate" class="muted" title="Filtrar a partir desta data (dd/mm/aaaa). Ao selecionar, a hora atual é capturada automaticamente.">Início</label>
    <input id="startDate" type="date" style="padding:0.4rem;" lang="pt-BR" title="Data inicial (dd/mm/aaaa)" />
    <label for="endDate" class="muted" title="Filtrar até esta data (dd/mm/aaaa). Ao selecionar, a hora atual é capturada automaticamente.">Fim</label>
    <input id="endDate" type="date" style="padding:0.4rem;" lang="pt-BR" title="Data final (dd/mm/aaaa)" />
    <button id="btnExport" class="btn" title="Exportar CSV com filtros aplicados">Exportar CSV</button>
    <button id="btnEntrada" class="btn" title="Abrir formulário para registrar entrada">Registrar Entrada</button>
    <button id="btnSaida" class="btn" title="Abrir formulário para registrar saída">Registrar Saída</button>
  </div>
  <div id="entryPanel" class="muted" style="display:none; padding:0.5rem; border:1px solid var(--border-color,#ddd); border-radius:8px; margin-bottom:1rem;">
    <div style="display:flex; gap:0.5rem; align-items:center; flex-wrap:wrap;">
      <strong id="entryTitle">Registrar</strong>
      <input id="panelProductSearch" type="text" placeholder="Produto: ID, nome ou SKU" title="Digite ao menos 3 caracteres para buscar por nome/SKU ou informe o ID diretamente" autocomplete="off" style="padding:0.4rem; min-width:16rem;">
      <div id="panelProductSuggestions" style="position:relative; min-width:16rem;">
        <div id="panelProductSuggestionsList" style="position:absolute; top:100%; left:0; right:0; background:#fff; border:1px solid #e5e7eb; border-radius:6px; box-shadow:0 8px 24px rgba(0,0,0,0.08); display:none; z-index:100; max-height:240px; overflow:auto;"></div>
      </div>
      <input id="panelProductId" type="number" min="1" placeholder="Produto ID" title="ID do produto" style="padding:0.4rem; width:10rem;">
      <input id="panelQuantity" type="number" min="1" placeholder="Quantidade" title="Quantidade inteira" style="padding:0.4rem; width:10rem;">
      <input id="panelReason" type="text" placeholder="Motivo (opcional)" title="Informe o motivo da movimentação, se desejar" style="padding:0.4rem; min-width:16rem;">
      <button id="panelConfirm" class="btn">Confirmar</button>
      <button id="panelCancel" class="btn">Cancelar</button>
    </div>
    <div class="muted" id="panelFeedback" aria-live="polite"></div>
  </div>
  <div id="feedback" class="muted" aria-live="polite"></div>
  <table class="table" id="tbl">
    <thead>
      <tr>
        <th style="width:2rem;"><input type="checkbox" id="chkAll" title="Selecionar todos" /></th>
        <th>ID</th><th>Produto</th><th>Tipo</th><th>Transação</th><th>Quantidade</th><th>Motivo</th><th>Estoque Antes</th><th>Estoque Depois</th><th>Documento/Origem</th><th>Data</th>
      </tr>
    </thead>
    <tbody id="rows"></tbody>
  </table>
  <div id="massPanel" class="muted" style="display:none; padding:0.5rem; border:1px solid var(--border-color,#ddd); border-radius:8px; margin-top:0.75rem;">
    <div style="display:flex; gap:0.5rem; align-items:center; flex-wrap:wrap;">
      <strong>Alteração em massa</strong>
      <label class="muted" for="massType">Tipo</label>
      <select id="massType" style="padding:0.4rem;">
        <option value="in">Entrada</option>
        <option value="out">Saída</option>
      </select>
      <label class="muted" for="massQty">Quantidade</label>
      <input id="massQty" type="number" min="1" placeholder="Quantidade" style="padding:0.4rem; width:10rem;">
      <input id="massReason" type="text" placeholder="Motivo (opcional)" title="Informe o motivo da movimentação em massa" style="padding:0.4rem; min-width:16rem;">
      <button id="massApply" class="btn">Aplicar nos selecionados</button>
      <button id="massCancel" class="btn">Cancelar</button>
    </div>
    <div class="muted" id="massFeedback" aria-live="polite"></div>
  </div>
  <div id="pagination" class="muted" style="display:flex; gap:0.5rem; align-items:center; margin-top:0.75rem;">
    <button id="btnPrev" class="btn">Anterior</button>
    <button id="btnNext" class="btn">Próxima</button>
    <span id="pageInfo">Página 1</span>
    <label for="perPage" class="muted">Itens por página</label>
    <select id="perPage" style="padding:0.4rem;">
      <option value="10">10</option>
      <option value="20" selected>20</option>
      <option value="50">50</option>
      <option value="100">100</option>
    </select>
  </div>
</div>

<script>
async function apiRequest(url, opts = {}) {
  const res = await fetch(url, { ...opts, headers: { 'Content-Type': 'application/json' } });
  return res;
}
let currentRows = [];
let productNameMap = new Map();
let page = 1; let perPage = 20; let total = 0; let totalPages = 1;

function pad2(n) { return String(n).padStart(2, '0'); }
function combineDateTime(dateStr, timeStr, endOfDay) {
  if (!dateStr) return '';
  const t = timeStr ? timeStr : (endOfDay ? '23:59:59' : '00:00:00');
  // Garantir HH:mm:ss
  const parts = String(t).split(':');
  const hh = pad2(parts[0] || '00');
  const mm = pad2(parts[1] || '00');
  const ss = pad2(parts[2] || '00');
  return `${dateStr}T${hh}:${mm}:${ss}`;
}
function nowTimeString() {
  const d = new Date();
  return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
}
let capturedStartTime = '';
let capturedEndTime = '';

// Painel de entrada/saída (substitui prompt)
let panelMode = null; // 'entrada' | 'saida'
function openEntryPanel(mode) {
  panelMode = mode;
  const panel = document.getElementById('entryPanel');
  const title = document.getElementById('entryTitle');
  const pf = document.getElementById('panelFeedback');
  const pidEl = document.getElementById('panelProductId');
  const qtyEl = document.getElementById('panelQuantity');
  title.textContent = mode === 'saida' ? 'Registrar Saída' : 'Registrar Entrada';
  pidEl.value = '';
  qtyEl.value = '';
  pf.textContent = '';
  panel.style.display = 'block';
  pidEl.focus();
}
function closeEntryPanel() {
  const panel = document.getElementById('entryPanel');
  const pf = document.getElementById('panelFeedback');
  panel.style.display = 'none';
  pf.textContent = '';
  panelMode = null;
}

function fmtTipo(t) {
  const v = String(t || '').toLowerCase();
  if (v === 'in' || v.startsWith('entrada')) return 'Entrada';
  if (v === 'out' || v.startsWith('saida')) return 'Saída';
  return v ? v.charAt(0).toUpperCase() + v.slice(1) : '';
}
function fmtTransacao(t) {
  const v = String(t || '').toLowerCase();
  if (v.includes('entrada') && v.includes('compra')) return 'Entrada de Nota';
  if (v.includes('saida') && v.includes('venda')) return 'Venda Faturada';
  if (v.includes('reserva')) return 'Reserva de Estoque';
  if (v.includes('nota') && v.includes('entrada')) return 'Entrada de Nota';
  if (v.includes('nota') && v.includes('saida')) return 'Saída de Nota';
  if (v === 'in') return 'Entrada (manual)';
  if (v === 'out') return 'Saída (manual)';
  return '';
}

function fmtDateTimeBR(s) {
  if (!s) return '';
  const d = new Date(s);
  if (!isNaN(d)) {
    const dd = String(d.getDate()).padStart(2, '0');
    const mm = String(d.getMonth() + 1).padStart(2, '0');
    const yyyy = d.getFullYear();
    const hh = String(d.getHours()).padStart(2, '0');
    const mi = String(d.getMinutes()).padStart(2, '0');
    const ss = String(d.getSeconds()).padStart(2, '0');
    return `${dd}-${mm}-${yyyy} ${hh}:${mi}:${ss}`;
  }
  const raw = String(s).replace('T', ' ').slice(0, 19);
  const parts = raw.split(/[\s:-]/);
  if (parts.length >= 6) {
    const [Y, M, D, h, m, sec] = parts;
    return `${D}-${M}-${Y} ${h}:${m}:${sec}`;
  }
  return raw;
}

async function getProductName(pid) {
  if (!pid) return '';
  if (productNameMap.has(pid)) return productNameMap.get(pid);
  try {
    const res = await apiRequest(`/api/produtos/${pid}`);
    if (!res || !res.ok) { productNameMap.set(pid, String(pid)); return String(pid); }
    const js = await res.json();
    const d = js.data || {};
    let nome = d.descricao || d.nome || '';
    if (!nome && d.meta_json) {
      try { const meta = JSON.parse(d.meta_json); nome = meta.nome || meta.name || ''; } catch(_) {}
    }
    if (!nome) nome = d.codigo || String(pid);
    productNameMap.set(pid, nome);
    return nome;
  } catch (_) { productNameMap.set(pid, String(pid)); return String(pid); }
}

async function enrichProductNames(rows) {
  const unique = Array.from(new Set(rows.map(r => r.product_id).filter(Boolean)));
  await Promise.all(unique.map(pid => getProductName(pid)));
}

function renderRows(rows) {
  const tbody = document.getElementById('rows');
  tbody.innerHTML = '';
  for (const r of rows) {
    const tr = document.createElement('tr');
    const pnome = productNameMap.get(r.product_id) || r.product_name || r.codigo || r.product_id;
    const tipoRaw = r.type || r.tipo;
    const tipo = fmtTipo(tipoRaw);
    const transacao = fmtTransacao(tipoRaw);
    const data = fmtDateTimeBR(r.created_at || r.data || '');
    const qtd = Number(r.quantity ?? r.quantidade ?? 0);
    const qtdAbs = Math.abs(qtd);
    const motivo = r.motivo || '';
    const sb = (r.stock_before != null) ? Number(r.stock_before) : '';
    const sa = (r.stock_after != null) ? Number(r.stock_after) : '';
    const originType = String(r.origin_type||'');
    const originNumber = String(r.origin_number||'');
    const prefix = originType.includes('purchase') ? 'Nota ' : (originType.includes('sales') ? 'Pedido ' : 'Ref ');
    const docLabel = originNumber ? (prefix + originNumber) : '-';
    const originId = Number(r.origin_id||0);
    let docHref = '';
    if (originId > 0) {
      if (originType.includes('sales')) {
        docHref = `/vendas/pedidos/${originId}/imprimir`;
      } else if (originType.includes('purchase')) {
        // Sem view dedicada para notas de compra; abrir API como fallback
        docHref = `/api/compras/notas/${originId}`;
      }
    }
    tr.innerHTML = `
      <td><input type="checkbox" class="rowChk" data-id="${r.id}" data-pid="${r.product_id}" /></td>
      <td>${r.id}</td>
      <td>${pnome}</td>
      <td>${tipo}</td>
      <td>${transacao}</td>
      <td>${window.fmtQty ? window.fmtQty(qtdAbs) : String(Math.trunc(qtdAbs))}</td>
      <td>${motivo ? motivo : '-'}</td>
      <td>${sb !== '' ? (window.fmtQty ? window.fmtQty(sb) : String(sb)) : '-'}</td>
      <td>${sa !== '' ? (window.fmtQty ? window.fmtQty(sa) : String(sa)) : '-'}</td>
      <td>${docHref ? `<a href="${docHref}" target="_blank" rel="noopener" title="Abrir ${prefix.trim()} ${originNumber}">${docLabel}</a>` : docLabel}</td>
      <td>${data}</td>`;
    tbody.appendChild(tr);
  }
}
async function loadMovements() {
  const fb = document.getElementById('feedback'); fb.textContent = 'Carregando…';
  try {
    const res = await apiRequest(`/api/estoque/movimentos?page=${page}&per_page=${perPage}`);
    if (!res.ok) throw new Error('Falha ao carregar');
    const json = await res.json();
    currentRows = json.data || [];
    total = Number(json.total || currentRows.length || 0);
    totalPages = Math.max(1, Math.ceil(total / perPage));
    await enrichProductNames(currentRows);
    renderRows(currentRows);
    fb.textContent = `${currentRows.length} movimento(s) carregados.`;
    document.getElementById('pageInfo').textContent = `Página ${page} de ${totalPages}`;
    document.getElementById('btnPrev').disabled = page <= 1;
    document.getElementById('btnNext').disabled = page >= totalPages;
  } catch (e) { fb.textContent = 'Erro: ' + e.message; }
}
document.getElementById('q').addEventListener('input', () => {
  const q = document.getElementById('q').value.trim().toLowerCase();
  const type = document.getElementById('typeFilter').value || '';
  const startDate = document.getElementById('startDate').value || '';
  const endDate = document.getElementById('endDate').value || '';
  const start = startDate ? combineDateTime(startDate, capturedStartTime || nowTimeString(), false) : '';
  const end = endDate ? combineDateTime(endDate, capturedEndTime || nowTimeString(), false) : '';
  const rows = currentRows.filter(r => {
    const pnome = productNameMap.get(r.product_id) || '';
    const originNumber = String(r.origin_number||'').toLowerCase();
    const matchQ = (!q) || pnome.toLowerCase().includes(q) || String(r.product_id||'').toLowerCase().includes(q) || originNumber.includes(q);
    const rvType = (r.type || r.tipo || '').toLowerCase();
    const matchType = !type || (rvType === type) || ((type==='in') && rvType.startsWith('entrada')) || ((type==='out') && rvType.startsWith('saida'));
    const dtRow = new Date(r.created_at || r.data || '');
    const startDt = start ? new Date(start) : null;
    const endDt = end ? new Date(end) : null;
    const afterStart = !startDt || (!isNaN(dtRow) && dtRow >= startDt);
    const beforeEnd = !endDt || (!isNaN(dtRow) && dtRow <= endDt);
    return matchQ && matchType && afterStart && beforeEnd;
  });
  renderRows(rows);
});
document.getElementById('typeFilter').addEventListener('change', () => {
  document.getElementById('q').dispatchEvent(new Event('input'));
});
const startDateEl = document.getElementById('startDate');
const endDateEl = document.getElementById('endDate');
if (startDateEl) startDateEl.addEventListener('change', () => { capturedStartTime = nowTimeString(); document.getElementById('q').dispatchEvent(new Event('input')); });
if (endDateEl) endDateEl.addEventListener('change', () => { capturedEndTime = nowTimeString(); document.getElementById('q').dispatchEvent(new Event('input')); });
document.getElementById('btnExport').addEventListener('click', function() {
  const sep = document.getElementById('sepSelect').value || ';';
  const q = document.getElementById('q').value || '';
  const type = document.getElementById('typeFilter').value || '';
  const startDate = document.getElementById('startDate').value || '';
  const endDate = document.getElementById('endDate').value || '';
  const start = startDate ? combineDateTime(startDate, capturedStartTime || nowTimeString(), false) : '';
  const end = endDate ? combineDateTime(endDate, capturedEndTime || nowTimeString(), false) : '';
  const params = new URLSearchParams({ sep, q });
  if (type) params.set('type', type);
  if (start) params.set('start', start);
  if (end) params.set('end', end);
  const url = `/api/estoque/movimentos/export.csv?${params.toString()}`;
  const a = document.createElement('a');
  a.href = url;
  a.download = `estoque_movimentos_${Date.now()}.csv`;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
});
document.getElementById('btnEntrada').addEventListener('click', () => openEntryPanel('entrada'));
document.getElementById('btnSaida').addEventListener('click', () => openEntryPanel('saida'));
document.getElementById('panelCancel').addEventListener('click', closeEntryPanel);
// Botão de alteração em massa
const massButton = document.createElement('button');
massButton.id = 'btnMassEdit';
massButton.className = 'btn';
massButton.textContent = 'Alteração em Massa';
massButton.title = 'Aplicar entrada/saída em lote nos itens selecionados';
document.querySelector('.card > div').appendChild(massButton);
massButton.addEventListener('click', () => {
  const sel = document.querySelectorAll('.rowChk:checked');
  const massPanel = document.getElementById('massPanel');
  const fb = document.getElementById('massFeedback');
  if (!sel.length) { if (window.showAlert) showAlert('Nenhum item selecionado na grid.', 'warning'); else alert('Nenhum item selecionado.'); return; }
  fb.textContent = `Selecionados: ${sel.length} linha(s).`;
  massPanel.style.display = '';
});
document.getElementById('massCancel').addEventListener('click', () => {
  document.getElementById('massPanel').style.display = 'none';
  document.getElementById('massFeedback').textContent = '';
});
document.getElementById('massApply').addEventListener('click', async () => {
  const fb = document.getElementById('massFeedback');
  const qty = Math.trunc(Number(document.getElementById('massQty').value));
  const type = document.getElementById('massType').value;
  const reason = String(document.getElementById('massReason').value||'').trim();
  const sel = Array.from(document.querySelectorAll('.rowChk:checked'));
  const productIds = sel.map(el => Number(el.getAttribute('data-pid'))).filter(v => v > 0);
  if (!qty || qty <= 0) { const msg='Informe quantidade válida (> 0).'; if (window.showAlert) showAlert(msg, 'error'); else alert(msg); return; }
  if (!productIds.length) { const msg='Seleção inválida.'; if (window.showAlert) showAlert(msg, 'error'); else alert(msg); return; }
  fb.textContent = 'Processando lote…';
  try {
    const url = type === 'out' ? '/api/estoque/movimentos/saida' : '/api/estoque/movimentos/entrada';
    await Promise.all(productIds.map(pid => apiRequest(url, { method:'POST', body: JSON.stringify({ product_id: pid, quantity: qty, reason }) })));
    if (window.showAlert) showAlert('Alteração em massa aplicada.', 'success');
    document.getElementById('massPanel').style.display = 'none';
    fb.textContent = '';
    await loadMovements();
  } catch(e) {
    const msg = 'Erro no processamento em massa: ' + (e.message||e);
    fb.textContent = msg;
    if (window.showAlert) showAlert(msg, 'error'); else alert(msg);
  }
});

// Selecionar todos
document.getElementById('chkAll').addEventListener('change', (ev)=>{
  const on = ev.target.checked;
  document.querySelectorAll('.rowChk').forEach(chk => { chk.checked = on; });
});

// Autocomplete de produto no painel
async function searchProducts(term) {
  const url = `/api/produtos?q=${encodeURIComponent(term)}&page=1&per_page=10`;
  const res = await apiRequest(url);
  if (!res.ok) return [];
  const json = await res.json();
  return Array.isArray(json.data) ? json.data : [];
}
function renderPanelSuggestions(items) {
  const list = document.getElementById('panelProductSuggestionsList');
  if (!items.length) { list.style.display='none'; list.innerHTML=''; return; }
  list.innerHTML = items.map(it => {
    const nome = (it.nome || it.descricao || '').toString();
    const codigo = (it.codigo || '').toString();
    return `<div class="suggest-item" data-id="${it.id}" style="padding:0.4rem; cursor:pointer; border-bottom:1px solid #eee;">${codigo ? '['+codigo+'] ' : ''}${nome || ('Produto '+it.id)}</div>`;
  }).join('');
  list.style.display='block';
  list.querySelectorAll('.suggest-item').forEach(el => {
    el.addEventListener('click', () => {
      const pid = Number(el.getAttribute('data-id'));
      document.getElementById('panelProductId').value = String(pid);
      document.getElementById('panelProductSearch').value = '';
      list.style.display='none'; list.innerHTML='';
      const fb = document.getElementById('panelFeedback');
      fb.textContent = `Produto selecionado: ID ${pid}.`;
    });
  });
}
const panelSearchEl = document.getElementById('panelProductSearch');
panelSearchEl.addEventListener('input', async ()=>{
  const term = panelSearchEl.value.trim();
  const list = document.getElementById('panelProductSuggestionsList');
  if (/^\d+$/.test(term)) {
    document.getElementById('panelProductId').value = term;
    list.style.display='none'; list.innerHTML='';
    return;
  }
  if (term.length < 3) { list.style.display='none'; list.innerHTML=''; return; }
  const items = await searchProducts(term);
  renderPanelSuggestions(items);
});
document.getElementById('panelConfirm').addEventListener('click', async () => {
  const pf = document.getElementById('panelFeedback');
  const btn = document.getElementById('panelConfirm');
  const pid = Number(document.getElementById('panelProductId').value);
  const qty = Math.trunc(Number(document.getElementById('panelQuantity').value));
  const reason = String(document.getElementById('panelReason').value||'').trim();
  if (!panelMode) return;
  if (!pid || !qty || qty <= 0) {
    const msg = 'Informe Produto ID e Quantidade válida (> 0).';
    if (window.showAlert) showAlert(msg, 'error'); else alert(msg);
    return;
  }
  try {
    btn.disabled = true; pf.textContent = 'Processando…';
    const url = panelMode === 'saida' ? '/api/estoque/movimentos/saida' : '/api/estoque/movimentos/entrada';
    const res = await apiRequest(url, { method: 'POST', body: JSON.stringify({ product_id: pid, quantity: qty, reason }) });
    if (!res.ok) throw new Error('Falha na operação');
    closeEntryPanel();
    const okMsg = panelMode === 'saida' ? 'Saída registrada com sucesso.' : 'Entrada registrada com sucesso.';
    if (window.showAlert) showAlert(okMsg, 'success');
    await loadMovements();
  } catch (e) {
    const err = 'Erro: ' + (e.message || e);
    pf.textContent = err;
    if (window.showAlert) showAlert(err, 'error'); else alert(err);
  } finally {
    btn.disabled = false;
  }
});
setTimeout(loadMovements, 50);
document.getElementById('btnPrev').addEventListener('click', async ()=>{ if (page>1) { page--; await loadMovements(); } });
document.getElementById('btnNext').addEventListener('click', async ()=>{ if (page<totalPages) { page++; await loadMovements(); } });
document.getElementById('perPage').addEventListener('change', async (ev)=>{ perPage = Math.max(1, parseInt(ev.target.value||'20',10)); page = 1; await loadMovements(); });
</script>