// ============================================================
// Octale Legal — Painel de Créditos do Gestor (spec §5)
// Voltado ao CLIENTE (dono/admin da organização). Mostra apenas
// preços em créditos e saldos — nunca custo/markup interno.
// 1 crédito = R$ 1,00.
// ============================================================

// ─── Formatação ──────────────────────────────────────────────
const _nf = (x) =>
  Number(x || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const cred = (x) => `${_nf(x)} créditos`;
const brl = (x) => `R$ ${_nf(x)}`;

// ─── Mapas de rótulos (pt-BR) ────────────────────────────────
const QUOTA_LABELS = {
  monitoramento_diarios: 'Monitoramento de diários',
  busca_ativa_oab: 'Busca ativa por OAB',
  download_autos: 'Download de autos',
  distribuicao_processos: 'Distribuição de novos processos',
};
const CREDIT_SERVICE_LABELS = {
  download_autos: 'Download de autos',
  busca_ativa_oab: 'Busca ativa por OAB',
  consulta_cnj_tribunal: 'Consulta CNJ (Tribunal)',
  consulta_cnj_jus: 'Consulta CNJ (Jus)',
  monitoramento_diarios: 'Monitoramento de diários',
  distribuicao_processos: 'Distribuição de novos processos',
};
const svcLabel = (s) => CREDIT_SERVICE_LABELS[s] || QUOTA_LABELS[s] || s || '—';

const TX_TYPE_LABELS = {
  purchase: 'Recarga', debit: 'Débito', refund: 'Estorno',
  bonus: 'Bônus', expiration: 'Expiração',
};
const TX_TYPE_COLORS = {
  purchase: '#065f46', debit: '#991b1b', refund: '#1e40af',
  bonus: '#4c1d95', expiration: '#92400e',
};
const TX_STATUS_LABELS = { completed: 'Concluído', cancelled: 'Estornado', pending: 'Pendente' };

const PAY_STATUS_LABELS = { pending: 'Pendente', confirmed: 'Confirmado', failed: 'Falhou' };
const PAY_STATUS_COLORS = {
  pending: ['#fef3c7', '#92400e'], confirmed: ['#d1fae5', '#065f46'], failed: ['#fee2e2', '#991b1b'],
};

// ─── Cores de estilo ─────────────────────────────────────────
const C_GREEN = '#1F9D55';
const C_YELLOW = '#D49A1A';
const C_RED = '#C2253E';

const CARD = { background: '#fff', border: '1px solid var(--border)', borderRadius: 12, padding: 20 };
const SEC_TITLE = { fontSize: 15, fontWeight: 800, color: 'var(--octale-navy)', margin: 0 };
const EYEBROW = {
  fontSize: 10.5, fontWeight: 700, textTransform: 'uppercase',
  letterSpacing: '.07em', color: 'var(--fg-muted)',
};

// ─── Utilitários visuais ─────────────────────────────────────
const Spinner = ({ size = 22 }) => (
  <div style={{ display: 'flex', justifyContent: 'center', padding: 40 }}>
    <div className="spinner" style={{ width: size, height: size }} />
  </div>
);

const Badge = ({ text, bg, fg }) => (
  <span style={{
    display: 'inline-block', fontSize: 10.5, fontWeight: 700, padding: '2px 9px',
    borderRadius: 999, background: bg, color: fg, whiteSpace: 'nowrap',
  }}>{text}</span>
);

const InitialsChip = ({ user }) => {
  const u = user || {};
  const initials = u.initials || (u.name || '?').slice(0, 2).toUpperCase();
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7 }}>
      <span style={{
        width: 24, height: 24, borderRadius: 999, background: u.color || 'var(--octale-navy)',
        color: '#fff', fontSize: 10, fontWeight: 800, display: 'inline-flex',
        alignItems: 'center', justifyContent: 'center', flexShrink: 0,
      }}>{initials}</span>
      <span style={{ fontSize: 12.5 }}>{u.name || '—'}</span>
    </span>
  );
};

// Toggle inline (sem :hover — apenas estado on/off)
const Toggle = ({ on, onClick, disabled }) => (
  <button
    type="button"
    onClick={disabled ? undefined : onClick}
    disabled={disabled}
    aria-pressed={on}
    style={{
      width: 38, height: 22, borderRadius: 999, border: 'none', position: 'relative',
      cursor: disabled ? 'default' : 'pointer', flexShrink: 0,
      background: on ? 'var(--octale-navy)' : '#d1d5db', opacity: disabled ? 0.55 : 1,
      transition: 'background .2s',
    }}
  >
    <span style={{
      position: 'absolute', top: 2, left: on ? 18 : 2, width: 18, height: 18,
      borderRadius: '50%', background: '#fff', transition: 'left .2s',
    }} />
  </button>
);

// ─── Modal de compra de créditos ─────────────────────────────
const BuyCreditsModal = ({ packages, onClose, onPurchased }) => {
  const [pkgId, setPkgId] = React.useState(packages[0]?.id || null);
  const [method, setMethod] = React.useState('pix');
  const [saving, setSaving] = React.useState(false);
  const [err, setErr] = React.useState('');
  const [done, setDone] = React.useState(null); // purchase pendente

  React.useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', h);
    return () => document.removeEventListener('keydown', h);
  }, [onClose]);

  const confirm = async () => {
    if (!pkgId) { setErr('Selecione um pacote.'); return; }
    setSaving(true); setErr('');
    try {
      const purchase = await window.OctaleApi.credits.createPurchase(pkgId, method);
      setDone(purchase || {});
      onPurchased && onPurchased(purchase);
    } catch (e) {
      setErr(e.message || 'Erro ao registrar recarga.');
    } finally {
      setSaving(false);
    }
  };

  return (
    <div
      onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
      style={{
        position: 'fixed', inset: 0, background: 'rgba(23,23,15,.55)', zIndex: 9999,
        display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16,
      }}
    >
      <div style={{ background: '#fff', borderRadius: 14, padding: 28, width: 560, maxWidth: '94vw', maxHeight: '90vh', overflow: 'auto' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4 }}>
          <h2 style={{ ...SEC_TITLE, fontSize: 18 }}>Comprar créditos</h2>
          <button className="btn ghost sm" onClick={onClose} style={{ padding: '0 8px' }}>
            <Icon name="x" size={15} />
          </button>
        </div>

        {done ? (
          <div style={{ padding: '18px 0 4px' }}>
            <div style={{
              display: 'flex', alignItems: 'flex-start', gap: 12, padding: '14px 16px',
              background: 'rgba(31,157,85,.08)', border: '1px solid rgba(31,157,85,.3)', borderRadius: 10,
            }}>
              <span style={{ color: C_GREEN, marginTop: 1 }}><Icon name="check" size={20} /></span>
              <div>
                <div style={{ fontWeight: 800, color: 'var(--octale-black)', fontSize: 14 }}>
                  Recarga registrada
                </div>
                <div style={{ fontSize: 12.5, color: 'var(--fg-muted)', marginTop: 4, lineHeight: 1.5 }}>
                  Sua recarga foi registrada e está <b>aguardando confirmação de pagamento</b>.
                  O gateway de pagamento ainda será conectado — assim que o pagamento
                  {method === 'pix' ? ' via Pix' : ' no cartão'} for confirmado, os créditos
                  entram automaticamente no seu saldo.
                </div>
              </div>
            </div>
            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 20 }}>
              <button className="btn" onClick={onClose}>Entendi</button>
            </div>
          </div>
        ) : (
          <>
            <p style={{ fontSize: 12.5, color: 'var(--fg-muted)', margin: '4px 0 18px' }}>
              1 crédito = R$ 1,00. Escolha um pacote e a forma de pagamento.
            </p>

            {packages.length === 0 ? (
              <div style={{ textAlign: 'center', padding: '32px 0', color: 'var(--fg-muted)', fontSize: 13 }}>
                Nenhum pacote disponível no momento.
              </div>
            ) : (
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(160px,1fr))', gap: 12, marginBottom: 20 }}>
                {packages.map((p) => {
                  const total = Number(p.credits || 0) + Number(p.bonus || 0);
                  const active = p.id === pkgId;
                  return (
                    <button
                      key={p.id}
                      type="button"
                      onClick={() => setPkgId(p.id)}
                      style={{
                        textAlign: 'left', cursor: 'pointer', borderRadius: 10, padding: 14,
                        background: active ? 'rgba(23,23,15,.03)' : '#fff',
                        border: active ? '2px solid var(--octale-navy)' : '1px solid var(--border)',
                      }}
                    >
                      <div style={{ fontWeight: 800, fontSize: 14, color: 'var(--octale-black)' }}>{p.label}</div>
                      <div style={{ fontSize: 12.5, color: 'var(--fg-muted)', marginTop: 4 }}>
                        {cred(p.credits)}
                        {Number(p.bonus) > 0 && (
                          <span style={{ color: C_GREEN, fontWeight: 700 }}> +{_nf(p.bonus)} bônus</span>
                        )}
                      </div>
                      <div style={{ fontSize: 12, color: 'var(--fg-muted)', marginTop: 2 }}>
                        = {cred(total)}
                      </div>
                      <div style={{ fontWeight: 800, fontSize: 15, color: 'var(--octale-navy)', marginTop: 8 }}>
                        {brl(p.amount_brl)}
                      </div>
                    </button>
                  );
                })}
              </div>
            )}

            <div style={{ ...EYEBROW, marginBottom: 8 }}>Forma de pagamento</div>
            <div style={{ display: 'flex', gap: 10, marginBottom: 20 }}>
              {[['pix', 'Pix'], ['credit_card', 'Cartão']].map(([val, label]) => (
                <button
                  key={val}
                  type="button"
                  onClick={() => setMethod(val)}
                  style={{
                    flex: 1, cursor: 'pointer', borderRadius: 8, padding: '10px 14px', fontSize: 13, fontWeight: 700,
                    background: method === val ? 'var(--octale-navy)' : '#fff',
                    color: method === val ? '#fff' : 'var(--octale-navy)',
                    border: method === val ? '1px solid var(--octale-navy)' : '1px solid var(--border)',
                  }}
                >{label}</button>
              ))}
            </div>

            {err && (
              <div style={{ padding: '9px 12px', background: 'rgba(194,37,62,.08)', border: '1px solid rgba(194,37,62,.2)', borderRadius: 6, color: C_RED, fontSize: 12.5, marginBottom: 14 }}>
                {err}
              </div>
            )}

            <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end' }}>
              <button className="btn ghost" onClick={onClose}>Cancelar</button>
              <button className="btn" onClick={confirm} disabled={saving || !pkgId}>
                {saving
                  ? <><span className="spinner" style={{ width: 12, height: 12, borderWidth: 2, marginRight: 6 }} />Registrando…</>
                  : 'Confirmar recarga'}
              </button>
            </div>
          </>
        )}
      </div>
    </div>
  );
};

// ─── Bloco §5.1 — Saldo e Recarga ────────────────────────────
const SaldoRecarga = ({ wallet, balanceBrl, alerts, packages, purchases, onRefresh }) => {
  const [modalOpen, setModalOpen] = React.useState(false);
  const [showPurchases, setShowPurchases] = React.useState(false);

  const balance = Number(wallet?.balance || 0);
  const brlEquiv = balanceBrl != null ? balanceBrl : balance; // 1:1

  const lowAlert = (alerts || []).find(a => a.kind === 'low_balance');
  const zeroAlert = (alerts || []).find(a => a.kind === 'zero_balance');

  return (
    <>
      {/* Banners de alerta */}
      {zeroAlert && (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12, padding: '14px 18px', marginBottom: 14,
          background: 'rgba(194,37,62,.1)', border: `1.5px solid ${C_RED}`, borderRadius: 10,
        }}>
          <span style={{ color: C_RED }}><Icon name="bell" size={20} /></span>
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 800, color: C_RED, fontSize: 13.5 }}>Saldo esgotado</div>
            <div style={{ fontSize: 12.5, color: 'var(--octale-black)', marginTop: 2 }}>
              {zeroAlert.message || 'Seus créditos acabaram. Recarregue para continuar usando os serviços por crédito.'}
            </div>
          </div>
          <button className="btn sm" onClick={() => setModalOpen(true)}>Recarregar</button>
        </div>
      )}
      {lowAlert && !zeroAlert && (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 12, padding: '12px 18px', marginBottom: 14,
          background: 'rgba(212,154,26,.12)', border: `1px solid ${C_YELLOW}`, borderRadius: 10,
        }}>
          <span style={{ color: C_YELLOW }}><Icon name="bell" size={18} /></span>
          <div style={{ flex: 1, fontSize: 12.5, color: 'var(--octale-black)' }}>
            {lowAlert.message || 'Seu saldo de créditos está baixo. Considere recarregar em breve.'}
          </div>
        </div>
      )}

      <div style={{ ...CARD, display: 'flex', flexDirection: 'column', gap: 16 }}>
        <div style={EYEBROW}>Saldo disponível</div>
        <div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 10, flexWrap: 'wrap' }}>
            <span style={{ fontSize: 40, fontWeight: 800, color: 'var(--octale-navy)', lineHeight: 1 }}>
              {_nf(balance)}
            </span>
            <span style={{ fontSize: 18, fontWeight: 700, color: 'var(--fg-muted)' }}>créditos disponíveis</span>
          </div>
          <div style={{ fontSize: 13.5, color: 'var(--fg-muted)', marginTop: 8 }}>
            Equivalente a <b style={{ color: 'var(--octale-black)' }}>{brl(brlEquiv)}</b>
          </div>
        </div>

        <div style={{ display: 'flex', gap: 20, flexWrap: 'wrap', fontSize: 12, color: 'var(--fg-muted)', paddingTop: 4 }}>
          <span>Comprado: <b style={{ color: 'var(--octale-black)' }}>{cred(wallet?.total_purchased)}</b></span>
          <span>Bônus: <b style={{ color: C_GREEN }}>{cred(wallet?.total_bonus)}</b></span>
          <span>Consumido: <b style={{ color: 'var(--octale-black)' }}>{cred(wallet?.total_consumed)}</b></span>
        </div>

        <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
          <button className="btn" onClick={() => setModalOpen(true)}>
            <Icon name="creditCard" size={14} /> Comprar créditos
          </button>
          <button className="btn ghost sm" onClick={() => setShowPurchases(v => !v)}>
            Histórico de recargas <Icon name={showPurchases ? 'chevronDown' : 'chevronRight'} size={13} />
          </button>
        </div>

        {showPurchases && (
          <div style={{ borderTop: '1px solid var(--border)', paddingTop: 14 }}>
            {(!purchases || purchases.length === 0) ? (
              <div style={{ fontSize: 12.5, color: 'var(--fg-muted)', padding: '8px 0' }}>
                Nenhuma recarga registrada ainda.
              </div>
            ) : (
              <div style={{ overflowX: 'auto' }}>
                <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5, minWidth: 420 }}>
                  <thead>
                    <tr>
                      {['Data', 'Pacote', 'Créditos', 'Valor', 'Status'].map(h => (
                        <th key={h} style={{ textAlign: h === 'Valor' || h === 'Créditos' ? 'right' : 'left', ...EYEBROW, padding: '6px 8px', borderBottom: '1px solid var(--border)' }}>{h}</th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {purchases.map((p, i) => {
                      const st = p.payment_status || 'pending';
                      const [bg, fg] = PAY_STATUS_COLORS[st] || PAY_STATUS_COLORS.pending;
                      const totalCred = Number(p.credits_purchased || 0) + Number(p.credits_bonus || 0);
                      return (
                        <tr key={i}>
                          <td style={{ padding: '8px', borderBottom: '1px solid var(--border)', color: 'var(--fg-muted)', whiteSpace: 'nowrap' }}>
                            {p.created_at ? new Date(p.created_at).toLocaleDateString('pt-BR') : '—'}
                          </td>
                          <td style={{ padding: '8px', borderBottom: '1px solid var(--border)' }}>
                            {(packages.find(pk => pk.id === p.package_id) || {}).label || p.package_id || '—'}
                          </td>
                          <td style={{ padding: '8px', borderBottom: '1px solid var(--border)', textAlign: 'right' }}>{_nf(totalCred)}</td>
                          <td style={{ padding: '8px', borderBottom: '1px solid var(--border)', textAlign: 'right', fontWeight: 600 }}>{brl(p.amount_brl)}</td>
                          <td style={{ padding: '8px', borderBottom: '1px solid var(--border)' }}>
                            <Badge text={PAY_STATUS_LABELS[st] || st} bg={bg} fg={fg} />
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        )}
      </div>

      {modalOpen && (
        <BuyCreditsModal
          packages={packages || []}
          onClose={() => setModalOpen(false)}
          onPurchased={() => { onRefresh && onRefresh(); }}
        />
      )}
    </>
  );
};

// ─── Bloco §5.2 — Franquia do Plano ──────────────────────────
const FranquiaPlano = ({ quotas }) => {
  const list = quotas?.quotas || [];
  return (
    <div style={CARD}>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 4 }}>
        <h3 style={SEC_TITLE}>Franquia do plano</h3>
        {quotas?.plan_id && <span style={EYEBROW}>Plano: {quotas.plan_id}</span>}
      </div>
      <p style={{ fontSize: 12.5, color: 'var(--fg-muted)', margin: '0 0 16px' }}>Consumo incluído no plano neste mês.</p>

      {list.length === 0 ? (
        <div style={{ fontSize: 13, color: 'var(--fg-muted)', padding: '12px 0' }}>Nenhuma franquia configurada.</div>
      ) : (
        <div style={{ display: 'grid', gap: 16 }}>
          {list.map((q) => {
            const limit = Number(q.quota_limit || 0);
            const consumed = Number(q.consumed || 0);
            const hasFranchise = limit > 0;
            const pct = hasFranchise ? Math.round((consumed / limit) * 100) : (consumed > 0 ? 100 : 0);
            const barColor = !hasFranchise ? '#c7c7cf' : pct >= 100 ? C_RED : pct >= 80 ? C_YELLOW : C_GREEN;
            return (
              <div key={q.service}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6, gap: 12, flexWrap: 'wrap' }}>
                  <span style={{ fontSize: 13, fontWeight: 700, color: 'var(--octale-black)' }}>{QUOTA_LABELS[q.service] || q.service}</span>
                  <span style={{ fontSize: 12, color: 'var(--fg-muted)' }}>
                    {hasFranchise
                      ? <><b style={{ color: 'var(--octale-black)' }}>{_nf(consumed)}</b> de {_nf(limit)} este mês</>
                      : <span style={{ fontWeight: 700 }}>Por créditos</span>}
                  </span>
                </div>
                <div style={{ height: 10, borderRadius: 999, background: 'rgba(23,23,15,.07)', overflow: 'hidden' }}>
                  <div style={{ height: '100%', width: `${Math.min(pct, 100)}%`, background: barColor, borderRadius: 999, transition: 'width .3s' }} />
                </div>
                {hasFranchise && (
                  <div style={{ fontSize: 11, color: pct >= 100 ? C_RED : 'var(--fg-muted)', marginTop: 4 }}>
                    {pct}% utilizado{pct >= 100 ? ' — excedente será cobrado por créditos' : ''}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
};

// ─── Bloco §5.3 — Consumo por Créditos ───────────────────────
const ConsumoCreditos = ({ consumption }) => {
  const total = Number(consumption?.total || 0);
  const byService = consumption?.byService || {};
  const entries = Object.entries(byService).sort((a, b) => Number(b[1]) - Number(a[1]));
  const max = entries.reduce((m, [, v]) => Math.max(m, Number(v) || 0), 0) || 1;
  const projection = consumption?.projection;
  const topKey = typeof consumption?.topService === 'string'
    ? consumption.topService
    : consumption?.topService?.service;

  return (
    <div style={CARD}>
      <h3 style={SEC_TITLE}>Consumo por créditos</h3>
      <p style={{ fontSize: 12.5, color: 'var(--fg-muted)', margin: '4px 0 16px' }}>Serviços cobrados por crédito neste mês.</p>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(180px,1fr))', gap: 12, marginBottom: 18 }}>
        <div style={{ background: 'var(--octale-off-white)', borderRadius: 10, padding: '12px 14px' }}>
          <div style={EYEBROW}>Total debitado no mês</div>
          <div style={{ fontSize: 20, fontWeight: 800, color: 'var(--octale-navy)', marginTop: 4 }}>{cred(total)}</div>
        </div>
        <div style={{ background: 'var(--octale-off-white)', borderRadius: 10, padding: '12px 14px' }}>
          <div style={EYEBROW}>Maior uso</div>
          <div style={{ fontSize: 15, fontWeight: 800, color: 'var(--octale-black)', marginTop: 6 }}>
            {topKey ? svcLabel(topKey) : '—'}
          </div>
        </div>
        {projection != null && (
          <div style={{ background: 'var(--octale-off-white)', borderRadius: 10, padding: '12px 14px' }}>
            <div style={{ ...EYEBROW, display: 'flex', alignItems: 'center', gap: 5 }}>
              <Icon name="trendingUp" size={13} /> Projeção de gasto
            </div>
            <div style={{ fontSize: 12.5, color: 'var(--octale-black)', marginTop: 6, lineHeight: 1.4 }}>
              Mantendo o ritmo, gastará ~<b>{cred(projection)}</b> até o fim do mês.
            </div>
          </div>
        )}
      </div>

      {entries.length === 0 ? (
        <div style={{ fontSize: 13, color: 'var(--fg-muted)', padding: '8px 0' }}>Nenhum consumo por crédito neste mês.</div>
      ) : (
        <div style={{ display: 'grid', gap: 10 }}>
          {entries.map(([svc, val]) => {
            const v = Number(val) || 0;
            return (
              <div key={svc}>
                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12.5, marginBottom: 4 }}>
                  <span style={{ color: 'var(--octale-black)', fontWeight: 600 }}>{svcLabel(svc)}</span>
                  <span style={{ color: 'var(--fg-muted)' }}>{cred(v)}</span>
                </div>
                <div style={{ height: 8, borderRadius: 999, background: 'rgba(23,23,15,.06)', overflow: 'hidden' }}>
                  <div style={{ height: '100%', width: `${Math.max((v / max) * 100, 2)}%`, background: 'var(--octale-navy)', borderRadius: 999 }} />
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
};

// ─── Bloco §5.4 — Histórico de Transações ────────────────────
const HistoricoTransacoes = () => {
  const [filters, setFilters] = React.useState({ type: '', service: '', from: '', to: '' });
  const [page, setPage] = React.useState(1);
  const [data, setData] = React.useState({ data: [], total: 0, hasMore: false });
  const [loading, setLoading] = React.useState(true);
  const LIMIT = 15;

  const setF = (k, v) => { setPage(1); setFilters(f => ({ ...f, [k]: v })); };

  React.useEffect(() => {
    let alive = true;
    setLoading(true);
    const params = { page, limit: LIMIT };
    if (filters.type) params.type = filters.type;
    if (filters.service) params.service = filters.service;
    if (filters.from) params.from = filters.from;
    if (filters.to) params.to = filters.to;
    window.OctaleApi.credits.transactions(params)
      .then((res) => { if (alive) setData(res || { data: [], total: 0, hasMore: false }); })
      .catch(() => { if (alive) setData({ data: [], total: 0, hasMore: false }); })
      .finally(() => { if (alive) setLoading(false); });
    return () => { alive = false; };
  }, [filters, page]);

  const rows = data.data || [];
  const selStyle = { padding: '7px 10px', border: '1px solid var(--border)', borderRadius: 6, fontSize: 12.5, background: '#fff', color: 'var(--octale-black)' };
  const th = { textAlign: 'left', ...EYEBROW, padding: '8px 10px', borderBottom: '1px solid var(--border)', whiteSpace: 'nowrap' };
  const td = { padding: '9px 10px', borderBottom: '1px solid var(--border)', verticalAlign: 'middle' };

  return (
    <div style={CARD}>
      <h3 style={SEC_TITLE}>Histórico de transações</h3>

      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', margin: '14px 0 16px' }}>
        <select style={selStyle} value={filters.type} onChange={e => setF('type', e.target.value)}>
          <option value="">Todos os tipos</option>
          {Object.entries(TX_TYPE_LABELS).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
        </select>
        <select style={selStyle} value={filters.service} onChange={e => setF('service', e.target.value)}>
          <option value="">Todos os serviços</option>
          {Object.entries(CREDIT_SERVICE_LABELS).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
        </select>
        <input type="date" style={selStyle} value={filters.from} onChange={e => setF('from', e.target.value)} title="De" />
        <input type="date" style={selStyle} value={filters.to} onChange={e => setF('to', e.target.value)} title="Até" />
        {(filters.type || filters.service || filters.from || filters.to) && (
          <button className="btn ghost sm" onClick={() => { setPage(1); setFilters({ type: '', service: '', from: '', to: '' }); }}>Limpar</button>
        )}
      </div>

      {loading ? <Spinner /> : rows.length === 0 ? (
        <div style={{ textAlign: 'center', padding: '36px 0', color: 'var(--fg-muted)', fontSize: 13 }}>
          Nenhuma transação encontrada.
        </div>
      ) : (
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5, minWidth: 760 }}>
            <thead>
              <tr>
                <th style={th}>Data e hora</th>
                <th style={th}>Tipo</th>
                <th style={th}>Serviço</th>
                <th style={th}>Processo/OAB</th>
                <th style={th}>Usuário</th>
                <th style={{ ...th, textAlign: 'right' }}>Créditos</th>
                <th style={{ ...th, textAlign: 'right' }}>Saldo após</th>
                <th style={{ ...th, textAlign: 'center' }}>Status</th>
              </tr>
            </thead>
            <tbody>
              {rows.map((t, i) => {
                const amt = Number(t.amount || 0);
                const meta = t.metadata || {};
                const ref = meta.cnj || meta.oab || '—';
                return (
                  <tr key={i}>
                    <td style={{ ...td, color: 'var(--fg-muted)', whiteSpace: 'nowrap' }}>
                      {t.created_at ? new Date(t.created_at).toLocaleString('pt-BR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }) : '—'}
                    </td>
                    <td style={td}>
                      <span style={{ fontWeight: 700, color: TX_TYPE_COLORS[t.type] || 'var(--octale-black)' }}>
                        {TX_TYPE_LABELS[t.type] || t.type}
                      </span>
                    </td>
                    <td style={td}>{t.service ? svcLabel(t.service) : '—'}</td>
                    <td style={{ ...td, color: 'var(--fg-muted)' }}>{ref}</td>
                    <td style={td}>{t.user ? <InitialsChip user={t.user} /> : '—'}</td>
                    <td style={{ ...td, textAlign: 'right', fontWeight: 700, color: amt < 0 ? C_RED : C_GREEN, whiteSpace: 'nowrap' }}>
                      {amt > 0 ? '+' : ''}{_nf(amt)}
                    </td>
                    <td style={{ ...td, textAlign: 'right', color: 'var(--octale-black)' }}>
                      {t.balance_after != null ? _nf(t.balance_after) : '—'}
                    </td>
                    <td style={{ ...td, textAlign: 'center' }}>
                      <span style={{ fontSize: 11.5, color: 'var(--fg-muted)' }}>{TX_STATUS_LABELS[t.status] || t.status || '—'}</span>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}

      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 14 }}>
        <span style={{ fontSize: 12, color: 'var(--fg-muted)' }}>
          Página {page}{data.total ? ` · ${data.total} transações` : ''}
        </span>
        <div style={{ display: 'flex', gap: 8 }}>
          <button className="btn ghost sm" disabled={page <= 1 || loading} onClick={() => setPage(p => Math.max(1, p - 1))}>Anterior</button>
          <button className="btn ghost sm" disabled={!data.hasMore || loading} onClick={() => setPage(p => p + 1)}>Próxima</button>
        </div>
      </div>
    </div>
  );
};

// ─── Bloco §5.5 — Configurações de Alertas ───────────────────
const ConfigAlertas = ({ currentUser }) => {
  const canEdit = currentUser?.org_role === 'owner' || currentUser?.org_role === 'admin';
  const [open, setOpen] = React.useState(false);
  const [settings, setSettings] = React.useState(null);
  const [loading, setLoading] = React.useState(false);
  const [saving, setSaving] = React.useState(false);
  const [msg, setMsg] = React.useState('');
  const [loaded, setLoaded] = React.useState(false);

  React.useEffect(() => {
    if (!open || loaded) return;
    setLoading(true);
    window.OctaleApi.credits.alertSettings()
      .then((s) => { setSettings(s || {}); setLoaded(true); })
      .catch(() => { setSettings({}); setLoaded(true); })
      .finally(() => setLoading(false));
  }, [open, loaded]);

  const set = (k, v) => setSettings(s => ({ ...s, [k]: v }));

  const save = async () => {
    if (!canEdit) return;
    setSaving(true); setMsg('');
    try {
      const patch = {
        low_balance_threshold: Number(settings.low_balance_threshold) || 0,
        alert_80_franchise: !!settings.alert_80_franchise,
        email_on_recharge: !!settings.email_on_recharge,
        confirm_each_debit: !!settings.confirm_each_debit,
        monthly_spend_limit: settings.monthly_spend_limit === '' || settings.monthly_spend_limit == null
          ? null : Number(settings.monthly_spend_limit),
      };
      const updated = await window.OctaleApi.credits.updateAlertSettings(patch);
      setSettings(updated || patch);
      setMsg('Configurações salvas.');
      setTimeout(() => setMsg(''), 3000);
    } catch (e) {
      setMsg(e.message || 'Erro ao salvar.');
    } finally {
      setSaving(false);
    }
  };

  const Row = ({ label, hint, children }) => (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, padding: '12px 0', borderBottom: '1px solid var(--border)' }}>
      <div>
        <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--octale-black)' }}>{label}</div>
        {hint && <div style={{ fontSize: 11.5, color: 'var(--fg-muted)', marginTop: 2 }}>{hint}</div>}
      </div>
      <div style={{ flexShrink: 0 }}>{children}</div>
    </div>
  );

  const numInput = {
    width: 120, padding: '8px 10px', border: '1px solid var(--border)', borderRadius: 6,
    fontSize: 13, textAlign: 'right', background: canEdit ? '#fff' : 'var(--octale-off-white)', color: 'var(--octale-black)',
  };

  return (
    <div style={CARD}>
      <button
        type="button"
        onClick={() => setOpen(v => !v)}
        style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: 'transparent', border: 'none', padding: 0, cursor: 'pointer' }}
      >
        <span style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ color: 'var(--octale-navy)' }}><Icon name="settings" size={16} /></span>
          <span style={SEC_TITLE}>Configurações de alertas</span>
        </span>
        <Icon name={open ? 'chevronDown' : 'chevronRight'} size={16} />
      </button>

      {open && (
        <div style={{ marginTop: 16 }}>
          {!canEdit && (
            <div style={{ padding: '9px 12px', background: 'var(--octale-off-white)', borderRadius: 6, fontSize: 12, color: 'var(--fg-muted)', marginBottom: 12 }}>
              Somente o dono ou administrador da organização pode alterar estas configurações. Você está em modo leitura.
            </div>
          )}

          {loading ? <Spinner size={18} /> : !settings ? null : (
            <>
              <Row label="Alerta de saldo baixo (créditos)" hint="Avisa quando o saldo cair abaixo deste valor.">
                <input type="number" min="0" style={numInput} disabled={!canEdit}
                  value={settings.low_balance_threshold ?? ''}
                  onChange={e => set('low_balance_threshold', e.target.value)} />
              </Row>
              <Row label="Alerta de 80% da franquia" hint="Avisa ao atingir 80% de qualquer franquia do plano.">
                <Toggle on={!!settings.alert_80_franchise} disabled={!canEdit} onClick={() => set('alert_80_franchise', !settings.alert_80_franchise)} />
              </Row>
              <Row label="E-mail ao recarregar" hint="Envia confirmação por e-mail a cada recarga.">
                <Toggle on={!!settings.email_on_recharge} disabled={!canEdit} onClick={() => set('email_on_recharge', !settings.email_on_recharge)} />
              </Row>
              <Row label="Confirmar cada débito" hint="Pede confirmação antes de debitar créditos em cada uso.">
                <Toggle on={!!settings.confirm_each_debit} disabled={!canEdit} onClick={() => set('confirm_each_debit', !settings.confirm_each_debit)} />
              </Row>
              <Row label="Limite de gasto mensal (créditos)" hint="Deixe vazio para não definir limite.">
                <input type="number" min="0" placeholder="sem limite" style={numInput} disabled={!canEdit}
                  value={settings.monthly_spend_limit ?? ''}
                  onChange={e => set('monthly_spend_limit', e.target.value)} />
              </Row>

              {canEdit && (
                <div style={{ display: 'flex', alignItems: 'center', gap: 14, marginTop: 16 }}>
                  <button className="btn" onClick={save} disabled={saving}>
                    {saving
                      ? <><span className="spinner" style={{ width: 12, height: 12, borderWidth: 2, marginRight: 6 }} />Salvando…</>
                      : 'Salvar configurações'}
                  </button>
                  {msg && <span style={{ fontSize: 12.5, color: 'var(--fg-muted)' }}>{msg}</span>}
                </div>
              )}
            </>
          )}
        </div>
      )}
    </div>
  );
};

// ─── Componente raiz ─────────────────────────────────────────
const CreditsPanel = ({ currentUser }) => {
  const [state, setState] = React.useState({
    wallet: null, balanceBrl: null, quotas: null, consumption: null,
    alerts: [], packages: [], purchases: [],
  });
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState('');

  const load = React.useCallback(async () => {
    setLoading(true); setError('');
    const safe = (p) => p.then(r => r).catch(() => null);
    try {
      const [walletRes, quotasRes, consumptionRes, alertsRes, packagesRes, purchasesRes] = await Promise.all([
        safe(window.OctaleApi.credits.wallet()),
        safe(window.OctaleApi.credits.quotas()),
        safe(window.OctaleApi.credits.consumption()),
        safe(window.OctaleApi.credits.alerts()),
        safe(window.OctaleApi.credits.packages()),
        safe(window.OctaleApi.credits.purchases()),
      ]);
      setState({
        wallet: walletRes?.wallet || null,
        balanceBrl: walletRes?.balance_brl != null ? walletRes.balance_brl : null,
        quotas: quotasRes || null,
        consumption: consumptionRes || null,
        alerts: Array.isArray(alertsRes) ? alertsRes : [],
        packages: Array.isArray(packagesRes) ? packagesRes : [],
        purchases: Array.isArray(purchasesRes) ? purchasesRes : [],
      });
    } catch (e) {
      setError('Não foi possível carregar o painel de créditos.');
    } finally {
      setLoading(false);
    }
  }, []);

  React.useEffect(() => { load(); }, [load]);

  if (loading) {
    return (
      <div style={{ padding: '48px 32px', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12, color: 'var(--fg-muted)', fontSize: 13 }}>
        <div className="spinner" /> Carregando painel de créditos…
      </div>
    );
  }

  return (
    <div style={{ padding: '28px 32px', maxWidth: 1080, margin: '0 auto' }}>
      <div style={{ marginBottom: 20 }}>
        <div style={{ ...EYEBROW, letterSpacing: '.08em' }}>Créditos e franquia</div>
        <div style={{ fontSize: 20, fontWeight: 800, color: 'var(--octale-navy)', display: 'flex', alignItems: 'center', gap: 8 }}>
          <Icon name="coins" size={20} /> Painel de créditos
        </div>
      </div>

      {error && (
        <div style={{ padding: '10px 14px', background: 'rgba(194,37,62,.08)', border: '1px solid rgba(194,37,62,.2)', borderRadius: 8, color: C_RED, fontSize: 13, marginBottom: 16 }}>
          {error}
        </div>
      )}

      <div style={{ display: 'grid', gap: 16 }}>
        <SaldoRecarga
          wallet={state.wallet}
          balanceBrl={state.balanceBrl}
          alerts={state.alerts}
          packages={state.packages}
          purchases={state.purchases}
          onRefresh={load}
        />
        <FranquiaPlano quotas={state.quotas} />
        <ConsumoCreditos consumption={state.consumption} />
        <HistoricoTransacoes />
        <ConfigAlertas currentUser={currentUser} />
      </div>
    </div>
  );
};

window.CreditsPanel = CreditsPanel;
