<?php /* Página de Fluxo de Caixa */ ?>
<div class="page-header">
  <h1>Fluxo de Caixa</h1>
  <p class="muted">Visualize entradas e saídas de caixa por período</p>
</div>

<!-- Filtros -->
<section class="card">
  <div style="display:flex;gap:1rem;align-items:center;flex-wrap:wrap;">
    <div class="form-group" style="margin:0;">
      <label for="dataInicio">Data Início</label>
      <input type="date" id="dataInicio" class="input" />
    </div>
    <div class="form-group" style="margin:0;">
      <label for="dataFim">Data Fim</label>
      <input type="date" id="dataFim" class="input" />
    </div>
    <button id="btnFiltrar" class="btn btn-primary">Filtrar</button>
    <button id="btnPrint" class="btn">Imprimir / PDF</button>
  </div>
</section>

<!-- Resumo -->
<section class="card">
  <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:1rem;">
    <div class="stat-card success">
      <h3>Entradas</h3>
      <p id="totalEntradas">R$ 0,00</p>
    </div>
    <div class="stat-card danger">
      <h3>Saídas</h3>
      <p id="totalSaidas">R$ 0,00</p>
    </div>
    <div class="stat-card info">
      <h3>Saldo</h3>
      <p id="saldoTotal">R$ 0,00</p>
    </div>
  </div>
</section>

<!-- Gráfico -->
<section class="card">
  <h3>Fluxo por Período</h3>
  <canvas id="fluxoChart" width="800" height="300" style="width:100%;height:auto;"></canvas>
  <div id="chartLegend" style="display:flex;gap:1rem;margin-top:.5rem;align-items:center;font-size:.9rem;">
    <span style="display:flex;align-items:center;gap:.4rem;"><span style="width:14px;height:14px;background:#16a34a;display:inline-block;"></span>Positivo</span>
    <span style="display:flex;align-items:center;gap:.4rem;"><span style="width:14px;height:14px;background:#dc2626;display:inline-block;"></span>Negativo</span>
  </div>
  <div id="chartTooltip" style="position:absolute;pointer-events:none;background:#111;color:#fff;padding:.25rem .5rem;border-radius:.25rem;font-size:.8rem;opacity:0;transform:translate(-50%, -130%);"></div>
</section>

<!-- Movimentações -->
<section class="card">
  <h3>Movimentações Recentes</h3>
  <div id="fluxoStatus" class="alert" style="display:none;"></div>
  <div style="overflow-x:auto; max-height:480px; overflow-y:auto;">
    <table class="table">
      <thead>
        <tr>
          <th>Data</th>
          <th>Descrição</th>
          <th>Tipo</th>
          <th>Valor</th>
          <th>Status</th>
        </tr>
      </thead>
      <tbody id="movimentacoesTableBody">
        <tr>
          <td colspan="5" style="text-align:center;padding:2rem;">
            <div class="loading">Carregando movimentações...</div>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
  <div id="pagination" class="pagination-bar" style="display:flex;gap:.5rem;align-items:center;justify-content:flex-end;margin-top:.5rem;"></div>
</section>

<section class="card">
  <h3>Relatório Simples</h3>
  <div id="relatorio">
    <p>Período: <strong id="relPeriodo">-</strong></p>
    <p>Entradas: <strong id="relEntradas">R$ 0,00</strong> • Saídas: <strong id="relSaidas">R$ 0,00</strong> • Saldo: <strong id="relSaldo">R$ 0,00</strong></p>
  </div>
</section>

<style>
@media print {
  header, footer, #btnFiltrar, #btnPrint, .pagination-bar, .page-header .muted { display:none !important; }
  .card { box-shadow:none; border:none; }
  #fluxoChart, #chartLegend { display:none !important; }
}
</style>

<script>
(function() {
  // Utilitários de data
  function pad(n){ return String(n).padStart(2,'0'); }
  function toISO(br){
    if (!br) return '';
    try {
      if (typeof window !== 'undefined' && typeof window.parseDateBR === 'function') {
        const d = window.parseDateBR(br); if (d) return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`;
      }
      const m = String(br).match(/^(\d{2})-(\d{2})-(\d{4})$/);
      if (m) { const dd=+m[1], mm=+m[2], yy=+m[3]; const d=new Date(yy,mm-1,dd); if (!isNaN(d)) return `${yy}-${pad(mm)}-${pad(dd)}`; }
      const d = new Date(br); if (!isNaN(d)) return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`;
    } catch(_){ }
    return String(br);
  }
  function toBR(d){ try { const dt = (d instanceof Date) ? d : new Date(String(d)); if (isNaN(dt)) return ''; return `${pad(dt.getDate())}-${pad(dt.getMonth()+1)}-${dt.getFullYear()}`; } catch(_){ return ''; } }
  const fmtBRL = (v)=>{ try { return new Intl.NumberFormat('pt-BR',{style:'currency',currency:'BRL'}).format(v||0); } catch(e){ return 'R$ ' + Number(v||0).toFixed(2).replace('.', ','); } };

  // Função para fazer requisições à API (usa global quando disponível; fallback injeta Authorization/x-tenant)
  const apiRequest = async function(url, options = {}) {
    if (typeof window.apiRequest === 'function') {
      const resp = await window.apiRequest(url, options);
      if (!resp || !resp.ok) { throw new Error(`HTTP ${resp ? resp.status : 'N/A'}`); }
      return resp.json();
    }
    // Fallback: construir headers com Authorization e x-tenant-id
    const headers = { 'Accept': 'application/json', ...(options.headers || {}) };
    try {
      const lsToken = localStorage.getItem('auth_token');
      const m = document.cookie.match(/(?:^|; )auth_token=([^;]+)/);
      const token = lsToken || (m ? decodeURIComponent(m[1]) : '');
      if (token && !headers['Authorization']) headers['Authorization'] = `Bearer ${token}`;
      const mTenant = document.cookie.match(/(?:^|; )x-tenant-id=([^;]+)/);
      if (!headers['x-tenant-id']) headers['x-tenant-id'] = mTenant ? decodeURIComponent(mTenant[1]) : 'default';
    } catch(_) {}
    const resp = await fetch(url, { ...options, headers, credentials: 'include', cache: 'no-store' });
    if (!resp.ok) { throw new Error(`HTTP ${resp.status}`); }
    return resp.json();
  };

  // Datas padrão (últimos 30 dias)
  const hoje = new Date();
  const inicio = new Date(Date.now() - 29*24*60*60*1000);
  document.getElementById('dataInicio').value = toBR(inicio);
  document.getElementById('dataFim').value = toBR(hoje);

  async function loadFluxoCaixa() {
    const vIni = document.getElementById('dataInicio').value;
    const vFim = document.getElementById('dataFim').value;
    if (!vIni || !vFim) { alert('Selecione o período para consulta'); return; }
    const start = toISO(vIni);
    const end = toISO(vFim);
    // Atualizar período no relatório
    const relPeriodo = document.getElementById('relPeriodo');
    if (relPeriodo) relPeriodo.textContent = `${vIni} a ${vFim}`;

    try {
      // Buscar dados de pagar e receber
      const [rec, pay] = await Promise.all([
        apiRequest(`/api/financeiro/contas-receber?start=${encodeURIComponent(start)}&end=${encodeURIComponent(end)}&per_page=100`),
        apiRequest(`/api/financeiro/contas-pagar?start=${encodeURIComponent(start)}&end=${encodeURIComponent(end)}&per_page=100`)
      ]);

      // Status do módulo (tabelas e migrações)
      const statusMsg = [rec.message, pay.message].filter(Boolean).join(' \u2022 ');
      const statusEl = document.getElementById('fluxoStatus');
      if (statusMsg) {
        statusEl.className = 'alert alert-error';
        statusEl.textContent = `Status: ${statusMsg}`;
        statusEl.style.display = 'block';
      } else {
        statusEl.style.display = 'none';
      }

      const recebiveis = Array.isArray(rec.data) ? rec.data : [];
      const pagaveis = Array.isArray(pay.data) ? pay.data : [];

      // Resumo simples por período
      const totalEntradas = recebiveis.reduce((s, r) => s + (parseFloat(r.valor) || 0), 0);
      const totalSaidas = pagaveis.reduce((s, p) => s + (parseFloat(p.valor) || 0), 0);
      renderResumo({ entradas: totalEntradas, saidas: totalSaidas, saldo: totalEntradas - totalSaidas });
      const relEntradas = document.getElementById('relEntradas');
      const relSaidas = document.getElementById('relSaidas');
      const relSaldo = document.getElementById('relSaldo');
      if (relEntradas) relEntradas.textContent = fmtBRL(totalEntradas);
      if (relSaidas) relSaidas.textContent = fmtBRL(totalSaidas);
      if (relSaldo) relSaldo.textContent = fmtBRL(totalEntradas - totalSaidas);

      // Movimentações unificadas
      const movimentos = [
        ...recebiveis.map(r => ({
          data: r.data_vencimento || r.created_at,
          descricao: r.descricao || r.documento || 'Recebível',
          tipo: 'entrada',
          valor: parseFloat(r.valor) || 0,
          status: r.status || 'pendente'
        })),
        ...pagaveis.map(p => ({
          data: p.data_vencimento || p.created_at,
          descricao: p.descricao || p.documento || 'Pagamento',
          tipo: 'saida',
          valor: parseFloat(p.valor) || 0,
          status: p.status || 'pendente'
        })),
      ].sort((a,b)=> new Date(a.data) - new Date(b.data));
      renderMovimentacoes(movimentos);
      renderChart(movimentos, start, end);
    } catch (e) {
      console.error('Falha ao carregar fluxo de caixa', e);
      renderResumo({ entradas: 0, saidas: 0, saldo: 0 });
      const tbody = document.getElementById('movimentacoesTableBody');
      tbody.innerHTML = `<tr><td colspan="5" style="text-align:center;color:#b91c1c;">Erro ao carregar: ${String(e.message||e)}</td></tr>`;
    }
  }

  function renderResumo(resumo) {
    document.getElementById('totalEntradas').textContent = fmtBRL(resumo.entradas);
    document.getElementById('totalSaidas').textContent = fmtBRL(resumo.saidas);
    document.getElementById('saldoTotal').textContent = fmtBRL(resumo.saldo);
  }

  const state = { movimentos: [], pageSize: 15, currentPage: 1 };
  function renderMovimentacoes(movimentacoes) {
    state.movimentos = movimentacoes.slice();
    state.currentPage = 1;
    renderMovimentacoesPage(state.currentPage);
    renderPagination();
  }
  function renderMovimentacoesPage(page) {
    const tbody = document.getElementById('movimentacoesTableBody');
    const start = (page - 1) * state.pageSize;
    const rows = state.movimentos.slice(start, start + state.pageSize);
    if (!rows.length) { tbody.innerHTML = '<tr><td colspan="5" style="text-align:center;">Nenhuma movimentação encontrada</td></tr>'; return; }
    tbody.innerHTML = rows.map(mov => {
      const tipoClass = mov.tipo === 'entrada' ? 'success' : 'danger';
      const statusClass = (mov.status === 'recebido' || mov.status === 'pago') ? 'success' : (mov.status === 'vencido' ? 'danger' : 'warning');
      const d = new Date(mov.data);
      const ddmmyyyy = isNaN(d) ? String(mov.data) : `${pad(d.getDate())}-${pad(d.getMonth()+1)}-${d.getFullYear()}`;
      return `
        <tr>
          <td>${ddmmyyyy}</td>
          <td>${mov.descricao}</td>
          <td><span class="badge badge-${tipoClass}">${mov.tipo}</span></td>
          <td>${fmtBRL(mov.valor)}</td>
          <td><span class="badge badge-${statusClass}">${mov.status}</span></td>
        </tr>
      `;
    }).join('');
  }
  function renderPagination() {
    const total = state.movimentos.length;
    const totalPages = Math.max(1, Math.ceil(total / state.pageSize));
    const el = document.getElementById('pagination');
    el.innerHTML = `
      <span>Página ${state.currentPage} de ${totalPages}</span>
      <button class="btn" data-action="prev" ${state.currentPage<=1?'disabled':''}>Anterior</button>
      <button class="btn" data-action="next" ${state.currentPage>=totalPages?'disabled':''}>Próxima</button>
    `;
    el.querySelector('[data-action="prev"]').onclick = () => { if (state.currentPage > 1) { state.currentPage--; renderMovimentacoesPage(state.currentPage); renderPagination(); } };
    el.querySelector('[data-action="next"]').onclick = () => { if (state.currentPage < totalPages) { state.currentPage++; renderMovimentacoesPage(state.currentPage); renderPagination(); } };
  }

  function renderChart(movimentos, startISO, endISO){
    const c = document.getElementById('fluxoChart'); if (!c || !c.getContext) return;
    // Ajuste de nitidez: dimensionar pelo devicePixelRatio e desenhar em pixels CSS
    const dpr = Math.max(1, window.devicePixelRatio || 1);
    const rect = c.getBoundingClientRect();
    const cssW = Math.max(300, Math.floor(rect.width));
    const cssH = 300; // altura fixa de exibição
    c.style.width = cssW + 'px';
    c.style.height = cssH + 'px';
    c.width = Math.floor(cssW * dpr);
    c.height = Math.floor(cssH * dpr);

    const ctx = c.getContext('2d');
    ctx.setTransform(1,0,0,1,0,0); // reset
    ctx.scale(dpr, dpr); // desenhar em coordenadas CSS
    ctx.clearRect(0,0,cssW,cssH);
    // Construir série contínua de dias no período
    const start = new Date(startISO), end = new Date(endISO);
    if (isNaN(start) || isNaN(end)) { ctx.fillStyle = '#666'; ctx.fillText('Período inválido', 12, 20); return; }
    const days = []; const dtmp = new Date(start);
    while (dtmp <= end) { days.push(new Date(dtmp)); dtmp.setDate(dtmp.getDate() + 1); }
    const agg = Object.create(null);
    days.forEach(d => { const k = `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`; agg[k] = 0; });
    movimentos.forEach(m => {
      const d = new Date(m.data); if (isNaN(d)) return; const key = `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`;
      if (key in agg) agg[key] += (m.tipo === 'entrada' ? m.valor : -m.valor);
    });
    const keys = Object.keys(agg);
    const values = keys.map(k=>agg[k]);
    const maxAbs = Math.max(...values.map(v=>Math.abs(v))) || 1;
    const leftPad = 40, bottomPad = 30, topPad = 10, rightPad = 10;
    const plotW = cssW - leftPad - rightPad, plotH = cssH - topPad - bottomPad;
    const midY = topPad + Math.floor(plotH*0.6);
    // Eixos (alinhados ao pixel)
    const crisp = (n) => Math.round(n) + 0.5;
    ctx.strokeStyle = '#aaa'; ctx.lineWidth = 1;
    ctx.beginPath(); ctx.moveTo(crisp(leftPad), crisp(midY)); ctx.lineTo(crisp(leftPad + plotW), crisp(midY)); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(crisp(leftPad), crisp(topPad)); ctx.lineTo(crisp(leftPad), crisp(topPad + plotH)); ctx.stroke();
    // Barras e rótulos parciais
    const barW = Math.max(2, Math.floor(plotW / keys.length));
    keys.forEach((k, i) => {
      const v = values[i]; const h = Math.round((Math.abs(v)/maxAbs)*(plotH*0.5));
      const x = leftPad + i*barW + 1; const y = v>=0 ? midY - h : midY;
      ctx.fillStyle = v>=0 ? '#16a34a' : '#dc2626';
      ctx.fillRect(x, y, Math.max(1, barW-2), h);
    });
    // Ticks do eixo X a cada ~6 rótulos
    ctx.fillStyle = '#666';
    ctx.font = '12px system-ui, -apple-system, Segoe UI, Roboto, sans-serif';
    ctx.textBaseline = 'top';
    const tickEvery = Math.max(1, Math.floor(keys.length / 6));
    keys.forEach((k, i) => {
      if (i % tickEvery === 0) {
        const x = Math.round(leftPad + i*barW);
        ctx.fillText(k.slice(8,10)+'/'+k.slice(5,7), x, topPad + plotH + 16);
      }
    });
    // Tooltip: mapear índice de barra
    const tooltip = document.getElementById('chartTooltip');
    c.onmousemove = (ev) => {
      const rect2 = c.getBoundingClientRect();
      const scaleX = c.width / rect2.width; const scaleY = c.height / rect2.height;
      const px = (ev.clientX - rect2.left) * scaleX; const py = (ev.clientY - rect2.top) * scaleY;
      if (px < leftPad || px > leftPad + plotW || py < topPad || py > topPad + plotH) { tooltip.style.opacity = 0; return; }
      const idx = Math.floor((px - leftPad) / barW);
      if (idx < 0 || idx >= keys.length) { tooltip.style.opacity = 0; return; }
      const k = keys[idx]; const v = values[idx];
      tooltip.textContent = `${k.split('-').reverse().join('/')}: ${fmtBRL(v)}`;
      tooltip.style.left = `${ev.clientX}px`;
      tooltip.style.top = `${ev.clientY}px`;
      tooltip.style.opacity = 0.95;
    };
    c.onmouseleave = () => { tooltip.style.opacity = 0; };
  }

  document.getElementById('btnFiltrar').addEventListener('click', loadFluxoCaixa);
  document.getElementById('btnPrint').addEventListener('click', () => window.print());
  loadFluxoCaixa();
})();
</script>