/* global React, Icon, Badge, Button, Card, brl, KpiMini, ChartCanvas */

// ─── Constantes ──────────────────────────────────────────────────────────────

const FIN_STATUS_TONE = {
  'Recebido':   'success',
  'Pago':       'success',
  'Parcial':    'warning',
  'Vencido':    'danger',
  'Vence hoje': 'brand',
  'Em aberto':  'info',
};

const CATEGORIAS_DESPESA = [
  'Matéria-prima', 'Embalagens', 'Frete', 'Aluguel', 'Energia', 'Água',
  'Internet/Telefone', 'Salários', 'Impostos', 'Marketing', 'Marketplace',
  'Software/SaaS', 'Manutenção', 'Produção', 'Folha', 'Outros',
];

const FORMAS_PAGAMENTO = ['Boleto', 'PIX', 'Cartão', 'Transferência', 'Cheque', 'Dinheiro'];

// ─── Status automático ───────────────────────────────────────────────────────

function computeFinStatus(row) {
  if (row.status === 'Recebido' || row.status === 'Pago') return row.status;
  if (row.status === 'Parcial') return 'Parcial';
  const venc = row.vencimento ? String(row.vencimento).slice(0, 10) : null;
  if (!venc) return row.status || 'Em aberto';
  const today = new Date().toISOString().slice(0, 10);
  if (venc < today) return 'Vencido';
  if (venc === today) return 'Vence hoje';
  return 'Em aberto';
}

function FinStatusBadge({ row }) {
  const st = computeFinStatus(row);
  return <Badge tone={FIN_STATUS_TONE[st] || 'neutral'}>{st}</Badge>;
}

// ─── KPIs calculados ─────────────────────────────────────────────────────────

function finRecKpis(rows) {
  const today = new Date().toISOString().slice(0, 10);
  const abertos = rows.filter(r => r.status !== 'Recebido');
  const vencidos = abertos.filter(r => {
    const v = r.vencimento ? String(r.vencimento).slice(0, 10) : null;
    return v && v < today;
  });
  const vencendoHoje = abertos.filter(r => {
    const v = r.vencimento ? String(r.vencimento).slice(0, 10) : null;
    return v === today;
  });
  const prox30 = new Date(Date.now() + 30 * 86400000).toISOString().slice(0, 10);
  const previsao30 = abertos.filter(r => {
    const v = r.vencimento ? String(r.vencimento).slice(0, 10) : null;
    return v && v >= today && v <= prox30;
  });

  const totalAberto = abertos.reduce((a, r) => a + ((parseFloat(r.valor) || 0) - (parseFloat(r.valor_recebido || r.recebido) || 0)), 0);
  const totalVencido = vencidos.reduce((a, r) => a + ((parseFloat(r.valor) || 0) - (parseFloat(r.valor_recebido || r.recebido) || 0)), 0);
  const totalVenceHoje = vencendoHoje.reduce((a, r) => a + (parseFloat(r.valor) || 0), 0);
  const totalPrev30 = previsao30.reduce((a, r) => a + ((parseFloat(r.valor) || 0) - (parseFloat(r.valor_recebido || r.recebido) || 0)), 0);
  const recebidosMes = rows.filter(r => {
    if (r.status !== 'Recebido') return false;
    const dp = r.data_pagamento || r.vencimento;
    if (!dp) return false;
    const d = String(dp).slice(0, 7);
    return d === today.slice(0, 7);
  });
  const totalRecMes = recebidosMes.reduce((a, r) => a + (parseFloat(r.valor_recebido || r.recebido || r.valor) || 0), 0);
  const inadPct = totalAberto > 0 ? (totalVencido / totalAberto) * 100 : 0;
  const ticketMedio = rows.length > 0 ? rows.reduce((a, r) => a + (parseFloat(r.valor) || 0), 0) / rows.length : 0;

  return {
    vencendoHoje: { count: vencendoHoje.length, valor: totalVenceHoje },
    vencidos:     { count: vencidos.length, valor: totalVencido },
    inadPct:      Math.round(inadPct),
    previsao30:   totalPrev30,
    ticketMedio,
    totalAberto,
    totalRecMes,
    abertosCount: abertos.length,
  };
}

function finPagKpis(rows) {
  const today = new Date().toISOString().slice(0, 10);
  const abertos = rows.filter(r => r.status !== 'Pago');
  const vencidos = abertos.filter(r => {
    const v = r.vencimento ? String(r.vencimento).slice(0, 10) : null;
    return v && v < today;
  });
  const pagosMes = rows.filter(r => {
    if (r.status !== 'Pago') return false;
    const dp = r.data_pagamento || r.vencimento;
    if (!dp) return false;
    return String(dp).slice(0, 7) === today.slice(0, 7);
  });
  const recorrentes = rows.filter(r => r.recorrente || r.recorrenteFlag);
  const totalAberto = abertos.reduce((a, r) => a + (parseFloat(r.valor) || 0), 0);
  const totalVencido = vencidos.reduce((a, r) => a + (parseFloat(r.valor) || 0), 0);
  const totalPagoMes = pagosMes.reduce((a, r) => a + (parseFloat(r.valor) || 0), 0);

  return {
    totalAberto,
    totalVencido,
    vencidosCount: vencidos.length,
    abertosCount: abertos.length,
    totalPagoMes,
    pagosMesCount: pagosMes.length,
    recorrentesCount: recorrentes.length,
  };
}

// ─── Row Actions ─────────────────────────────────────────────────────────────

function FinRowActions({ row, onReceber, onEdit, onDuplicar, onParcelar, tipo }) {
  const isPago = tipo === 'pagar' ? row.status === 'Pago' : row.status === 'Recebido';
  return (
    <span className="row-actions" style={{ opacity: 1 }} onClick={e => e.stopPropagation()}>
      {!isPago && (
        <button className="icon-btn" title={tipo === 'pagar' ? 'Pagar' : 'Receber'} onClick={onReceber}
          style={{ color: 'var(--tm-success)' }}>
          <Icon name="check-circle" size={14} />
        </button>
      )}
      <button className="icon-btn" title="Editar" onClick={onEdit}>
        <Icon name="pencil" size={14} />
      </button>
      <button className="icon-btn" title="Duplicar" onClick={onDuplicar}>
        <Icon name="copy" size={14} />
      </button>
      {tipo === 'receber' && !isPago && (row.total_parcelas || 1) <= 1 && onParcelar && (
        <button className="icon-btn" title="Parcelar" onClick={onParcelar}>
          <Icon name="split" size={14} />
        </button>
      )}
    </span>
  );
}

// ─── Fluxo de Caixa Chart ───────────────────────────────────────────────────

function buildFluxoData(receber, pagar, periodoLabel) {
  const today = new Date();
  let days;
  if (periodoLabel === '7d')  days = 7;
  else if (periodoLabel === '30d')  days = 30;
  else if (periodoLabel === '90d')  days = 90;
  else days = 365;

  const labels = [];
  const entradas = [];
  const saidas = [];
  const saldo = [];
  let acum = 0;

  for (let i = 0; i < days; i++) {
    const d = new Date(today.getTime() + i * 86400000);
    const iso = d.toISOString().slice(0, 10);
    const lbl = days <= 30
      ? d.toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' })
      : days <= 90
        ? (i % 7 === 0 ? d.toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' }) : '')
        : (d.getDate() === 1 ? d.toLocaleDateString('pt-BR', { month: 'short' }) : '');

    let entDia = 0;
    receber.forEach(r => {
      if (r.status === 'Recebido') return;
      const v = r.vencimento ? String(r.vencimento).slice(0, 10) : null;
      if (v === iso) entDia += (parseFloat(r.valor) || 0) - (parseFloat(r.valor_recebido || r.recebido) || 0);
    });

    let saiDia = 0;
    pagar.forEach(r => {
      if (r.status === 'Pago') return;
      const v = r.vencimento ? String(r.vencimento).slice(0, 10) : null;
      if (v === iso) saiDia += parseFloat(r.valor) || 0;
    });

    acum += entDia - saiDia;

    if (lbl || days <= 30) {
      labels.push(lbl || iso.slice(5));
      entradas.push(entDia);
      saidas.push(saiDia);
      saldo.push(acum);
    }
  }

  return {
    labels,
    datasets: [
      {
        label: 'Entradas previstas',
        data: entradas,
        borderColor: 'rgba(91,177,122,0.9)',
        backgroundColor: 'rgba(91,177,122,0.08)',
        fill: true, tension: 0.3, pointRadius: days <= 30 ? 2 : 0, borderWidth: 2,
      },
      {
        label: 'Saídas previstas',
        data: saidas,
        borderColor: 'rgba(217,101,94,0.9)',
        backgroundColor: 'rgba(217,101,94,0.06)',
        fill: true, tension: 0.3, pointRadius: days <= 30 ? 2 : 0, borderWidth: 2,
      },
      {
        label: 'Saldo projetado',
        data: saldo,
        borderColor: 'rgba(201,163,107,1)',
        backgroundColor: 'rgba(201,163,107,0.06)',
        fill: true, tension: 0.4, pointRadius: 0, borderWidth: 2.5, borderDash: [6, 3],
      },
    ],
  };
}

function FluxoCaixaChart({ receber, pagar, periodo }) {
  const data = React.useMemo(() => buildFluxoData(receber, pagar, periodo), [receber, pagar, periodo]);

  return (
    <ChartCanvas
      type="line"
      data={data}
      height={260}
      options={{
        scales: {
          x: { grid: { color: 'rgba(255,255,255,0.06)' }, ticks: { color: 'rgba(255,255,255,0.55)', font: { size: 10 }, maxRotation: 45 } },
          y: { grid: { color: 'rgba(255,255,255,0.06)' }, ticks: { color: 'rgba(255,255,255,0.55)', font: { size: 10 }, callback: v => v >= 1000 ? `${(v / 1000).toFixed(0)}k` : v } },
        },
        plugins: {
          legend: { display: true, position: 'bottom', labels: { color: 'rgba(255,255,255,0.7)', font: { size: 11 }, boxWidth: 12, padding: 16 } },
          tooltip: { callbacks: { label: ctx => `${ctx.dataset.label}: R$ ${brl(ctx.raw)}` } },
        },
      }}
    />
  );
}

// ─── Dashboard Financeiro Widgets ────────────────────────────────────────────

function FinDashKpi({ label, value, sub, tone, onClick }) {
  const style = {
    padding: 14, borderRadius: 8, cursor: onClick ? 'pointer' : 'default',
    background: 'var(--tm-bg-2)', border: '1px solid var(--tm-line-1)',
    transition: 'transform 0.15s',
  };
  return (
    <div style={style} onClick={onClick}
      onMouseEnter={e => { if (onClick) e.currentTarget.style.transform = 'translateY(-2px)'; }}
      onMouseLeave={e => { e.currentTarget.style.transform = ''; }}>
      <div style={{ fontSize: 10.5, color: 'var(--tm-fg-4)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 4 }}>{label}</div>
      <div style={{ fontSize: 20, fontWeight: 700, color: tone ? `var(--tm-${tone})` : 'var(--tm-fg-1)', fontVariantNumeric: 'tabular-nums' }}>{value}</div>
      {sub && <div style={{ fontSize: 11, color: 'var(--tm-fg-4)', marginTop: 2 }}>{sub}</div>}
    </div>
  );
}

// ─── Mapeamento DRE ─────────────────────────────────────────────────────────

const DRE_MAP = {
  'Matéria-prima': 'custo',
  'Embalagens':    'custo',
  'Produção':      'custo',
  'Frete':         'custo',
  'Marketing':     'despesa_comercial',
  'Marketplace':   'despesa_comercial',
  'Salários':      'despesa_folha',
  'Folha':         'despesa_folha',
  'Aluguel':       'despesa_operacional',
  'Energia':       'despesa_operacional',
  'Água':          'despesa_operacional',
  'Internet/Telefone': 'despesa_operacional',
  'Manutenção':    'despesa_operacional',
  'Software/SaaS': 'despesa_operacional',
  'Impostos':      'imposto',
  'Outros':        'despesa_operacional',
};

function buildDRE(recRows, pagRows, mesIso) {
  // mesIso = "2026-05" por exemplo
  const recMes = recRows.filter(r => {
    if (r.status !== 'Recebido') return false;
    const dp = r.data_pagamento || r.dataPagamento || r.vencimento || '';
    return String(dp).slice(0, 7) === mesIso;
  });
  const pagMes = pagRows.filter(r => {
    if (r.status !== 'Pago') return false;
    const dp = r.data_pagamento || r.dataPagamento || r.vencimento || '';
    return String(dp).slice(0, 7) === mesIso;
  });

  const receitaBruta = recMes.reduce((a, r) => a + (parseFloat(r.valor_recebido || r.recebido || r.valor) || 0), 0);

  const grupos = { custo: 0, despesa_comercial: 0, despesa_folha: 0, despesa_operacional: 0, imposto: 0 };
  const detalhes = { custo: [], despesa_comercial: [], despesa_folha: [], despesa_operacional: [], imposto: [] };

  pagMes.forEach(r => {
    const cat = r.cat || r.categoria || 'Outros';
    const cls = DRE_MAP[cat] || 'despesa_operacional';
    const val = parseFloat(r.valor) || 0;
    grupos[cls] += val;
    detalhes[cls].push({ desc: r.forn || r.fornecedor || cat, cat, valor: val });
  });

  const custoTotal = grupos.custo;
  const lucroBruto = receitaBruta - custoTotal;
  const despesasTotal = grupos.despesa_comercial + grupos.despesa_folha + grupos.despesa_operacional;
  const impostoTotal = grupos.imposto;
  const resultadoLiquido = lucroBruto - despesasTotal - impostoTotal;
  const margemBruta = receitaBruta > 0 ? (lucroBruto / receitaBruta) * 100 : 0;
  const margemLiquida = receitaBruta > 0 ? (resultadoLiquido / receitaBruta) * 100 : 0;

  return {
    receitaBruta, custoTotal, lucroBruto, despesasTotal, impostoTotal, resultadoLiquido,
    margemBruta, margemLiquida,
    grupos, detalhes,
    recCount: recMes.length, pagCount: pagMes.length,
  };
}

// ─── Timeline de Parcelas ───────────────────────────────────────────────────

function TimelineParcela({ parcelas }) {
  if (!parcelas || parcelas.length <= 1) return null;

  const today = new Date().toISOString().slice(0, 10);
  const sorted = [...parcelas].sort((a, b) => {
    const va = a.vencimento ? String(a.vencimento).slice(0, 10) : '';
    const vb = b.vencimento ? String(b.vencimento).slice(0, 10) : '';
    return va.localeCompare(vb);
  });

  const getColor = (p) => {
    if (p.status === 'Recebido' || p.status === 'Pago') return 'var(--tm-success)';
    const v = p.vencimento ? String(p.vencimento).slice(0, 10) : '';
    if (v === today) return 'var(--tm-brand-champagne)';
    if (v < today) return 'var(--tm-danger)';
    return 'var(--tm-fg-4)';
  };

  const getLabel = (p) => {
    if (p.status === 'Recebido' || p.status === 'Pago') return 'Pago';
    const v = p.vencimento ? String(p.vencimento).slice(0, 10) : '';
    if (v === today) return 'Hoje';
    if (v < today) return 'Atrasado';
    return 'Futuro';
  };

  const formatDate = (p) => {
    const v = p.vencimento ? String(p.vencimento).slice(0, 10) : '';
    if (!v || !v.includes('-')) return v;
    const [y, m, d] = v.split('-');
    return `${d}/${m}`;
  };

  return (
    <div style={{ marginBottom: 16 }}>
      <div style={{
        fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.08em',
        color: 'var(--tm-fg-4)', marginBottom: 10, paddingBottom: 4,
        borderBottom: '1px solid var(--tm-line-1)',
      }}>Timeline de parcelas</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 0, padding: '8px 0', overflowX: 'auto' }}>
        {sorted.map((p, i) => {
          const color = getColor(p);
          const isPago = p.status === 'Recebido' || p.status === 'Pago';
          return (
            <React.Fragment key={i}>
              {i > 0 && (
                <div style={{
                  flex: 1, minWidth: 24, height: 2,
                  background: isPago ? 'var(--tm-success)' : 'var(--tm-line-1)',
                }} />
              )}
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', minWidth: 56, position: 'relative' }}>
                <div style={{
                  width: 20, height: 20, borderRadius: '50%',
                  background: isPago ? color : 'transparent',
                  border: `2.5px solid ${color}`,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: 10, fontWeight: 700, color: isPago ? '#fff' : color,
                }}>
                  {isPago ? <Icon name="check" size={11} /> : (p.numero_parcela || p.numParcela || i + 1)}
                </div>
                <div style={{ fontSize: 10, color, marginTop: 4, fontWeight: 600 }}>
                  {formatDate(p)}
                </div>
                <div style={{ fontSize: 9, color: 'var(--tm-fg-4)', marginTop: 1 }}>
                  R$ {brl(p.valor)}
                </div>
                <div style={{
                  fontSize: 8, color, marginTop: 2, textTransform: 'uppercase',
                  fontWeight: 600, letterSpacing: '0.04em',
                }}>
                  {getLabel(p)}
                </div>
              </div>
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

// ─── Tabs ────────────────────────────────────────────────────────────────────

function FinanceiroTabs({ active, onNav }) {
  const tabs = [
    { id: 'dashboard',      label: 'Dashboard' },
    { id: 'contas-receber',  label: 'Contas a Receber' },
    { id: 'contas-pagar',    label: 'Contas a Pagar' },
    { id: 'entradas',        label: 'Entradas' },
    { id: 'saidas',          label: 'Saídas' },
    { id: 'fluxo-caixa',     label: 'Fluxo de Caixa' },
    { id: 'dre',             label: 'DRE' },
    { id: 'extrato',         label: 'Extrato' },
  ];
  return (
    <div className="tabs">
      {tabs.map(t => (
        <div key={t.id} className={`tab ${active === t.id ? 'active' : ''}`}
          onClick={() => onNav(`financeiro/${t.id}`)}>{t.label}</div>
      ))}
    </div>
  );
}

// ─── Utilitários de data ─────────────────────────────────────────────────────

function addDaysIso(isoDate, days) {
  const d = new Date(isoDate);
  d.setDate(d.getDate() + days);
  return d.toISOString().slice(0, 10);
}

// ─── Exports ─────────────────────────────────────────────────────────────────

Object.assign(window, {
  FIN_STATUS_TONE, CATEGORIAS_DESPESA, FORMAS_PAGAMENTO,
  computeFinStatus, FinStatusBadge,
  finRecKpis, finPagKpis,
  FinRowActions, FluxoCaixaChart, buildFluxoData,
  FinDashKpi, FinanceiroTabs, addDaysIso,
  DRE_MAP, buildDRE, TimelineParcela,
});
