<?php /** @var string $title */ ?>
<main class="container">
  <header class="page-header">
    <h1><?= htmlspecialchars($title ?? 'Serviços: Ordens de Serviço') ?></h1>
    <p class="muted">Acompanhe, crie e atualize ordens de serviço.</p>
  </header>

  <section class="card">
    <div class="grid" style="align-items:flex-end;grid-template-columns: 1fr auto auto; gap: .5rem;">
      <div>
        <label class="muted" for="q">Filtrar</label>
        <input id="q" type="text" placeholder="Placa, modelo ou status" />
      </div>
      <div style="display:flex; gap:.5rem;">
        <button id="btnReload" class="btn">Recarregar</button>
        <button id="btnClear" class="btn btn-outline">Limpar</button>
      </div>
      <div style="display:flex; gap:.5rem;">
        <button id="btnNew" class="btn">Nova OS</button>
      </div>
    </div>
  </section>

  <section class="card">
    <table class="table">
      <thead>
        <tr><th>#</th><th>Placa</th><th>Modelo</th><th>Status</th><th>Cliente</th><th>Técnico</th><th>Abertura</th><th>Ações</th></tr>
      </thead>
      <tbody id="rows"><tr><td colspan="8" class="muted">Carregando…</td></tr></tbody>
    </table>
    <div id="ordersError" style="display:none;margin:.5rem 0;padding:.5rem;border:1px solid #b00;color:#b00;background:#fee;border-radius:.25rem;"></div>
    <div id="ordersPager" style="display:flex; gap:.5rem; align-items:center; justify-content:flex-end; margin-top:.5rem;">
      <label class="muted">Itens por página</label>
      <select id="ordersPerPage" style="min-width:5rem;">
        <option value="10" selected>10</option>
        <option value="20">20</option>
        <option value="50">50</option>
      </select>
      <button id="ordersPrev" class="btn btn-outline">Anterior</button>
      <span id="ordersPageInfo" class="muted">Página 1 de 1</span>
      <button id="ordersNext" class="btn btn-outline">Próxima</button>
    </div>
  </section>
</main>

<dialog id="newDialog" class="modal">
  <div class="modal-toolbar">
    <button type="button" class="btnSmall" data-action="minimize" title="Minimizar">_</button>
    <button type="button" class="btnSmall" data-action="maximize" title="Maximizar">□</button>
    <button type="button" class="btnSmall" data-action="close" title="Fechar">×</button>
  </div>
  <form method="dialog" id="newForm">
    <h3>Nova Ordem de Serviço</h3>
    <div class="grid" style="grid-template-columns:repeat(2, minmax(0,1fr)); gap: .5rem;">
      <div>
        <label class="muted">Placa</label>
        <div style="display:flex; gap:.5rem; align-items:center;">
          <input id="osPlaca" type="text" placeholder="ABC1D23" />
          <button type="button" id="btnLookupOs">Consultar</button>
        </div>
        <small id="osPlacaStatus" class="muted"></small>
      </div>
      <div><label class="muted">Veículo ID</label><input name="vehicle_id" type="number" placeholder="ID do veículo" required /></div>
      <div>
        <label class="muted">Cliente</label>
        <input id="osClienteNome" type="text" placeholder="Buscar cliente por nome/CPF/CNPJ" autocomplete="off" />
        <input name="cliente_id" id="osClienteIdHidden" type="hidden" />
      </div>
      <div style="grid-column: 1 / -1;"><label class="muted">Descrição</label><textarea name="descricao" rows="3" placeholder="Serviços, queixas ou observações"></textarea></div>
      <div><label class="muted">Técnico</label><input name="tecnico" type="text" placeholder="Responsável" /></div>
    </div>
    <footer style="margin-top:.75rem; display:flex; gap:.5rem; justify-content:flex-end;">
      <button type="button" id="btnCancel" class="btn btn-outline">Cancelar</button>
      <button type="submit" id="btnSave" class="btn">Salvar</button>
    </footer>
  </form>
</dialog>

<script>
// Garantir attachAutocomplete disponível mesmo que o layout carregue depois
if (typeof window.attachAutocomplete !== 'function') {
  window.attachAutocomplete = function(input, options){
    const cfg = Object.assign({ minChars: 3, fetch: null, onSelect: null, placeholder: 'Digite para buscar…' }, options||{});
    if (!input || typeof cfg.fetch !== 'function') return;
    let list = document.createElement('div');
    list.className = 'autocomplete-list';
    list.style.display = 'none';
    input.parentNode.style.position = input.parentNode.style.position || 'relative';
    input.parentNode.appendChild(list);
    let timer;
    const closeList = ()=>{ list.style.display='none'; list.innerHTML=''; };
    input.addEventListener('input', async ()=>{
      const term = input.value.trim();
      if (!term || term.length < cfg.minChars) { closeList(); return; }
      clearTimeout(timer);
      timer = setTimeout(async ()=>{
        try {
          list.innerHTML = `<div class="item muted">${cfg.placeholder}</div>`;
          list.style.display = 'block';
          const items = await cfg.fetch(term);
          if (!items || items.length === 0) { list.innerHTML = '<div class="item muted">Sem resultados</div>'; return; }
          list.innerHTML = items.map(it => `<div class="item" data-id="${String(it.id||'')}">${String(it.label||it.nome||it.name||'')}</div>`).join('');
          list.querySelectorAll('.item').forEach(el=>{
            el.addEventListener('click', ()=>{
              const id = el.getAttribute('data-id');
              const text = el.textContent;
              if (typeof cfg.onSelect === 'function') cfg.onSelect({ id, label: text });
              input.value = text;
              closeList();
            });
          });
        } catch(err){
          list.innerHTML = '<div class="item muted">Erro na busca</div>';
        }
      }, 250);
    });
    input.addEventListener('blur', ()=>{ setTimeout(closeList, 150); });
  }
}
async function apiRequest(url, options){ if (typeof window.apiRequest === 'function') { return window.apiRequest(url, options); } const base='/api'; const opts=options||{}; const headers=opts.headers||{}; if(!(opts.body instanceof FormData)) headers['Content-Type']=headers['Content-Type']||'application/json'; return fetch(base+url,{...opts, headers, credentials:'include'}); }
function escapeHtml(s){ return String(s||'').replace(/[&<>"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c])); }
function setError(id,msg){ const el=document.getElementById(id); if(!el) return; if(msg){ el.textContent=msg; el.style.display='block'; } else { el.textContent=''; el.style.display='none'; } }
function fmtRows(data){ const q=document.getElementById('q').value.trim().toLowerCase(); return (data||[]).filter(r=> !q || String(r.placa||'').toLowerCase().includes(q) || String(r.modelo||'').toLowerCase().includes(q) || String(r.status||'').toLowerCase().includes(q)).map(r=>{
  const canEmit = !['faturada','cancelada'].includes(String(r.status||''));
  const actions = [
    `<button onclick="openStatusDialog(${r.id}, '${escapeHtml(r.status||'')}')">Atualizar Status</button>`,
    `<button onclick="openTecnicoDialog(${r.id}, '${escapeHtml(r.tecnico_responsavel||'')}')">Designar Técnico</button>`,
    (canEmit ? `<button onclick="emitirNfse(${r.id})">Emitir NFS-e</button>` : '<span class="muted">—</span>'),
    (canEmit ? `<button onclick="openFaturarDialog(${r.id})">Faturar OS</button>` : '')
  ].join(' ');
  const cliente = (r.cliente_nome || r.cliente_id || '-');
  return `<tr><td>${r.id}</td><td>${escapeHtml(r.placa||'-')}</td><td>${escapeHtml(r.modelo||'-')}</td><td>${escapeHtml(r.status||'-')}</td><td>${escapeHtml(cliente)}</td><td>${escapeHtml(r.tecnico_responsavel||'-')}</td><td>${escapeHtml(r.aberta_em||'-')}</td><td>${actions}</td></tr>`;
}).join(''); }
// Estado de paginação e leitura inicial da URL
const __params = new URLSearchParams(window.location.search||'');
document.getElementById('q').value = __params.get('q') || '';
let ordersPage = Number(__params.get('page')||__params.get('orders_page')||1) || 1;
let ordersPerPage = Number(__params.get('per_page')||__params.get('orders_per_page')||10) || 10;
let ordersTotalPages = 1;
async function load(){
  try {
    document.getElementById('rows').innerHTML = '<tr><td colspan="8" class="muted">Carregando…</td></tr>';
    setError('ordersError','');
    const qVal = document.getElementById('q').value.trim();
    const params = new URLSearchParams();
    params.set('page', String(ordersPage));
    params.set('per_page', String(ordersPerPage));
    if (qVal) params.set('q', qVal);
    const resp = await apiRequest('/api/servicos/ordens?'+params.toString());
    if (resp.status === 401) {
      alert('Sessão expirada ou ausente. Faça login para visualizar Serviços.');
      window.location.href = '/login?next=' + encodeURIComponent('/servicos/ordens');
      return;
    }
    if (!resp.ok) { const txt = await resp.text().catch(()=> ''); setError('ordersError', `Erro ${resp.status}: ${txt.slice(0,200)}`); document.getElementById('rows').innerHTML = '<tr><td colspan="8" class="muted">Erro ao carregar</td></tr>'; return; }
    const json = await resp.json();
    const rows = fmtRows(json.data||[]);
    document.getElementById('rows').innerHTML = rows || '<tr><td colspan="8" class="muted">Sem dados</td></tr>';
    // Atualiza paginação
    ordersTotalPages = Number(json.total_pages || json.totalPages || 1) || 1;
    const curPage = Number(json.page || ordersPage || 1) || 1;
    ordersPage = curPage;
    const info = document.getElementById('ordersPageInfo'); if (info) info.textContent = `Página ${ordersPage} de ${ordersTotalPages}`;
    const prev = document.getElementById('ordersPrev'); if (prev) prev.disabled = ordersPage <= 1;
    const next = document.getElementById('ordersNext'); if (next) next.disabled = ordersPage >= ordersTotalPages;
    // Persistir na URL
    const qs = new URLSearchParams(window.location.search||''); qs.set('page', String(ordersPage)); qs.set('per_page', String(ordersPerPage)); if (qVal) qs.set('q', qVal); else qs.delete('q'); window.history.replaceState(null,'', window.location.pathname+'?'+qs.toString());
  } catch(e) {
    document.getElementById('rows').innerHTML = '<tr><td colspan="8" class="muted">Erro ao carregar</td></tr>';
    setError('ordersError', 'Falha ao carregar ordens: '+(e&&e.message?e.message:'erro desconhecido'));
  }
}

document.getElementById('btnReload').addEventListener('click', load);
document.getElementById('btnClear').addEventListener('click', ()=>{ try { document.getElementById('q').value=''; ordersPage=1; const qs=new URLSearchParams(window.location.search||''); qs.delete('q'); qs.set('page','1'); window.history.replaceState(null,'', window.location.pathname+'?'+qs.toString()); load(); } catch(e){ load(); } });
document.getElementById('q').addEventListener('input', ()=>{ clearTimeout(window.__t); window.__t=setTimeout(()=>{ ordersPage=1; load(); },220); });
// Eventos de paginação
document.getElementById('ordersPerPage').addEventListener('change', (e)=>{ ordersPerPage = Number(e.target.value||10); ordersPage = 1; load(); });
document.getElementById('ordersPrev').addEventListener('click', ()=>{ if (ordersPage > 1) { ordersPage--; load(); } });
document.getElementById('ordersNext').addEventListener('click', ()=>{ if (ordersPage < ordersTotalPages) { ordersPage++; load(); } });
document.getElementById('btnNew').addEventListener('click', ()=>{ if (typeof window.openModalById === 'function') window.openModalById('newDialog'); else { const d=document.getElementById('newDialog'); if (d && typeof d.showModal==='function') d.showModal(); else if (d && typeof d.show==='function') d.show(); else if (d) d.setAttribute('open',''); } });
document.getElementById('btnCancel').addEventListener('click', ()=>{ document.getElementById('newDialog').close(); });
// Botão Seed removido: seed deve ocorrer via script CLI, não pela UI
document.getElementById('newForm').addEventListener('submit', async (e)=>{
  e.preventDefault(); const fd=new FormData(e.currentTarget); const body={ vehicle_id: Number(fd.get('vehicle_id')), cliente_id: fd.get('cliente_id')?Number(fd.get('cliente_id')):null, descricao: fd.get('descricao'), tecnico: fd.get('tecnico') };
  const resp = await apiRequest('/api/servicos/ordens', { method:'POST', body: JSON.stringify(body) });
  if (resp.ok) { document.getElementById('newDialog').close(); setTimeout(load, 100); } else { alert('Falha ao salvar'); }
});
setTimeout(load, 50);
// Abrir modal Nova OS via query param new=1
(function(){ try { const params = new URLSearchParams(window.location.search||''); if (params.get('new') === '1') { const b=document.getElementById('btnNew'); if (b) b.click(); } } catch(e){} })();
async function emitirNfse(id){ try { const resp = await apiRequest(`/api/servicos/ordens/${id}/emitir-nfs-e`, { method:'POST' }); if (resp.ok) { const j=await resp.json(); alert('NFS-e emitida. Nº: '+(j.nfse?.numero||'-')); load(); } else { const e=await resp.json().catch(()=>({})); alert('Falha: '+(e.error?.message||resp.status)); } } catch(err){ alert('Erro ao emitir NFS-e'); } }
function normalizePlate(v){ return String(v||'').toUpperCase().replace(/[^A-Z0-9]/g,''); }
function isValidPlate(v){ const s=normalizePlate(v); return /^[A-Z]{3}[0-9]{4}$/.test(s) || /^[A-Z]{3}[0-9][A-Z][0-9]{2}$/.test(s); }
document.getElementById('osPlaca').addEventListener('input', (e)=>{
  const v=e.target.value; const el=document.getElementById('osPlacaStatus');
  if (!v) { el.textContent=''; return; }
  if (isValidPlate(v)) { el.textContent='Formato válido'; el.style.color='var(--muted)'; }
  else { el.textContent='Placa inválida'; el.style.color='#b00'; }
});
document.getElementById('btnLookupOs').addEventListener('click', async ()=>{
  const v = document.getElementById('osPlaca').value.trim(); const el=document.getElementById('osPlacaStatus');
  if (!isValidPlate(v)) { el.textContent='Informe uma placa válida para consultar'; el.style.color='#b00'; return; }
  el.textContent='Consultando…'; el.style.color='var(--muted)';
  try {
    const norm = normalizePlate(v);
    const resp = await apiRequest(`/api/servicos/veiculos/placa/${encodeURIComponent(norm)}`);
    const j = await resp.json();
    if (resp.ok && j.ok) {
      if (j.source === 'db' && j.data && j.data.id) {
        document.querySelector('[name="vehicle_id"]').value = j.data.id;
        el.textContent='Veículo encontrado e selecionado'; el.style.color='var(--muted)';
      } else {
        el.textContent='Veículo não cadastrado. Cadastre o veículo primeiro.'; el.style.color='#b00';
      }
    } else {
      el.textContent = j.error ? ('Falha: '+j.error) : 'Não encontrado'; el.style.color='#b00';
    }
  } catch(e) { el.textContent='Erro na consulta'; el.style.color='#b00'; }
});

// Autocomplete para Placa (busca veículos)
attachAutocomplete(document.getElementById('osPlaca'), {
  minChars: 3,
  fetch: async (term) => {
    const resp = await apiRequest(`/api/servicos/veiculos?q=${encodeURIComponent(term)}`);
    const j = await resp.json();
    return (j.data||[]).slice(0,8).map(v => ({ id: v.id, label: `${v.placa||'-'} — ${v.modelo||'-'}` }));
  },
  onSelect: ({ id, label }) => {
    document.querySelector('[name="vehicle_id"]').value = id || '';
    document.getElementById('osPlacaStatus').textContent = 'Veículo selecionado via autocomplete';
  }
});

// Autocomplete para Técnico
attachAutocomplete(document.querySelector('[name="tecnico"]'), {
  minChars: 3,
  fetch: async (term) => {
    const resp = await apiRequest(`/api/cadastros/tecnicos?q=${encodeURIComponent(term)}&page=1&per_page=10`);
    const j = await resp.json();
    return (j.data||[]).slice(0,8).map(t => ({ id: t.id, label: t.nome||t.name||'-' }));
  },
  onSelect: ({ id, label }) => {
    const inp=document.querySelector('[name="tecnico"]'); inp.value = label;
    document.getElementById('osPlacaStatus').textContent = '';
  }
});

// Autocomplete para Cliente (Nova OS)
attachAutocomplete(document.getElementById('osClienteNome'), {
  minChars: 3,
  fetch: async (term) => {
    const resp = await apiRequest(`/api/clientes?q=${encodeURIComponent(term)}&page=1&per_page=10`);
    const j = await resp.json();
    return (j.data||[]).slice(0,8).map(c => ({ id: c.id, label: (c.nome||c.nome_fantasia||c.razao_social||c.cnpj||c.cpf||'-') }));
  },
  onSelect: ({ id, label }) => {
    document.getElementById('osClienteIdHidden').value = id || '';
  }
});
// Ao digitar manualmente, limpar seleção do cliente
document.getElementById('osClienteNome').addEventListener('input', ()=>{
  document.getElementById('osClienteIdHidden').value = '';
});
</script>
<dialog id="itensDialog" class="modal">
  <div class="modal-toolbar">
    <button type="button" class="btnSmall" data-action="minimize" title="Minimizar">_</button>
    <button type="button" class="btnSmall" data-action="maximize" title="Maximizar">□</button>
    <button type="button" class="btnSmall" data-action="close" title="Fechar">×</button>
  </div>
  <form method="dialog" id="itensForm">
    <h3>Itens da OS</h3>
    <input type="hidden" name="order_id" />
    <div id="itensList" class="card" style="margin:.5rem 0; overflow:auto; max-height:40vh;">
      <table class="table">
        <thead>
          <tr><th>ID</th><th>Produto</th><th>Descrição</th><th>Qtd</th><th>Valor Unit.</th><th>Subtotal</th><th>Ações</th></tr>
        </thead>
        <tbody id="itensRows"><tr><td colspan="7" class="muted">Carregando…</td></tr></tbody>
      </table>
    </div>
    <fieldset class="card" style="margin:.5rem 0;">
      <legend>Adicionar item</legend>
      <div class="grid" style="grid-template-columns:repeat(2,minmax(0,1fr)); gap:.5rem;">
        <div>
          <label class="muted">Produto ID</label>
          <input type="number" name="product_id" placeholder="Opcional: ID do produto" />
          <small class="muted">Se informado, a descrição será puxada do produto.</small>
        </div>
        <div>
          <label class="muted">Descrição</label>
          <input type="text" name="descricao" placeholder="Obrigatório se não houver produto" />
        </div>
        <div>
          <label class="muted">Quantidade</label>
          <input type="number" name="quantidade" step="0.01" min="0" placeholder="Ex.: 1" required />
        </div>
        <div>
          <label class="muted">Valor unitário (R$)</label>
          <input type="text" name="valor_unit" placeholder="Ex.: 199,90" required />
        </div>
      </div>
    </fieldset>
    <footer style="margin-top:.75rem; display:flex; gap:.5rem; justify-content:flex-end;">
      <button type="button" id="btnItensClose" class="btn btn-outline">Fechar</button>
      <button type="submit" id="btnItensAdd" class="btn">Adicionar</button>
    </footer>
  </form>
</dialog>

<script>
function openItensDialog(orderId){ const d=document.getElementById('itensDialog'); d.querySelector('[name="order_id"]').value=String(orderId); d.showModal(); loadItens(orderId); }
document.getElementById('btnItensClose').addEventListener('click', ()=> document.getElementById('itensDialog').close());
function toCents(brl){ const s=String(brl||'').trim(); if(!s) return 0; const n=parseFloat(s.replace(/\./g,'').replace(',','.')); if(isNaN(n)||!isFinite(n)) return 0; return Math.round(n*100); }
async function loadItens(orderId){ const rowsEl=document.getElementById('itensRows'); try { const resp=await apiRequest(`/api/servicos/ordens/${orderId}/itens`); const j=await resp.json(); const items=(j.data||[]); if(items.length===0){ rowsEl.innerHTML='<tr><td colspan="7" class="muted">Sem itens</td></tr>'; return; } rowsEl.innerHTML = items.map(it=>{
  const prod = it.product_id ? `${escapeHtml(it.product_codigo||'')} (#${it.product_id})` : '-';
  const vu = (Number(it.valor_unit_cents||0)/100).toLocaleString('pt-BR',{style:'currency',currency:'BRL'});
  const st = (Number(it.subtotal_cents||0)/100).toLocaleString('pt-BR',{style:'currency',currency:'BRL'});
  return `<tr>
    <td>${it.id}</td>
    <td>${prod}</td>
    <td>${escapeHtml(it.descricao||'')}</td>
    <td>${escapeHtml(it.quantidade||'')}</td>
    <td>${vu}</td>
    <td>${st}</td>
    <td><button data-action="del" data-item-id="${it.id}" data-order-id="${orderId}">Remover</button></td>
  </tr>`; }).join('');
  // Bind delete
  rowsEl.querySelectorAll('button[data-action="del"]').forEach(btn=>{
    btn.addEventListener('click', async (e)=>{
      const itemId=Number(e.currentTarget.getAttribute('data-item-id')); const oid=Number(e.currentTarget.getAttribute('data-order-id'));
      if(!confirm('Remover este item?')) return;
try { const resp=await apiRequest(`/api/servicos/ordens/${oid}/itens/${itemId}`, { method:'DELETE' }); if(resp.ok){ await loadItens(oid); setTimeout(load, 50); } else { alert('Falha ao remover item'); } } catch(err){ alert('Erro ao remover item'); }
    });
  });
} catch(err){ rowsEl.innerHTML='<tr><td colspan="7" class="muted">Erro ao carregar itens</td></tr>'; }
}

document.getElementById('itensForm').addEventListener('submit', async (e)=>{
  e.preventDefault(); const fd=new FormData(e.currentTarget); const orderId=Number(fd.get('order_id'));
  const product_id = fd.get('product_id') ? Number(fd.get('product_id')) : null;
  const descricao = String(fd.get('descricao')||'').trim();
  const quantidade = Number(String(fd.get('quantidade')||'').replace(',','.'));
  const valor_unit_cents = toCents(fd.get('valor_unit'));
  if(!product_id && descricao===''){ alert('Informe descrição ou um produto'); return; }
  if(!(quantidade>0)){ alert('Quantidade deve ser maior que zero'); return; }
  try {
    const body = { product_id, descricao: product_id?undefined:descricao, quantidade, valor_unit_cents };
const resp = await apiRequest(`/api/servicos/ordens/${orderId}/itens`, { method:'POST', body: JSON.stringify(body) });
    const j = await resp.json().catch(()=>({}));
    if(resp.ok && j.ok){ await loadItens(orderId); setTimeout(load, 50); e.target.reset(); }
    else { alert('Falha ao adicionar item: '+(j.error?.message||resp.status)); }
  } catch(err){ alert('Erro ao adicionar item'); }
});
</script>
<dialog id="statusDialog" class="modal">
  <div class="modal-toolbar">
    <button type="button" class="btnSmall" data-action="minimize" title="Minimizar">_</button>
    <button type="button" class="btnSmall" data-action="maximize" title="Maximizar">□</button>
    <button type="button" class="btnSmall" data-action="close" title="Fechar">×</button>
  </div>
  <form method="dialog" id="statusForm">
    <h3>Atualizar Status da OS</h3>
    <input type="hidden" name="order_id" />
    <div>
      <label class="muted">Status</label>
      <select name="status">
        <option value="aberta">Aberta</option>
        <option value="em_andamento">Em andamento</option>
        <option value="aguardando">Aguardando</option>
        <option value="concluida">Concluída</option>
        <option value="faturada">Faturada</option>
        <option value="cancelada">Cancelada</option>
      </select>
    </div>
    <footer style="margin-top:.75rem; display:flex; gap:.5rem; justify-content:flex-end;">
      <button type="button" id="btnStatusCancel" class="btn btn-outline">Cancelar</button>
      <button type="submit" id="btnStatusSave" class="btn">Salvar</button>
    </footer>
  </form>
  </dialog>

<dialog id="tecnicoDialog" class="modal">
  <div class="modal-toolbar">
    <button type="button" class="btnSmall" data-action="minimize" title="Minimizar">_</button>
    <button type="button" class="btnSmall" data-action="maximize" title="Maximizar">□</button>
    <button type="button" class="btnSmall" data-action="close" title="Fechar">×</button>
  </div>
  <form method="dialog" id="tecnicoForm">
    <h3>Designar Técnico</h3>
    <input type="hidden" name="order_id" />
    <div>
      <label class="muted">Técnico responsável</label>
      <input name="tecnico" type="text" placeholder="Nome ou identificação" />
    </div>
    <footer style="margin-top:.75rem; display:flex; gap:.5rem; justify-content:flex-end;">
      <button type="button" id="btnTecnicoCancel" class="btn btn-outline">Cancelar</button>
      <button type="submit" id="btnTecnicoSave" class="btn">Salvar</button>
    </footer>
  </form>
  </dialog>

<script>
function openStatusDialog(id, current){ const d=document.getElementById('statusDialog'); d.querySelector('[name="order_id"]').value = String(id); const sel=d.querySelector('[name="status"]'); if (current) { sel.value = current; } d.showModal(); }
document.getElementById('btnStatusCancel').addEventListener('click', ()=> document.getElementById('statusDialog').close());
document.getElementById('statusForm').addEventListener('submit', async (e)=>{
  e.preventDefault(); const fd=new FormData(e.currentTarget); const id=Number(fd.get('order_id')); const status=String(fd.get('status'));
const resp = await apiRequest(`/api/servicos/ordens/${id}/status`, { method:'POST', body: JSON.stringify({ status }) });
  if (resp.ok) { document.getElementById('statusDialog').close(); load(); } else { alert('Falha ao atualizar status'); }
});

function openTecnicoDialog(id, current){ const d=document.getElementById('tecnicoDialog'); d.querySelector('[name="order_id"]').value = String(id); const inp=d.querySelector('[name="tecnico"]'); inp.value = current||''; d.showModal(); }
document.getElementById('btnTecnicoCancel').addEventListener('click', ()=> document.getElementById('tecnicoDialog').close());
document.getElementById('tecnicoForm').addEventListener('submit', async (e)=>{
  e.preventDefault(); const fd=new FormData(e.currentTarget); const id=Number(fd.get('order_id')); const tecnico=String(fd.get('tecnico'));
const resp = await apiRequest(`/api/servicos/ordens/${id}/tecnico`, { method:'POST', body: JSON.stringify({ tecnico }) });
  if (resp.ok) { document.getElementById('tecnicoDialog').close(); load(); } else { alert('Falha ao designar técnico'); }
});
</script>
<dialog id="faturarDialog" class="modal">
  <div class="modal-toolbar">
    <button type="button" class="btnSmall" data-action="minimize" title="Minimizar">_</button>
    <button type="button" class="btnSmall" data-action="maximize" title="Maximizar">□</button>
    <button type="button" class="btnSmall" data-action="close" title="Fechar">×</button>
  </div>
  <form method="dialog" id="faturarForm">
    <h3>Faturar Ordem de Serviço</h3>
    <input type="hidden" name="order_id" />
    <div class="grid" style="grid-template-columns: repeat(2, minmax(0,1fr)); gap: .5rem;">
      <div>
        <label class="muted">Data de vencimento</label>
        <input type="date" name="data_vencimento" />
        <small class="muted">Padrão: +7 dias se não informado</small>
      </div>
      <div style="grid-column: 1 / -1;">
        <label class="muted">Observações</label>
        <textarea name="observacoes" rows="3" placeholder="Opcional"></textarea>
      </div>
    </div>
    <footer style="margin-top:.75rem; display:flex; gap:.5rem; justify-content:flex-end;">
      <button type="button" id="btnFaturarCancel" class="btn btn-outline">Cancelar</button>
      <button type="submit" id="btnFaturarSave" class="btn">Faturar</button>
    </footer>
  </form>
  </dialog>

<script>
function openFaturarDialog(id){ const d=document.getElementById('faturarDialog'); d.querySelector('[name="order_id"]').value=String(id); const dt=d.querySelector('[name="data_vencimento"]'); const now=new Date(); const plus7=new Date(now.getTime()+7*24*60*60*1000); const yyyy=plus7.getFullYear(); const mm=String(plus7.getMonth()+1).padStart(2,'0'); const dd=String(plus7.getDate()).padStart(2,'0'); dt.value = `${yyyy}-${mm}-${dd}`; d.showModal(); }
document.getElementById('btnFaturarCancel').addEventListener('click', ()=> document.getElementById('faturarDialog').close());
document.getElementById('faturarForm').addEventListener('submit', async (e)=>{
  e.preventDefault(); const fd=new FormData(e.currentTarget); const id=Number(fd.get('order_id')); const data_vencimento=String(fd.get('data_vencimento')||''); const observacoes=String(fd.get('observacoes')||'');
  try {
const resp = await apiRequest(`/api/servicos/ordens/${id}/faturar`, { method:'POST', body: JSON.stringify({ data_vencimento, observacoes }) });
    const j = await resp.json().catch(()=>({}));
    if (resp.ok && j.ok) { alert('OS faturada com sucesso. Conta a receber criada: '+(j.contas_receber_id||'-')); document.getElementById('faturarDialog').close(); load(); }
    else { alert('Falha ao faturar OS: '+(j.error?.message||resp.status)); }
  } catch(err){ alert('Erro ao faturar OS: '+(err?.message||err)); }
});
</script>