/* global React, Icons, Toggle, Checkbox, ProductImage, Sparkline, Stars */
const { useState, useEffect, useMemo } = React;

/* ============================================================
   Master column definitions. The same set is used on Search and
   Leads — each page can default-show a subset.
   ============================================================ */
const MASTER_COLUMNS = [
  { key: 'product',         label: 'Product',          sticky: true, width: 260 },
  { key: 'asin',            label: 'ASIN',             mono: true },
  { key: 'brand',           label: 'Brand' },
  { key: 'category',        label: 'Category' },
  { key: 'source',          label: 'Source' },
  { key: 'addedDate',       label: 'Added' },
  { key: 'price',           label: 'Price',            num: true },
  { key: 'revenue30d',      label: '30d Revenue',      num: true },
  { key: 'monthlySales',    label: 'Monthly Sales',    num: true },
  { key: 'bsr',             label: '90d BSR',          num: true },
  { key: 'reviews',         label: 'Review Count',     num: true },
  { key: 'rating',          label: 'Rating' },
  { key: 'variations',      label: '# Variations',     num: true },
  { key: 'videos',          label: 'Videos',           num: true },
  { key: 'hasMainVideo',    label: 'Brand Video',  center: true },
  { key: 'cc',              label: 'CC %',             num: true },
  { key: 'onSite',          label: 'On‑Site %',        num: true },
  { key: 'onSiteCommission',label: 'On‑Site Commission', num: true },
  { key: 'ccCommission',    label: 'CC Commission',    num: true },
  { key: 'campaignStart',   label: 'Campaign Start' },
  { key: 'campaignEnd',     label: 'Campaign End' },
  { key: 'campaignDate',    label: 'Campaign Date' },
  { key: 'budget',          label: 'Budget',           num: true },
  { key: 'remainingBudget', label: 'Remaining Budget', num: true },
  { key: 'totalSlots',     label: 'Total Slots',      num: true },
  { key: 'availableSlots', label: 'Available Slots',  num: true },
  { key: 'slotsTrend',     label: 'Slots Left' },
  { key: 'listingAge',      label: 'Listing Age',      num: true },
  { key: 'trend',           label: 'Budget Left' },
];

const COLUMN_BY_KEY = Object.fromEntries(MASTER_COLUMNS.map(c => [c.key, c]));

function ProductCell({ p, i }) {
  const [imgError, setImgError] = useState(false);
  const [hovered, setHovered] = useState(false);
  const imgSrc = !imgError && p.image
    ? `https://m.media-amazon.com/images/I/${p.image}`
    : null;

  return (
    <div className="cell-product">
      {imgSrc ? (
        <div style={{ position: 'relative', flexShrink: 0 }}
          onMouseEnter={() => setHovered(true)}
          onMouseLeave={() => setHovered(false)}
        >
          <img
            src={imgSrc}
            alt=""
            style={{ width: 40, height: 40, objectFit: 'contain', borderRadius: 6,
                     background: 'var(--bg-2)', display: 'block', cursor: 'zoom-in' }}
            onError={() => setImgError(true)}
          />
          {hovered && (
            <div style={{
              position: 'absolute', bottom: 'calc(100% + 8px)', left: '50%',
              transform: 'translateX(-50%)',
              zIndex: 50, pointerEvents: 'none',
              background: 'var(--bg-elev)',
              border: '1px solid var(--line-strong)',
              borderRadius: 10, padding: 8,
              boxShadow: '0 20px 50px -8px rgba(0,0,0,0.75)',
            }}>
              <img src={imgSrc} alt="" style={{ width: 200, height: 200, objectFit: 'contain', display: 'block' }}/>
            </div>
          )}
        </div>
      ) : (
        <ProductImage seed={i + 7} label={p.name}/>
      )}
      <div>
        <a
          href={`https://www.amazon.com/dp/${p.asin}`}
          target="_blank"
          rel="noopener noreferrer"
          className="product-name"
          title={p.name}
          style={{
            color: 'inherit', textDecoration: 'none',
            display: 'block', overflow: 'hidden',
            textOverflow: 'ellipsis', whiteSpace: 'nowrap',
            maxWidth: 200,
          }}
          onClick={(e) => e.stopPropagation()}
        >
          {p.name}
        </a>
        <div className="product-asin">{p.brand} · {p.source}</div>
      </div>
    </div>
  );
}

function renderProductCell(p, i) {
  return <ProductCell p={p} i={i}/>;
}

function CopyableAsin({ asin }) {
  const [copied, setCopied] = useState(false);
  const copy = () => {
    navigator.clipboard.writeText(asin);
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  };
  return (
    <span
      className="num"
      onClick={copy}
      title="Click to copy ASIN"
      style={{ color: copied ? 'var(--success)' : 'var(--text-2)', cursor: 'pointer', transition: 'color 0.15s' }}
    >
      {copied ? '✓ Copied' : asin}
    </span>
  );
}

function BudgetBar({ p }) {
  const [hovered, setHovered] = useState(false);
  if (!p.budget || p.budget <= 0) return <span style={{ color: 'var(--text-3)' }}>—</span>;
  const pct     = Math.round((p.remainingBudget / p.budget) * 100);
  const clamped = Math.max(0, Math.min(100, pct));
  return (
    <div style={{ position: 'relative', width: 72, cursor: 'default' }}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
    >
      {/* Track */}
      <div style={{ height: 2, borderRadius: 2, background: 'rgba(255,255,255,0.15)' }}>
        {/* Fill */}
        <div style={{
          height: '100%', width: `${clamped}%`,
          borderRadius: 2,
          background: 'var(--accent)',
          boxShadow: '0 0 6px var(--accent), 0 0 12px var(--accent)',
          transition: 'width 0.3s ease',
        }}/>
      </div>
      {hovered && (
        <div style={{
          position: 'absolute', bottom: '100%', left: '50%', transform: 'translateX(-50%)',
          marginBottom: 8, padding: '4px 9px',
          background: 'var(--bg-elev)', border: '1px solid var(--line-strong)',
          borderRadius: 6, fontSize: 11, fontWeight: 600,
          color: 'var(--accent)', whiteSpace: 'nowrap',
          boxShadow: '0 4px 12px rgba(0,0,0,0.45)',
          zIndex: 10, pointerEvents: 'none',
        }}>
          {pct}% budget remaining
        </div>
      )}
    </div>
  );
}

function SlotsBar({ p }) {
  const [hovered, setHovered] = useState(false);
  if (!p.totalSlots || p.totalSlots <= 0) return <span style={{ color: 'var(--text-3)' }}>—</span>;
  const pct     = Math.round(((p.availableSlots ?? 0) / p.totalSlots) * 100);
  const clamped = Math.max(0, Math.min(100, pct));
  return (
    <div style={{ position: 'relative', width: 72, cursor: 'default' }}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
    >
      <div style={{ height: 2, borderRadius: 2, background: 'rgba(255,255,255,0.15)' }}>
        <div style={{
          height: '100%', width: `${clamped}%`,
          borderRadius: 2,
          background: 'var(--success)',
          boxShadow: '0 0 6px var(--success), 0 0 12px var(--success)',
          transition: 'width 0.3s ease',
        }}/>
      </div>
      {hovered && (
        <div style={{
          position: 'absolute', bottom: '100%', left: '50%', transform: 'translateX(-50%)',
          marginBottom: 8, padding: '4px 9px',
          background: 'var(--bg-elev)', border: '1px solid var(--line-strong)',
          borderRadius: 6, fontSize: 11, fontWeight: 600,
          color: 'var(--success)', whiteSpace: 'nowrap',
          boxShadow: '0 4px 12px rgba(0,0,0,0.45)',
          zIndex: 10, pointerEvents: 'none',
        }}>
          {p.availableSlots ?? 0} of {p.totalSlots} slots available
        </div>
      )}
    </div>
  );
}

const fmtIsoDate = (s) => s
  ? new Date(s + 'T00:00:00').toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' })
  : '—';

function renderCellValue(key, p, i, fmtUSD, fmtInt, fmtBSR) {
  switch (key) {
    case 'product': return renderProductCell(p, i);
    case 'asin': return <CopyableAsin asin={p.asin}/>;

    case 'brand': {
      if (!p.brand) return null;
      const creatorId = localStorage.getItem('aip_creator_id');
      const params = new URLSearchParams({
        status: 'opportunity', type: 'affiliate-plus',
        sortBy: 'recommended_for_you', keyword: p.brand,
        filterExpanderStatus: 'false', categories: '',
        nonFullyClaimedOnly: 'false', campaignStatuses: 'active,pending',
        earlyAccessOnly: 'false', topBrandsOnly: 'false',
        creatorFavoritesOnly: 'false', brands: '', contentType: '', budgetAvailability: '',
      });
      if (creatorId) params.set('creatorId', creatorId);
      const url = `https://affiliate-program.amazon.com/p/connect/requests?${params}`;
      return (
        <a href={url} target="_blank" rel="noreferrer"
          style={{ fontWeight: 500, color: 'inherit', textDecoration: 'none' }}
          onMouseEnter={e => e.target.style.textDecoration = 'underline'}
          onMouseLeave={e => e.target.style.textDecoration = 'none'}
        >{p.brand}</a>
      );
    }
    case 'category': return <span className="badge badge-neutral">{p.category}</span>;
    case 'source': return <span style={{ color: 'var(--text-2)' }}>{p.source}</span>;
    case 'addedDate': return <span style={{ color: 'var(--text-2)', fontSize: 12 }}>{p.addedDate}</span>;
    case 'price': return <span className="num">{fmtUSD(p.price)}</span>;
    case 'revenue30d': return <span className="num">{p.revenue30d != null ? fmtUSD(p.revenue30d) : '—'}</span>;
    case 'monthlySales': return <span className="num">{fmtInt(p.monthlySales)}</span>;
    case 'bsr': return <span className="num" style={{ color: 'var(--text-2)' }}>{fmtBSR(p.bsr)}</span>;
    case 'reviews': return <span className="num">{fmtInt(p.reviews)}</span>;
    case 'rating': return (
      <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
        <Stars value={p.rating} size={11}/>
        <span className="num" style={{ color: 'var(--text-2)' }}>{p.rating}</span>
      </span>
    );
    case 'variations': return <span className="num">{p.variations}</span>;
    case 'videos': return <span className="num" style={{ color: p.videos > 0 ? 'var(--text-0)' : 'var(--text-3)' }}>{p.videos != null ? p.videos : '—'}</span>;
    case 'hasMainVideo': return p.hasMainVideo
      ? (
        <div style={{ display: 'flex', justifyContent: 'center' }}>
          <svg width="15" height="15" viewBox="0 0 24 24" fill="none"
            stroke="var(--accent)" strokeWidth="3.5" strokeLinecap="round" strokeLinejoin="round"
            style={{ filter: 'drop-shadow(0 0 5px var(--accent)) drop-shadow(0 0 10px var(--accent))' }}>
            <polyline points="20 6 9 17 4 12"/>
          </svg>
        </div>
      )
      : null;
    case 'cc': {
      const color = p.cc >= 20 ? 'var(--success)' : 'var(--text-2)';
      const creatorId = localStorage.getItem('aip_creator_id');
      const params = new URLSearchParams({
        status: 'opportunity', type: 'affiliate-plus',
        sortBy: 'recommended_for_you', keyword: p.asin,
        filterExpanderStatus: 'false', categories: '',
        nonFullyClaimedOnly: 'false', campaignStatuses: 'active,pending',
        earlyAccessOnly: 'false', topBrandsOnly: 'false',
        creatorFavoritesOnly: 'false', brands: '', contentType: '', budgetAvailability: '',
      });
      if (creatorId) params.set('creatorId', creatorId);
      const url = `https://affiliate-program.amazon.com/p/connect/requests?${params}`;
      return (
        <a href={url} target="_blank" rel="noreferrer" className="num"
          style={{ color, textDecoration: 'none' }}
          onMouseEnter={e => e.target.style.textDecoration = 'underline'}
          onMouseLeave={e => e.target.style.textDecoration = 'none'}
        >{p.cc}%</a>
      );
    }
    case 'onSite': return <span className="num">{p.onSite}%</span>;
    case 'onSiteCommission': return <span className="num num-pos">{fmtUSD(p.onSiteCommission)}</span>;
    case 'ccCommission': return <span className="num" style={{ color: 'var(--accent)' }}>{fmtUSD(p.ccCommission)}</span>;
    case 'campaignStart': return <span style={{ color: 'var(--text-2)', fontSize: 12 }}>{fmtIsoDate(p.campaignStart)}</span>;
    case 'campaignEnd': return <span style={{ color: 'var(--text-2)', fontSize: 12 }}>{fmtIsoDate(p.campaignEnd)}</span>;
    case 'campaignDate': {
      const dateRange = `${fmtIsoDate(p.campaignStart)} → ${fmtIsoDate(p.campaignEnd)}`;
      if (p.campaignId) {
        const fullId    = p.campaignId.startsWith('amzn1.campaign.') ? p.campaignId : `amzn1.campaign.${p.campaignId}`;
        const creatorId = localStorage.getItem('aip_creator_id');
        const params    = [
          creatorId ? `creatorId=${creatorId}` : null,
          `adId=${fullId}`,
          `campaignId=${fullId}`,
          'recc=0', 'early-acc=0', 'type=spcc', 'status=opportunity',
        ].filter(Boolean).join('&');
        const url = `https://affiliate-program.amazon.com/p/connect/request?${params}`;
        return <a href={url} target="_blank" rel="noreferrer" style={{ color: 'var(--accent)', fontSize: 12, textDecoration: 'none' }} onMouseEnter={e => e.target.style.textDecoration='underline'} onMouseLeave={e => e.target.style.textDecoration='none'}>{dateRange}</a>;
      }
      return <span style={{ color: 'var(--text-2)', fontSize: 12 }}>{dateRange}</span>;
    }
    case 'budget': return <span className="num">{fmtUSD(p.budget)}</span>;
    case 'remainingBudget': return <span className="num" style={{ color: p.remainingBudget < p.budget * 0.25 ? 'var(--warn)' : 'var(--text-1)' }}>{fmtUSD(p.remainingBudget)}</span>;
    case 'totalSlots': return <span className="num">{p.totalSlots ?? '—'}</span>;
    case 'availableSlots': return <span className="num" style={{ color: p.availableSlots > 0 ? 'var(--success)' : 'var(--text-3)' }}>{p.availableSlots ?? '—'}</span>;
    case 'slotsTrend': return <SlotsBar p={p}/>;
    case 'listingAge': return <span className="num" style={{ color: 'var(--text-2)' }}>{p.listingAge > 0 ? `${p.listingAge.toLocaleString()}d` : '—'}</span>;
    case 'trend': return <BudgetBar p={p}/>;
    default: return null;
  }
}

// Plain-text version of renderCellValue — used for clipboard copy
function getPlainValue(key, p, fmtUSD, fmtInt, fmtBSR) {
  switch (key) {
    case 'product':          return p.name || '';
    case 'asin':             return p.asin || '';
    case 'brand':            return p.brand || '';
    case 'category':         return p.category || '';
    case 'source':           return p.source || '';
    case 'addedDate':        return p.addedDate || '';
    case 'price':            return p.price != null ? fmtUSD(p.price) : '';
    case 'revenue30d':       return p.revenue30d != null ? fmtUSD(p.revenue30d) : '';
    case 'monthlySales':     return fmtInt(p.monthlySales);
    case 'bsr':              return fmtBSR(p.bsr);
    case 'reviews':          return fmtInt(p.reviews);
    case 'rating':           return p.rating != null ? String(p.rating) : '';
    case 'variations':       return p.variations != null ? String(p.variations) : '';
    case 'videos':           return p.videos != null ? String(p.videos) : '';
    case 'hasMainVideo':     return p.hasMainVideo ? 'Yes' : 'No';
    case 'cc':               return p.cc != null ? `${p.cc}%` : '';
    case 'onSite':           return p.onSite != null ? `${p.onSite}%` : '';
    case 'onSiteCommission': return p.onSiteCommission != null ? fmtUSD(p.onSiteCommission) : '';
    case 'ccCommission':     return p.ccCommission != null ? fmtUSD(p.ccCommission) : '';
    case 'campaignStart':    return fmtIsoDate(p.campaignStart);
    case 'campaignEnd':      return fmtIsoDate(p.campaignEnd);
    case 'campaignDate':     return `${fmtIsoDate(p.campaignStart)} - ${fmtIsoDate(p.campaignEnd)}`;
    case 'budget':           return p.budget != null ? fmtUSD(p.budget) : '';
    case 'remainingBudget':  return p.remainingBudget != null ? fmtUSD(p.remainingBudget) : '';
    case 'totalSlots':       return p.totalSlots != null ? String(p.totalSlots) : '';
    case 'availableSlots':   return p.availableSlots != null ? String(p.availableSlots) : '';
    case 'slotsTrend':       return p.totalSlots > 0
      ? `${Math.round(((p.availableSlots ?? 0) / p.totalSlots) * 100)}%` : '';
    case 'listingAge':       return p.listingAge > 0 ? `${p.listingAge}d` : '';
    case 'trend':            return p.budget > 0
      ? `${Math.round((p.remainingBudget / p.budget) * 100)}%` : '';
    default: return '';
  }
}

/* ============================================================
   Drag-to-reorder list. Uses HTML5 DnD on row containers.
   onReorder(fromIdx, toIdx)
   ============================================================ */
function ReorderableList({ items, onReorder, renderItem, keyField = 'key' }) {
  const [dragIdx, setDragIdx] = useState(null);
  const [overIdx, setOverIdx] = useState(null);

  return (
    <div>
      {items.map((it, i) => (
        <div
          key={it[keyField]}
          draggable
          onDragStart={() => setDragIdx(i)}
          onDragOver={(e) => { e.preventDefault(); setOverIdx(i); }}
          onDragEnd={() => { setDragIdx(null); setOverIdx(null); }}
          onDrop={(e) => {
            e.preventDefault();
            if (dragIdx !== null && dragIdx !== i) onReorder(dragIdx, i);
            setDragIdx(null); setOverIdx(null);
          }}
          style={{
            opacity: dragIdx === i ? 0.4 : 1,
            borderTop: overIdx === i && dragIdx !== null && dragIdx > i ? '2px solid var(--accent)' : '2px solid transparent',
            borderBottom: overIdx === i && dragIdx !== null && dragIdx < i ? '2px solid var(--accent)' : '2px solid transparent',
            transition: 'opacity 0.12s',
          }}
        >
          {renderItem(it, i)}
        </div>
      ))}
    </div>
  );
}

/* ============================================================
   Manage Columns Drawer — shared between Search & Leads.
   Props:
     order: [colKey...]                 -> current visible order
     setOrder(next)
     hidden: Set<colKey>                -> keys hidden
     setHidden(next)
     customCols: [{key,label}]          -> only Leads passes these
     setCustomCols                       -> if omitted, custom column UI is not shown
     onClose
   ============================================================ */
function ManageColumnsDrawer({
  order, setOrder, hidden, setHidden,
  customCols, setCustomCols,
  onClose, defaultOrder,
}) {
  const allowCustom = !!setCustomCols;

  // resolve labels via master + custom
  const labelFor = (key) => {
    const std = COLUMN_BY_KEY[key];
    if (std) return std.label;
    return customCols?.find(c => c.key === key)?.label || 'Untitled';
  };
  const isCustom = (key) => key.startsWith('cust_');
  const isSticky = (key) => COLUMN_BY_KEY[key]?.sticky;

  const reorder = (from, to) => {
    setOrder(prev => {
      const next = [...prev];
      const [m] = next.splice(from, 1);
      next.splice(to, 0, m);
      return next;
    });
  };

  const toggleHidden = (key) => {
    setHidden(prev => {
      const n = new Set(prev);
      if (n.has(key)) n.delete(key); else n.add(key);
      return n;
    });
  };

  const addCustom = () => {
    const id = 'cust_' + Date.now();
    setCustomCols(prev => [...prev, { key: id, label: 'New column' }]);
    setOrder(prev => [...prev, id]);
  };
  const renameCustom = (key, label) => setCustomCols(prev => prev.map(c => c.key === key ? { ...c, label } : c));
  const deleteCustom = (key) => {
    setCustomCols(prev => prev.filter(c => c.key !== key));
    setOrder(prev => prev.filter(k => k !== key));
    setHidden(prev => { const n = new Set(prev); n.delete(key); return n; });
  };

  const reset = () => {
    setOrder(defaultOrder);
    setHidden(new Set());
  };

  // available standard columns NOT yet in order
  const inOrder = new Set(order);
  const availableStd = MASTER_COLUMNS.filter(c => !inOrder.has(c.key));
  const addStandard = (key) => {
    setOrder(prev => [...prev, key]);
    setHidden(prev => { const n = new Set(prev); n.delete(key); return n; });
  };

  const items = order.map(k => ({ key: k, label: labelFor(k), custom: isCustom(k), sticky: isSticky(k) }));

  return (
    <>
      <div className="drawer-backdrop" onClick={onClose}/>
      <div className="drawer">
        <div style={{ padding: 20, borderBottom: '1px solid var(--line)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <div>
            <div style={{ fontSize: 16, fontWeight: 700, letterSpacing: '-0.3px' }}>Manage columns</div>
            <div style={{ fontSize: 12, color: 'var(--text-2)', marginTop: 2 }}>Drag to reorder · toggle visibility{allowCustom ? ' · add note columns' : ''}</div>
          </div>
          <button className="icon-btn" onClick={onClose}><Icons.close size={14}/></button>
        </div>

        <div style={{ flex: 1, overflowY: 'auto', padding: 16 }}>
          <div className="card-eyebrow" style={{ padding: '6px 4px' }}>Active columns ({items.length})</div>

          <ReorderableList
            items={items}
            onReorder={reorder}
            renderItem={(it) => (
              <div style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '9px 10px', borderRadius: 8,
                background: 'var(--bg-2)', marginBottom: 4,
                border: '1px solid var(--line)',
                cursor: it.sticky ? 'default' : 'grab',
              }}>
                <Icons.drag size={14} style={{ color: 'var(--text-3)' }}/>
                {it.custom ? (
                  <input
                    className="field-input"
                    style={{ padding: '4px 8px', fontSize: 13, flex: 1, background: 'transparent', border: '1px dashed var(--line)' }}
                    value={it.label}
                    onChange={(e) => renameCustom(it.key, e.target.value)}
                    onKeyDown={(e) => { if (e.key === 'Enter') e.target.blur(); }}
                  />
                ) : (
                  <span style={{ flex: 1, fontSize: 13 }}>{it.label}</span>
                )}
                {it.custom && <span className="badge badge-accent" style={{ fontSize: 9 }}>note</span>}
                {it.sticky && <span className="badge badge-neutral" style={{ fontSize: 9 }}>required</span>}
                <Toggle on={!hidden.has(it.key)} onChange={() => !it.sticky && toggleHidden(it.key)} />
                {it.custom && (
                  <button className="icon-btn" style={{ width: 26, height: 26 }} onClick={() => deleteCustom(it.key)}>
                    <Icons.trash size={12}/>
                  </button>
                )}
              </div>
            )}
          />

          {availableStd.length > 0 && (
            <>
              <div className="card-eyebrow" style={{ padding: '14px 4px 6px' }}>Add column</div>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                {availableStd.map(c => (
                  <button
                    key={c.key}
                    className="btn btn-sm"
                    onClick={() => addStandard(c.key)}
                    style={{ fontSize: 11, padding: '5px 9px' }}
                  >
                    <Icons.plus size={11}/> {c.label}
                  </button>
                ))}
              </div>
            </>
          )}

          {allowCustom && (
            <>
              <div className="card-eyebrow" style={{ padding: '18px 4px 6px' }}>Custom note columns</div>
              <button className="btn btn-primary" style={{ width: '100%', justifyContent: 'center' }} onClick={addCustom}>
                <Icons.plus size={13}/> Add custom column
              </button>
              <div style={{ marginTop: 10, padding: 12, background: 'var(--bg-2)', borderRadius: 9, border: '1px solid var(--line)', fontSize: 12, color: 'var(--text-2)', lineHeight: 1.5 }}>
                Custom columns are free‑form notes — perfect for tracking video status, supplier contacts, or test dates.
              </div>
            </>
          )}
        </div>

        <div style={{ padding: 16, borderTop: '1px solid var(--line)', display: 'flex', gap: 10 }}>
          <button className="btn" style={{ flex: 1, justifyContent: 'center' }} onClick={reset}>Reset</button>
          <button className="btn btn-primary" style={{ flex: 1, justifyContent: 'center' }} onClick={onClose}>Done</button>
        </div>
      </div>
    </>
  );
}

window.MASTER_COLUMNS = MASTER_COLUMNS;
window.COLUMN_BY_KEY = COLUMN_BY_KEY;
window.renderCellValue = renderCellValue;
window.ManageColumnsDrawer = ManageColumnsDrawer;
window.ReorderableList = ReorderableList;
