function AssetsTable({ assets, onEdit, onDelete, onAdd, filter, onFilterChange, balanceHidden, cedearMap, isMobile }) {
  const [expandedId, setExpandedId] = React.useState(null);
  const filtered = assets.filter(a => {
    if (filter === 'todo') return true;
    if (filter === 'cripto') return a.type === 'cripto';
    if (filter === 'accion') return a.type === 'accion' || a.type === 'etf';
    return true;
  });

  return (
    <div style={{ background: 'var(--panel)', border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: '20px 0 4px', boxShadow: 'var(--shadow)' }}>
      <div className="table-header" style={{ display: 'flex', alignItems: 'center', padding: '0 24px 16px', gap: 16 }}>
        <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>Activos</h3>
        <div style={{ flex: 1 }} />
        <div className="tabs"><TabBar filter={filter} onFilterChange={onFilterChange} /></div>
        <button onClick={onAdd} style={{
          background: 'var(--accent)', color: '#1a0f05', fontWeight: 600, fontSize: 13,
          padding: '9px 16px', borderRadius: 10, display: 'inline-flex', alignItems: 'center', gap: 6,
        }}>
          <svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M8 3v10M3 8h10" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"/></svg>
          <span className="add-btn-label">Agregar Transacción</span>
        </button>
      </div>

      {/* Mobile: cards expandibles */}
      {isMobile ? (
        <div style={{ padding: '0 14px 14px', display: 'flex', flexDirection: 'column', gap: 8 }}>
          {filtered.length === 0 ? (
            <div style={{ padding: '36px 12px', textAlign: 'center', color: 'var(--text-dim)', fontSize: 13 }}>
              No hay activos en esta categoría. Agrega tu primera transacción para comenzar.
            </div>
          ) : filtered.map(a => (
            <MobileAssetCard
              key={a.id}
              asset={a}
              cedearMap={cedearMap}
              expanded={expandedId === a.id}
              onToggle={() => setExpandedId(prev => prev === a.id ? null : a.id)}
              onEdit={() => onEdit(a)}
              onDelete={() => onDelete(a.id)}
              balanceHidden={balanceHidden}
            />
          ))}
        </div>
      ) : (
      <div className="table-scroll">
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13.5 }}>
          <thead>
            <tr style={{ color: 'var(--text-dim)', fontSize: 12, fontWeight: 500 }}>
              <Th style={{ paddingLeft: 24 }}>Nombre</Th>
              <Th>Tipo</Th>
              <Th align="right">Precio</Th>
              <Th align="right">24h%</Th>
              <Th align="right">Cantidad</Th>
              <Th align="right">Monto actual</Th>
              <Th align="right">PPC</Th>
              <Th align="right">+/–</Th>
              <Th align="right" style={{ paddingRight: 24 }}>  </Th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(a => {
              const value = a.qty * a.currentPrice;
              const cost = a.qty * a.buyPrice;
              const pnl = value - cost;
              const pnlPct = (pnl / cost) * 100;
              return (
                <tr key={a.id} style={{ borderTop: '1px solid var(--border)' }}>
                  <Td style={{ paddingLeft: 24 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <TickerBadge ticker={a.ticker} type={a.type} iconUrl={a.iconUrl} />
                      <div style={{ lineHeight: 1.3 }}>
                        <div style={{ fontWeight: 600 }}>{a.ticker}</div>
                        <div style={{ color: 'var(--text-dim)', fontSize: 11.5 }}>{a.name}</div>
                      </div>
                    </div>
                  </Td>
                  <Td><TypePill type={a.type} /></Td>
                  <Td align="right">{window.formatPrice(a.currentPrice)}</Td>
                  <Td align="right">
                    <span style={{ color: a.change24 >= 0 ? 'var(--green)' : 'var(--red)', fontWeight: 500 }}>
                      {window.formatPct(a.change24)}
                    </span>
                  </Td>
                  <Td align="right" style={{ fontVariantNumeric: 'tabular-nums', minWidth: 160 }}>
                    <QuantityCell asset={a} cedearMap={cedearMap} />
                  </Td>
                  <Td align="right" style={{ fontVariantNumeric: 'tabular-nums' }}>{balanceHidden ? '••••••' : window.formatUSD(value)}</Td>
                  <Td align="right" style={{ fontVariantNumeric: 'tabular-nums', color: 'var(--text-dim)' }}>{window.formatPrice(a.buyPrice)}</Td>
                  <Td align="right">
                    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 1, fontVariantNumeric: 'tabular-nums' }}>
                      <span style={{ color: pnl >= 0 ? 'var(--green)' : 'var(--red)', fontWeight: 500 }}>
                        {pnl >= 0 ? '+' : ''}{window.formatUSD(pnl)}
                      </span>
                      <span style={{ color: pnl >= 0 ? 'var(--green)' : 'var(--red)', fontSize: 11.5, opacity: 0.85 }}>
                        {window.formatPct(pnlPct)}
                      </span>
                    </div>
                  </Td>
                  <Td align="right" style={{ paddingRight: 24 }}>
                    <RowActions onEdit={() => onEdit(a)} onDelete={() => onDelete(a.id)} />
                  </Td>
                </tr>
              );
            })}
            {filtered.length === 0 && (
              <tr><td colSpan={9} style={{ padding: '36px 24px', textAlign: 'center', color: 'var(--text-dim)' }}>
                No hay activos en esta categoría. Agrega tu primera transacción para comenzar.
              </td></tr>
            )}
          </tbody>
        </table>
      </div>
      )}
    </div>
  );
}

function MobileAssetCard({ asset, cedearMap, expanded, onToggle, onEdit, onDelete, balanceHidden }) {
  const value = asset.qty * asset.currentPrice;
  const cost = asset.qty * asset.buyPrice;
  const pnl = value - cost;
  const pnlPct = cost > 0 ? (pnl / cost) * 100 : 0;
  const pnlColor = pnl >= 0 ? 'var(--green)' : 'var(--red)';
  const fmtMoney = (n) => balanceHidden ? '••••••' : window.formatUSD(n);

  return (
    <div style={{
      background: 'var(--panel-2)',
      border: `1px solid ${expanded ? 'var(--border-strong)' : 'var(--border)'}`,
      borderRadius: 12,
      transition: 'border-color 0.15s',
      overflow: 'hidden',
    }}>
      {/* Header (siempre visible, click para expandir) */}
      <button
        type="button"
        onClick={onToggle}
        style={{
          width: '100%', display: 'flex', alignItems: 'center', gap: 12,
          padding: 14, textAlign: 'left', cursor: 'pointer',
          background: 'transparent', color: 'var(--text)', border: 'none',
        }}
      >
        <TickerBadge ticker={asset.ticker} type={asset.type} iconUrl={asset.iconUrl} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <span style={{ fontWeight: 700, fontSize: 14 }}>{asset.ticker}</span>
            <TypePill type={asset.type} />
          </div>
          <div style={{ fontSize: 11.5, color: 'var(--text-dim)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', marginTop: 2 }}>
            {asset.name}
          </div>
        </div>
        <div style={{ textAlign: 'right', flexShrink: 0 }}>
          <div style={{ fontWeight: 700, fontVariantNumeric: 'tabular-nums', fontSize: 14, lineHeight: 1.2 }}>
            {fmtMoney(value)}
          </div>
          <div style={{ fontSize: 11.5, fontWeight: 500, color: pnlColor, fontVariantNumeric: 'tabular-nums', marginTop: 2 }}>
            {pnl >= 0 ? '+' : ''}{fmtMoney(pnl)} · {window.formatPct(pnlPct)}
          </div>
        </div>
        <svg width="14" height="14" viewBox="0 0 16 16" fill="none"
          style={{ color: 'var(--text-faint)', transform: expanded ? 'rotate(180deg)' : 'none', transition: 'transform 0.2s', flexShrink: 0 }}>
          <path d="M3 6 L8 11 L13 6" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
        </svg>
      </button>

      {/* Contenido expandido */}
      {expanded && (
        <div style={{ padding: '0 14px 14px', borderTop: '1px solid var(--border)' }}>
          {/* Grid de detalles */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '14px 12px', padding: '14px 0' }}>
            <DetailRow label="Precio actual" value={window.formatPrice(asset.currentPrice)} />
            <DetailRow
              label="24h"
              value={window.formatPct(asset.change24)}
              valueColor={asset.change24 >= 0 ? 'var(--green)' : 'var(--red)'}
            />
            <DetailRow label="PPC" value={window.formatPrice(asset.buyPrice)} />
            <DetailRow label="Costo total" value={fmtMoney(cost)} />
          </div>

          {/* Cantidad con barra de progreso */}
          <div style={{ padding: '12px', background: 'var(--panel)', borderRadius: 9, border: '1px solid var(--border)' }}>
            <div style={{ fontSize: 10.5, color: 'var(--text-faint)', textTransform: 'uppercase', letterSpacing: 0.5, fontWeight: 600, marginBottom: 8 }}>
              Cantidad
            </div>
            <QuantityCell asset={asset} cedearMap={cedearMap} align="flex-start" />
          </div>

          {/* Acciones */}
          <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
            <button
              type="button"
              onClick={onEdit}
              style={{
                flex: 1, padding: '10px 0', borderRadius: 9, fontWeight: 600, fontSize: 13,
                background: 'var(--panel)', border: '1px solid var(--border)', color: 'var(--text)',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
              }}
            >
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none"><path d="M11.5 2.5l2 2L6 12H4v-2l7.5-7.5z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/></svg>
              Editar
            </button>
            <button
              type="button"
              onClick={onDelete}
              style={{
                flex: 1, padding: '10px 0', borderRadius: 9, fontWeight: 600, fontSize: 13,
                background: 'rgba(239,104,104,0.1)', border: '1px solid rgba(239,104,104,0.25)', color: 'var(--red)',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
              }}
            >
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none"><path d="M3 4h10M6 4V2.5h4V4M4.5 4L5 13.5h6L11.5 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/></svg>
              Eliminar
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

function DetailRow({ label, value, valueColor }) {
  return (
    <div>
      <div style={{ fontSize: 10.5, color: 'var(--text-faint)', textTransform: 'uppercase', letterSpacing: 0.5, fontWeight: 600, marginBottom: 3 }}>
        {label}
      </div>
      <div style={{ fontWeight: 600, fontSize: 13.5, fontVariantNumeric: 'tabular-nums', color: valueColor || 'var(--text)' }}>
        {value}
      </div>
    </div>
  );
}

function QuantityCell({ asset, cedearMap, align = 'flex-end' }) {
  // Detección por ticker (no por tipo) — así el subyacente se computa aunque el activo esté guardado como 'accion'.
  const cedearInfo = cedearMap?.[asset.ticker];
  const isCedear = !!cedearInfo;
  const ratio = isCedear ? cedearInfo.ratio : 1;
  const underlyingTicker = isCedear ? cedearInfo.underlying : asset.ticker;
  const underlyingQty = asset.qty / ratio;
  const fmt = (n, max = 6) => n.toLocaleString('en-US', { maximumFractionDigits: max });

  const wholeUnits = Math.floor(underlyingQty);
  const fractional = underlyingQty - wholeUnits;
  const filledPct = fractional * 100;
  const missing = fractional > 0 ? 1 - fractional : 0;
  // CEDEARs faltantes para llegar al próximo subyacente entero — Math.round evita errores de FP
  const missingCedears = isCedear && fractional > 0 ? Math.round(missing * ratio) : null;

  // El progress-bar "enteras / faltan" solo aporta cuando una unidad entera vale lo
  // suficiente como para ser un hito. Para memecoins (PEPE, SHIB) donde 1 entera vale
  // fracciones de centavo y tenés miles de millones, esconderlo. CEDEARs siempre
  // muestran porque el milestone es del underlying, no del propio CEDEAR.
  const unitWorthShowing = isCedear || (asset.currentPrice ?? 0) >= 1;

  // Para tokens micro-precio (PEPE, SHIB) los decimales de la qty no aportan: tener
  // 7,644,709,303.045608 PEPE vs. 7,644,709,303 PEPE no cambia nada porque el ".045"
  // vale fracciones de centavo. Mostramos solo enteros.
  const qtyDigits = unitWorthShowing ? 6 : 0;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: align, gap: 4, width: '100%' }}>
      <div style={{ fontWeight: 500 }}>{fmt(asset.qty, qtyDigits)} {asset.ticker}</div>

      {isCedear && (
        <div style={{ fontSize: 11, color: 'var(--text-faint)', lineHeight: 1.2 }}>
          = {fmt(underlyingQty, 4)} {underlyingTicker}
        </div>
      )}

      {unitWorthShowing && fractional > 0 && (
        <>
          <div style={{
            width: 90, height: 4, borderRadius: 2,
            background: 'var(--panel-2)', overflow: 'hidden', marginTop: 2,
          }}>
            <div style={{
              width: `${filledPct}%`, height: '100%',
              background: 'linear-gradient(90deg, var(--accent), var(--accent-soft))',
              transition: 'width 0.3s',
            }} />
          </div>
          <div style={{ fontSize: 10.5, color: 'var(--text-faint)', lineHeight: 1.2 }}>
            {wholeUnits > 0 && <>{wholeUnits} entera{wholeUnits === 1 ? '' : 's'} · </>}
            faltan {fmt(missing, 4)} {underlyingTicker}
            {isCedear && <> ({missingCedears} {asset.ticker})</>}
          </div>
        </>
      )}

      {unitWorthShowing && fractional === 0 && wholeUnits >= 1 && (
        <div style={{ fontSize: 10.5, color: 'var(--green)', lineHeight: 1.2 }}>
          ✓ {wholeUnits} entera{wholeUnits === 1 ? '' : 's'}
        </div>
      )}
    </div>
  );
}

function Th({ children, align = 'left', style = {} }) {
  return <th style={{ textAlign: align, fontWeight: 500, padding: '10px 12px', ...style }}>{children}</th>;
}
function Td({ children, align = 'left', style = {} }) {
  return <td style={{ textAlign: align, padding: '14px 12px', ...style }}>{children}</td>;
}

function TabBar({ filter, onFilterChange }) {
  const tabs = [
    { id: 'todo',   label: 'Todo' },
    { id: 'cripto', label: 'Criptomonedas' },
    { id: 'accion', label: 'Acciones' },
  ];
  return (
    <div style={{ display: 'flex', gap: 6, borderBottom: '1px solid var(--border)', paddingBottom: 0 }}>
      {tabs.map(t => {
        const isActive = t.id === filter;
        return (
          <button key={t.id} onClick={() => onFilterChange(t.id)}
            style={{
              padding: '8px 14px', fontSize: 13, fontWeight: 500,
              color: isActive ? 'var(--accent)' : 'var(--text-dim)',
              borderBottom: `2px solid ${isActive ? 'var(--accent)' : 'transparent'}`,
              marginBottom: -1,
            }}>{t.label}</button>
        );
      })}
    </div>
  );
}

function BitcoinIcon({ size = 30 }) {
  // Logo oficial de Bitcoin (₿ blanco sobre círculo naranja brand)
  return (
    <svg viewBox="0 0 64 64" width={size} height={size} style={{ flexShrink: 0, display: 'block' }}>
      <circle cx="32" cy="32" r="32" fill="#f7931a"/>
      <path fill="#fff" d="M46.1 27.6c.6-4-2.4-6.1-6.6-7.5l1.4-5.5-3.4-.8-1.3 5.3c-.9-.2-1.8-.4-2.7-.6l1.3-5.4-3.3-.8-1.4 5.5c-.7-.2-1.5-.3-2.2-.5L23 16.5l-.9 3.6s2.5.6 2.4.6c1.4.3 1.6 1.2 1.6 2l-1.6 6.4c.1 0 .2.1.3.1l-.3-.1-2.2 8.9c-.2.4-.6 1-1.6.8.1.1-2.4-.6-2.4-.6L17 41.2l4.5 1.1c.8.2 1.7.4 2.5.6l-1.4 5.6 3.3.8 1.4-5.5c.9.3 1.8.5 2.7.7l-1.4 5.5 3.4.8 1.4-5.6c5.7 1.1 10 .6 11.8-4.6 1.4-4.2-.1-6.6-3.1-8.2 2.2-.5 3.9-2 4-5zm-7.7 11c-1.1 4.2-8.2 1.9-10.5 1.4l1.9-7.6c2.3.6 9.7 1.7 8.6 6.2zm1-11c-1 3.8-6.9 1.9-8.8 1.4l1.7-6.9c1.9.5 8.1 1.3 7.1 5.5z"/>
    </svg>
  );
}

function TickerBadge({ ticker, type, iconUrl }) {
  // Si la imagen falla (404, CDN caído), bajamos al círculo con letras
  const [imgFailed, setImgFailed] = React.useState(false);
  // Reset cuando cambia la URL para que un nuevo intento no quede atrapado en el fallback
  React.useEffect(() => { setImgFailed(false); }, [iconUrl]);

  // Logo real del CDN (CryptoCompare para cripto, posible para otros tipos en el futuro)
  if (iconUrl && !imgFailed) {
    return (
      <img
        src={iconUrl}
        alt={ticker}
        onError={() => setImgFailed(true)}
        style={{
          width: 30, height: 30, borderRadius: '50%',
          objectFit: 'cover', flexShrink: 0,
          background: 'var(--panel-2)',
        }}
      />
    );
  }

  // Tickers con logo propio (renderizan SVG completo en vez del círculo con letras)
  if (ticker === 'BTC') return <BitcoinIcon size={30} />;

  // Fallback: círculo de color con las primeras 2 letras
  const colors = {
    ETH: '#627eea', BNB: '#f3ba2f',
    BABA: '#ff6a00', NVDA: '#76b900', QQQ: '#0072ce', SPY: '#1f4e79',
    MELI: '#ffe600',
  };
  const bg = colors[ticker] || '#6b6b74';
  return (
    <div style={{
      width: 30, height: 30, borderRadius: '50%', background: bg,
      display: 'grid', placeItems: 'center', color: '#fff', fontWeight: 700, fontSize: 11,
      flexShrink: 0,
    }}>
      {ticker.slice(0, 2)}
    </div>
  );
}

function TypePill({ type }) {
  const styles = {
    cripto: { bg: '#f7931a',       fg: '#ffffff', label: 'Cripto' },
    accion: { bg: 'var(--purple)', fg: '#ffffff', label: 'Acción' },
    etf:    { bg: 'var(--green)',  fg: '#ffffff', label: 'ETF' },
  }[type] || {};
  return (
    <span style={{
      display: 'inline-block', padding: '3px 10px', borderRadius: 6,
      background: styles.bg, color: styles.fg, fontSize: 11.5, fontWeight: 500,
    }}>{styles.label}</span>
  );
}

function RowActions({ onEdit, onDelete }) {
  return (
    <div style={{ display: 'inline-flex', gap: 4 }}>
      <IconBtn title="Editar" onClick={onEdit}>
        <svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M11.5 2.5l2 2L6 12H4v-2l7.5-7.5z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round"/></svg>
      </IconBtn>
      <IconBtn title="Eliminar" onClick={onDelete}>
        <svg width="14" height="14" viewBox="0 0 16 16" fill="none"><path d="M3 4h10M6 4V2.5h4V4M4.5 4L5 13.5h6L11.5 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/></svg>
      </IconBtn>
    </div>
  );
}

function IconBtn({ children, title, onClick }) {
  return (
    <button title={title} onClick={onClick}
      style={{
        width: 28, height: 28, borderRadius: 8, color: 'var(--text-dim)',
        display: 'grid', placeItems: 'center',
      }}
      onMouseEnter={e => { e.currentTarget.style.background = 'var(--panel-2)'; e.currentTarget.style.color = 'var(--text)'; }}
      onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; e.currentTarget.style.color = 'var(--text-dim)'; }}
    >{children}</button>
  );
}

Object.assign(window, { AssetsTable });
