<div class="card">
  <h1>SPED Fiscal</h1>
  <p>Gere e valide o arquivo EFD ICMS/IPI (prévia TXT).</p>
  <div class="muted" style="margin:0.25rem 0 0.75rem 0;">
    <span id="blocksBadge" style="display:inline-block; padding:0.25rem 0.5rem; border:1px solid #e5e7eb; border-radius:6px; background:#f9fafb;">
      Blocos ativos: D (sem movimento), K (K200)
    </span>
  </div>
  <div class="grid" style="gap:0.75rem;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));">
    <div class="form-group">
      <label>Competência</label>
      <div style="display:flex; gap:0.5rem; align-items:center;">
        <select id="comp_month" aria-label="Mês">
          <option value="1">Janeiro</option>
          <option value="2">Fevereiro</option>
          <option value="3">Março</option>
          <option value="4">Abril</option>
          <option value="5">Maio</option>
          <option value="6">Junho</option>
          <option value="7">Julho</option>
          <option value="8">Agosto</option>
          <option value="9">Setembro</option>
          <option value="10">Outubro</option>
          <option value="11">Novembro</option>
          <option value="12">Dezembro</option>
        </select>
        <input type="number" id="comp_year" aria-label="Ano" min="2000" max="2100" placeholder="AAAA" />
      </div>
      <small class="muted">Informe mês e ano (formato AAAA-MM).</small>
    </div>
    <div class="form-group">
      <label>Perfil</label>
      <select id="perfil"><option>A</option><option>B</option><option>C</option></select>
    </div>
    <div class="form-group">
      <label>Finalidade</label>
      <select id="cod_fin"><option value="0">Original</option><option value="1">Substituto</option></select>
    </div>
    <div class="form-group">
      <label>Atividade</label>
      <select id="ind_ativ"><option value="1">Ativo</option><option value="0">Inativo</option></select>
    </div>
    <div class="form-group">
      <label>Versão do Leiaute</label>
      <select id="cod_ver"><option value="017">017</option><option value="016">016</option><option value="015">015</option></select>
      <small class="muted">Default 017; ajuste conforme necessidade.</small>
    </div>
  </div>
  <h3 style="margin-top:0.75rem;">Taxas e Ajustes</h3>
  <p class="muted" style="margin-top:-0.5rem;">Configure as taxas e, se necessário, informe dados adicionais.</p>
  <div class="grid" style="gap:0.75rem;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));">
    <div class="form-group"><label>ICMS (%)</label><input type="number" id="icms_rate" step="0.01" placeholder="18.00" /></div>
    <div class="form-group"><label>PIS (%)</label><input type="number" id="pis_rate" step="0.01" placeholder="1.65" /></div>
    <div class="form-group"><label>COFINS (%)</label><input type="number" id="cofins_rate" step="0.01" placeholder="7.60" /></div>
    <div class="form-group"><label>IPI (%)</label><input type="number" id="ipi_rate" step="0.01" placeholder="4.00" /></div>
    <div class="form-group"><label>ICMS ST (%)</label><input type="number" id="icms_st_rate" step="0.01" placeholder="0.00" /></div>
  </div>
  <div class="form-group">
    <label>Ajustes E111 (JSON)</label>
    <textarea id="e111" rows="4" placeholder='Ex.: [{"tipo":"D","cod_aj":"SP000001","vl":100.00,"desc":"Ajuste débito"}]'></textarea>
  </div>
  <h3 style="margin-top:0.75rem;">Dados opcionais</h3>
  <p class="muted" style="margin-top:-0.5rem;">Preencha para incluir D100/D190 e K230/K235 na geração.</p>
  <div class="grid" style="gap:0.75rem;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));">
    <div class="form-group">
      <label>Documentos de Transporte (D100/D190)</label>
      <textarea id="d100_docs" rows="6" placeholder='Ex.: [{"ind_oper":1,"ind_emit":0,"cod_mod":"57","cod_sit":"00","serie":"1","num_doc":"123","chv_cte":"","dt_doc":"2025-11-01","dt_apur":"2025-11-01","vl_doc":1500.00,"itens":[{"cst":"00","cfop":"5353","aliq_icms":12.0,"vl_opr":1500.00,"vl_bc_icms":1500.00,"vl_icms":180.00}]}]'></textarea>
      <div style="display:flex;gap:0.5rem;margin-top:0.25rem;align-items:center;">
        <input type="file" id="d100Csv" accept=".csv" />
        <span id="d100Status" class="muted"></span>
        <a href="/sped_templates/d100.csv" download class="muted" style="margin-left:auto;">Baixar template CSV</a>
      </div>
      <small class="muted">Você pode importar um arquivo CSV com cabeçalho: ind_oper;ind_emit;cod_mod;cod_sit;serie;num_doc;chv_cte;dt_doc;dt_apur;vl_doc;cst;cfop;aliq_icms;vl_opr;vl_bc_icms;vl_icms</small>
    </div>
    <div class="form-group">
      <label>Produção (K230)</label>
      <textarea id="k230" rows="6" placeholder='Ex.: [{"dt_ini":"2025-11-01","dt_fin":"2025-11-30","cod_item":"PROD001","qtd":100.0}]'></textarea>
      <div style="display:flex;gap:0.5rem;margin-top:0.25rem;align-items:center;">
        <input type="file" id="k230Csv" accept=".csv" />
        <span id="k230Status" class="muted"></span>
        <a href="/sped_templates/k230.csv" download class="muted" style="margin-left:auto;">Baixar template CSV</a>
      </div>
      <small class="muted">Importe CSV com cabeçalho: dt_ini;dt_fin;cod_item;qtd;cod_doc</small>
    </div>
    <div class="form-group">
      <label>Consumo (K235)</label>
      <textarea id="k235" rows="6" placeholder='Ex.: [{"dt_ini":"2025-11-01","dt_fin":"2025-11-30","cod_item":"INS001","qtd":80.0}]'></textarea>
      <div style="display:flex;gap:0.5rem;margin-top:0.25rem;align-items:center;">
        <input type="file" id="k235Csv" accept=".csv" />
        <span id="k235Status" class="muted"></span>
        <a href="/sped_templates/k235.csv" download class="muted" style="margin-left:auto;">Baixar template CSV</a>
      </div>
      <small class="muted">Importe CSV com cabeçalho: cod_item;qtd;cod_ins_subst</small>
    </div>
  </div>
  <div style="display:flex;gap:0.5rem;margin-top:0.75rem;">
    <button class="btn" id="btnPreview">Gerar prévia</button>
    <button class="btn btn-secondary" id="btnValidate">Validar dados</button>
    <button class="btn btn-warning" id="btnCheck">Validar SPED gerado</button>
    <button class="btn btn-success" id="btnDownload" disabled>Baixar TXT</button>
  </div>
  <hr />
  <textarea id="txtOut" rows="12" style="width:100%;font-family:monospace;" placeholder="Arquivo TXT gerado aparecerá aqui..."></textarea>
  <div style="display:flex; align-items:center; gap:0.5rem; margin-top:0.5rem;">
    <label for="issueBlockFilter" class="muted">Filtrar por bloco:</label>
    <select id="issueBlockFilter"><option value="">Todos</option></select>
    <span id="issueCount" class="muted" style="margin-left:auto;"></span>
  </div>
  <div id="issues" class="muted" style="margin-top:0.25rem;"></div>
  <ul id="issuesList" style="margin-top:0.25rem; padding-left:1rem;"></ul>
</div>
<script>
  const btnPreview = document.getElementById('btnPreview');
  const btnValidate = document.getElementById('btnValidate');
  const btnCheck = document.getElementById('btnCheck');
  const btnDownload = document.getElementById('btnDownload');
  const txtOut = document.getElementById('txtOut');
  const issuesEl = document.getElementById('issues');
  const issuesListEl = document.getElementById('issuesList');
  const issueBlockFilterEl = document.getElementById('issueBlockFilter');
  const issueCountEl = document.getElementById('issueCount');
  const icmsRateEl = document.getElementById('icms_rate');
  const pisRateEl = document.getElementById('pis_rate');
  const cofinsRateEl = document.getElementById('cofins_rate');
  const ipiRateEl = document.getElementById('ipi_rate');
  const icmsStRateEl = document.getElementById('icms_st_rate');
  const e111El = document.getElementById('e111');
  const d100El = document.getElementById('d100_docs');
  const k230El = document.getElementById('k230');
  const k235El = document.getElementById('k235');
  const d100Status = document.getElementById('d100Status');
  const k230Status = document.getElementById('k230Status');
  const k235Status = document.getElementById('k235Status');
  const d100CsvInput = document.getElementById('d100Csv');
  const k230CsvInput = document.getElementById('k230Csv');
  const k235CsvInput = document.getElementById('k235Csv');

  function validateJsonInput(textarea, statusEl, arrayRequired=true){
    const raw = (textarea.value||'').trim();
    if (!raw){ statusEl.textContent = ''; statusEl.className = 'muted'; return null; }
    try { const parsed = JSON.parse(raw); const ok = arrayRequired ? Array.isArray(parsed) : !!parsed; if (!ok){ throw new Error('Formato deve ser array JSON'); }
      statusEl.textContent = 'JSON válido'; statusEl.className = 'text-success'; return parsed;
    } catch(e){ statusEl.textContent = 'JSON inválido'; statusEl.className = 'text-error'; return null; }
  }

  function attachValidation(){
    d100El.addEventListener('input', ()=>{ validateJsonInput(d100El, d100Status); updateBlocksBadge(); });
    k230El.addEventListener('input', ()=>{ validateJsonInput(k230El, k230Status); updateBlocksBadge(); });
    k235El.addEventListener('input', ()=>{ validateJsonInput(k235El, k235Status); updateBlocksBadge(); });
  }

  function parseCsvText(text){
    const lines = text.split(/\r?\n/).filter(l=>l.trim().length>0);
    if (lines.length < 2) return [];
    const header = lines[0].split(';').map(s=>s.trim());
    return lines.slice(1).map(line=>{
      const cols = line.split(';');
      const obj = {};
      header.forEach((h,i)=>{ obj[h] = (cols[i]??'').trim(); });
      return obj;
    });
  }
  function mapD100(rows){
    return rows.map(r=>({
      ind_oper: parseInt(r.ind_oper||'1',10),
      ind_emit: parseInt(r.ind_emit||'0',10),
      cod_mod: String(r.cod_mod||'57'),
      cod_sit: String(r.cod_sit||'00'),
      serie: String(r.serie||''),
      num_doc: String(r.num_doc||''),
      chv_cte: String(r.chv_cte||''),
      dt_doc: String(r.dt_doc||''),
      dt_apur: String(r.dt_apur||''),
      vl_doc: parseFloat(r.vl_doc||'0'),
      itens: (r.cst||r.cfop) ? [{
        cst: String(r.cst||'00'),
        cfop: String(r.cfop||'5353'),
        aliq_icms: parseFloat(r.aliq_icms||'0'),
        vl_opr: parseFloat(r.vl_opr||r.vl_doc||'0'),
        vl_bc_icms: parseFloat(r.vl_bc_icms||'0'),
        vl_icms: parseFloat(r.vl_icms||'0'),
      }] : []
    }));
  }
  function mapK230(rows){
    return rows.map(r=>({
      dt_ini: String(r.dt_ini||''),
      dt_fin: String(r.dt_fin||''),
      cod_item: String(r.cod_item||''),
      qtd: parseFloat(r.qtd||'0'),
      cod_doc: r.cod_doc ? String(r.cod_doc) : undefined,
    }));
  }
  function mapK235(rows){
    return rows.map(r=>({
      cod_item: String(r.cod_item||''),
      qtd: parseFloat(r.qtd||'0'),
      cod_ins_subst: r.cod_ins_subst ? String(r.cod_ins_subst) : undefined,
    }));
  }
  function attachCsvImport(){
    function handleFile(inputEl, targetEl, statusEl, mapper){
      inputEl.addEventListener('change', async ()=>{
        const f = inputEl.files && inputEl.files[0];
        if (!f){ return; }
        const text = await f.text();
        const rows = parseCsvText(text);
        const mapped = mapper(rows);
        targetEl.value = JSON.stringify(mapped, null, 2);
        validateJsonInput(targetEl, statusEl); updateBlocksBadge();
      });
    }
    handleFile(d100CsvInput, d100El, d100Status, mapD100);
    handleFile(k230CsvInput, k230El, k230Status, mapK230);
    handleFile(k235CsvInput, k235El, k235Status, mapK235);
  }
  function parseComp(){
    const ymSel = document.getElementById('comp_month');
    const ySel = document.getElementById('comp_year');
    if (ymSel && ySel){
      const m = parseInt(String(ymSel.value||''), 10);
      const y = parseInt(String(ySel.value||''), 10);
      if (!Number.isFinite(y) || !Number.isFinite(m) || m < 1 || m > 12) return {year:null, month:null};
      return { year: y, month: m };
    }
    // Fallback: input type="month" (caso exista em versões antigas)
    const compEl = document.getElementById('comp');
    const val = compEl ? (compEl.value || '') : '';
    if (!val || !/^\d{4}-\d{2}$/.test(val)) return {year:null,month:null};
    const [y,m] = val.split('-'); return {year:parseInt(y,10), month:parseInt(m,10)};
  }
  function initCompDefaults(){
    const ymSel = document.getElementById('comp_month');
    const ySel = document.getElementById('comp_year');
    if (ymSel && ySel){
      const now = new Date();
      ymSel.value = String(now.getMonth()+1);
      ySel.value = String(now.getFullYear());
    }
  }
  async function preview(){
    const {year,month} = parseComp(); if (!year||!month){ alert('Informe a competência AAAA-MM'); return; }
    const body = {
      year, month,
      perfil: document.getElementById('perfil').value,
      cod_fin: parseInt(document.getElementById('cod_fin').value,10),
      ind_ativ: parseInt(document.getElementById('ind_ativ').value,10),
      cod_ver: document.getElementById('cod_ver').value
    };
    // Optional rates (convert % to fraction)
    const icms = parseFloat(icmsRateEl.value); if (!isNaN(icms)) body.icms_rate = icms/100.0;
    const pis = parseFloat(pisRateEl.value); if (!isNaN(pis)) body.pis_rate = pis/100.0;
    const cof = parseFloat(cofinsRateEl.value); if (!isNaN(cof)) body.cofins_rate = cof/100.0;
    const ipi = parseFloat(ipiRateEl.value); if (!isNaN(ipi)) body.ipi_rate = ipi/100.0;
    const st = parseFloat(icmsStRateEl.value); if (!isNaN(st)) body.icms_st_rate = st/100.0;
    // Optional E111
    const e111Txt = (e111El.value||'').trim(); if (e111Txt) {
      try { const parsed = JSON.parse(e111Txt); if (Array.isArray(parsed)) body.e111 = parsed; } catch(e){ /* ignore parse errors */ }
    }
    // Dados opcionais: D100/D190 e K230/K235
    const d100Parsed = validateJsonInput(d100El, d100Status);
    const k230Parsed = validateJsonInput(k230El, k230Status);
    const k235Parsed = validateJsonInput(k235El, k235Status);
    if (Array.isArray(d100Parsed)) body.d100_docs = d100Parsed;
    if (Array.isArray(k230Parsed)) body.k230 = k230Parsed;
    if (Array.isArray(k235Parsed)) body.k235 = k235Parsed;
    btnPreview.disabled=true; btnPreview.textContent='Gerando...'; issuesEl.textContent='';
    try {
      const resp = await fetch('/api/fiscal/sped/generate',{method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(body)});
      const j = await resp.json();
      if (j && j.ok){ txtOut.value = j.txt || ''; btnDownload.disabled = !txtOut.value; }
      else { txtOut.value = ''; alert('Falha ao gerar SPED: '+(j?.message||'erro')); }
    } catch(e){ alert('Erro de rede'); }
    finally { btnPreview.disabled=false; btnPreview.textContent='Gerar prévia'; }
  }
  async function checkSped(){
    const {year,month} = parseComp(); if (!year||!month){ alert('Informe a competência AAAA-MM'); return; }
    const body = {
      year, month,
      perfil: document.getElementById('perfil').value,
      cod_fin: parseInt(document.getElementById('cod_fin').value,10),
      ind_ativ: parseInt(document.getElementById('ind_ativ').value,10),
      cod_ver: document.getElementById('cod_ver').value
    };
    const icms = parseFloat(icmsRateEl.value); if (!isNaN(icms)) body.icms_rate = icms/100.0;
    const pis = parseFloat(pisRateEl.value); if (!isNaN(pis)) body.pis_rate = pis/100.0;
    const cof = parseFloat(cofinsRateEl.value); if (!isNaN(cof)) body.cofins_rate = cof/100.0;
    const ipi = parseFloat(ipiRateEl.value); if (!isNaN(ipi)) body.ipi_rate = ipi/100.0;
    const st = parseFloat(icmsStRateEl.value); if (!isNaN(st)) body.icms_st_rate = st/100.0;
    const e111Txt = (e111El.value||'').trim(); if (e111Txt) {
      try { const parsed = JSON.parse(e111Txt); if (Array.isArray(parsed)) body.e111 = parsed; } catch(e){ /* ignore */ }
    }
    const d100Parsed2 = validateJsonInput(d100El, d100Status);
    const k230Parsed2 = validateJsonInput(k230El, k230Status);
    const k235Parsed2 = validateJsonInput(k235El, k235Status);
    if (Array.isArray(d100Parsed2)) body.d100_docs = d100Parsed2;
    if (Array.isArray(k230Parsed2)) body.k230 = k230Parsed2;
    if (Array.isArray(k235Parsed2)) body.k235 = k235Parsed2;
    btnCheck.disabled=true; btnCheck.textContent='Validando...'; issuesEl.textContent=''; clearIssues();
    try {
      const resp = await fetch('/api/fiscal/sped/check',{method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(body)});
      const j = await resp.json();
      if (j && j.ok){ issuesEl.textContent='Validação SPED OK'; issuesEl.className='text-success'; clearIssues(); }
      else { const issues = Array.isArray(j.issues) ? j.issues : []; issuesEl.textContent= issues.length ? 'Falhas de validação SPED' : 'Sem detalhes de falhas'; issuesEl.className='text-error'; renderIssues(issues); }
    } catch(e){ issuesEl.textContent='Erro de rede na validação SPED'; issuesEl.className='text-error'; }
    finally { btnCheck.disabled=false; btnCheck.textContent='Validar SPED gerado'; }
  }
  async function validate(){
    btnValidate.disabled=true; btnValidate.textContent='Validando...'; issuesEl.textContent=''; clearIssues();
    try {
      const resp = await fetch('/api/fiscal/sped/validate',{method:'POST'});
      const j = await resp.json();
      if (j && j.ok){ issuesEl.textContent='Validação OK'; issuesEl.className='text-success'; clearIssues(); }
      else { const issues = Array.isArray(j.issues) ? j.issues : []; issuesEl.textContent= issues.length ? 'Falhas de validação' : 'Sem detalhes de falhas'; issuesEl.className='text-error'; renderIssues(issues); }
    } catch(e){ issuesEl.textContent='Erro de rede na validação'; issuesEl.className='text-error'; }
    finally { btnValidate.disabled=false; btnValidate.textContent='Validar dados'; }
  }
  function download(){
    const content = txtOut.value || ''; if (!content){ alert('Nada para baixar'); return; }
    const blob = new Blob([content], {type:'text/plain'});
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a'); a.href=url; a.download='SPED_Fiscal.txt'; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url);
  }
  btnPreview.addEventListener('click', preview);
  btnValidate.addEventListener('click', validate);
  btnCheck.addEventListener('click', checkSped);
  btnDownload.addEventListener('click', download);
  function updateBlocksBadge(){
    const badge = document.getElementById('blocksBadge');
    const hasD100 = Array.isArray(validateJsonInput(d100El, d100Status));
    const hasK230 = Array.isArray(validateJsonInput(k230El, k230Status));
    const hasK235 = Array.isArray(validateJsonInput(k235El, k235Status));
    const parts = [];
    // D block
    parts.push(`D (${hasD100 ? 'D100/D190' : 'sem movimento'})`);
    // K block
    const kAdd = [];
    kAdd.push('K200');
    if (hasK230) kAdd.push('K230');
    if (hasK235) kAdd.push('K235');
    parts.push(`K (${kAdd.join(', ')})`);
    badge.textContent = `Blocos ativos: ${parts.join(', ')}`;
  }
  document.addEventListener('DOMContentLoaded', function(){ initCompDefaults(); attachValidation(); attachCsvImport(); updateBlocksBadge(); });

  function clearIssues(){ issuesListEl.innerHTML=''; updateIssueCount(); }
  function renderIssues(issues){
    issuesListEl.innerHTML = '';
    const blocks = new Set();
    (issues||[]).forEach(msg=>{
      const li = document.createElement('li');
      const severity = severityFromMessage(msg);
      li.className = 'issue-item ' + (severity === 'error' ? 'text-error' : (severity === 'warning' ? 'text-warning' : ''));
      li.textContent = msg;
      const m = /^([A-Z]\d{3,4})\b/.exec(msg) || /^\|(C\d{3})\|/.exec(msg);
      const block = m ? (m[1].replace('|','')) : '';
      if (block) { li.dataset.block = block; blocks.add(block); }
      issuesListEl.appendChild(li);
    });
    // Popular filtro com blocos encontrados
    const current = issueBlockFilterEl.value;
    const opts = Array.from(issueBlockFilterEl.options).map(o=>o.value);
    blocks.forEach(b=>{ if (!opts.includes(b)){ const o = document.createElement('option'); o.value=b; o.textContent=b; issueBlockFilterEl.appendChild(o); } });
    issueBlockFilterEl.value = current || '';
    updateIssueCount();
    applyIssueFilter();
  }
  function severityFromMessage(message){
    const m = String(message||'').toLowerCase();
    // Erros críticos comuns dos validadores (ex.: C190/C170 inconsistências de ICMS)
    if (m.includes('esperado pela alíquota') || m.includes('inconsistência') || m.includes('erro')) return 'error';
    // Avisos não bloqueantes
    if (m.includes('aviso') || m.includes('warning')) return 'warning';
    return '';
  }
  function updateIssueCount(){
    const items = issuesListEl.querySelectorAll('.issue-item');
    const visible = Array.from(items).filter(el=>el.style.display!=='none').length;
    issueCountEl.textContent = visible ? `${visible} issue(s) visíveis` : '';
  }
  function applyIssueFilter(){
    const sel = issueBlockFilterEl.value||'';
    const items = issuesListEl.querySelectorAll('.issue-item');
    items.forEach(el=>{
      const b = el.dataset.block||'';
      el.style.display = !sel || sel === '' ? '' : (b === sel ? '' : 'none');
    });
    updateIssueCount();
  }
  issueBlockFilterEl.addEventListener('change', applyIssueFilter);
</script>