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

// ── Fill a template with product data ────────────────────────────────────────
function fillTemplate(body, p, fmtUSD, fmtInt) {
  return (body || '')
    .replace(/{TITLE}/g,         p.name          || '')
    .replace(/{ASIN}/g,          p.asin          || '')
    .replace(/{BRAND}/g,         p.brand         || '')
    .replace(/{CC_PERCENT}/g,    p.cc            ? `${p.cc}%` : '')
    .replace(/{CC_COMMISSION}/g, p.ccCommission  ? fmtUSD(p.ccCommission) : '')
    .replace(/{PRICE}/g,         p.price         ? fmtUSD(p.price) : '')
    .replace(/{MONTHLY_SALES}/g, p.monthlySales  ? fmtInt(p.monthlySales) : '');
}
window.fillTemplate = fillTemplate;

// ── Column definitions ────────────────────────────────────────────────────────
const REQ_COLUMNS = [
  { key: 'product',        label: 'Product' },
  { key: 'asin',           label: 'ASIN' },
  { key: 'brand',          label: 'Brand' },
  { key: 'monthlySales',   label: 'Mo. Sales' },
  { key: 'note',           label: 'Note' },
  { key: 'price',          label: 'Price' },
  { key: 'cc',             label: 'CC%' },
  { key: 'ccCommission',   label: 'Commission' },
  { key: 'campaignDate',   label: 'Campaign Date' },
  { key: 'requestedAt',    label: 'Requested' },
  { key: 'lastFollowUpAt', label: 'Last Follow-Up' },
  { key: 'message',        label: 'Message' },
];
const REQ_COL_MAP = Object.fromEntries(REQ_COLUMNS.map(c => [c.key, c]));
const DEFAULT_COL_ORDER = REQ_COLUMNS.map(c => c.key);

// ── Small product cell ────────────────────────────────────────────────────────
function ReqProductCell({ r }) {
  const [imgError, setImgError] = useState(false);
  const [hovered, setHovered]   = useState(false);
  const imgSrc = !imgError && r.image ? `https://m.media-amazon.com/images/I/${r.image}` : null;
  return (
    <div className="cell-product">
      {imgSrc ? (
        <div style={{ position: 'relative', flexShrink: 0 }}
          onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}>
          <img src={imgSrc} alt="" onError={() => setImgError(true)}
            style={{ width: 36, height: 36, objectFit: 'contain', borderRadius: 6, background: 'var(--bg-2)', display: 'block', cursor: 'zoom-in' }}/>
          {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: 180, height: 180, objectFit: 'contain', display: 'block' }}/>
            </div>
          )}
        </div>
      ) : (
        <ProductImage seed={r.asin ? r.asin.charCodeAt(0) : 0} label={r.name}/>
      )}
      <div style={{ minWidth: 0 }}>
        <a href={`https://www.amazon.com/dp/${r.asin}`} target="_blank" rel="noopener noreferrer"
          className="product-name"
          style={{ color: 'inherit', textDecoration: 'none', display: '-webkit-box', WebkitLineClamp: 3, WebkitBoxOrient: 'vertical', overflow: 'hidden', whiteSpace: 'normal', maxWidth: 260 }}>
          {r.name}
        </a>
        <div className="product-asin">{r.asin}</div>
      </div>
    </div>
  );
}

// ── Message preview cell ──────────────────────────────────────────────────────
function MessageCell({ message }) {
  const [expanded, setExpanded] = useState(false);
  if (!message) return <span style={{ color: 'var(--text-3)', fontSize: 12 }}>—</span>;
  return (
    <div style={{ maxWidth: 280 }}>
      <div style={{ fontSize: 12, color: 'var(--text-2)', whiteSpace: 'pre-wrap', lineHeight: 1.5,
        ...(expanded ? {} : { display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' }) }}>
        {message}
      </div>
      <button onClick={() => setExpanded(e => !e)}
        style={{ fontSize: 11, color: 'var(--accent)', background: 'none', border: 'none', cursor: 'pointer', padding: '2px 0', marginTop: 2 }}>
        {expanded ? 'Show less' : 'Show more'}
      </button>
    </div>
  );
}

function reqFmtDate(iso) {
  if (!iso) return '—';
  try {
    const d = new Date(iso);
    if (isNaN(d.getTime())) return '—';
    return new Intl.DateTimeFormat('en-US', {
      month: '2-digit', day: '2-digit', year: 'numeric',
    }).format(d).replace(/\//g, '-');
  } catch (_) { return '—'; }
}

// For campaign date strings (YYYY-MM-DD) — avoids timezone shift
function reqFmtDateStr(str) {
  if (!str) return '';
  const m = str.match(/^(\d{4})-(\d{2})-(\d{2})/);
  if (m) return `${m[2]}-${m[3]}-${m[1]}`;
  return str;
}

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

// ── Brand link cell ──────────────────────────────────────────────────────────
function ReqBrandCell({ brand }) {
  if (!brand) return <span style={{ color: 'var(--text-3)' }}>—</span>;
  const creatorId = localStorage.getItem('aip_creator_id');
  const params = new URLSearchParams({
    status: 'opportunity', type: 'affiliate-plus', sortBy: 'recommended_for_you',
    keyword: brand, filterExpanderStatus: 'false', categories: '',
    nonFullyClaimedOnly: 'false', campaignStatuses: 'active,pending',
    earlyAccessOnly: 'false', topBrandsOnly: 'false',
    creatorFavoritesOnly: 'false', brands: '', contentType: '', budgetAvailability: '',
  });
  if (creatorId) params.set('creatorId', creatorId);
  return (
    <a href={`https://affiliate-program.amazon.com/p/connect/requests?${params}`}
      target="_blank" rel="noreferrer"
      style={{ fontWeight: 500, color: 'inherit', textDecoration: 'none', fontSize: 13 }}
      onMouseEnter={e => e.target.style.textDecoration = 'underline'}
      onMouseLeave={e => e.target.style.textDecoration = 'none'}>
      {brand}
    </a>
  );
}

// ── Sortable column header ────────────────────────────────────────────────────
function SortTh({ col, sortCol, sortDir, onSort, children, style }) {
  const active = sortCol === col;
  return (
    <th style={{ cursor: 'pointer', userSelect: 'none', whiteSpace: 'nowrap', ...style }}
      onClick={() => onSort(col)}>
      {children}
      <span style={{ marginLeft: 4, fontSize: 9, opacity: active ? 1 : 0.25, color: active ? 'var(--accent)' : undefined }}>
        {active && sortDir === 'asc' ? '▲' : '▼'}
      </span>
    </th>
  );
}

// ── Editable date cell ────────────────────────────────────────────────────────
function EditableDateCell({ iso, onUpdate, activeColor, emptyLabel }) {
  const [editing, setEditing] = useState(false);
  const [val, setVal]         = useState('');

  const startEdit = () => {
    const d = iso ? new Date(iso) : new Date();
    const pad = n => String(n).padStart(2, '0');
    setVal(`${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`);
    setEditing(true);
  };

  const commit = () => {
    setEditing(false);
    if (!val) return;
    onUpdate(new Date(val).toISOString());
  };

  if (editing) {
    return (
      <td style={{ whiteSpace: 'nowrap' }}>
        <input type="datetime-local" value={val}
          onChange={e => setVal(e.target.value)}
          onBlur={commit}
          onKeyDown={e => { if (e.key === 'Enter') commit(); if (e.key === 'Escape') setEditing(false); }}
          autoFocus
          style={{ fontSize: 11, background: 'var(--bg-2)', border: '1px solid var(--accent)', borderRadius: 6, color: 'var(--text-0)', padding: '3px 6px', outline: 'none' }}
        />
      </td>
    );
  }

  return (
    <td style={{ fontSize: 12, whiteSpace: 'nowrap', cursor: 'text' }} onClick={startEdit} title="Click to edit">
      {iso
        ? <span style={{ color: activeColor || 'var(--text-2)' }}>{reqFmtDate(iso)}</span>
        : <span style={{ color: 'var(--text-3)' }}>{emptyLabel || '—'}</span>}
    </td>
  );
}

// ── Isolated note cell ────────────────────────────────────────────────────────
function ReqNoteCell({ id, initialNote, onUpdate }) {
  const [val, setVal] = useState(initialNote || '');
  return (
    <td style={{ whiteSpace: 'normal' }}>
      <textarea
        placeholder="Add note…"
        value={val}
        rows={1}
        ref={(el) => {
          if (el) { el.style.height = 'auto'; el.style.height = Math.min(el.scrollHeight, 68) + 'px'; if (document.activeElement !== el) el.scrollTop = 0; }
        }}
        onChange={(e) => { setVal(e.target.value); e.target.style.height = 'auto'; e.target.style.height = Math.min(e.target.scrollHeight, 68) + 'px'; }}
        onBlur={(e) => { onUpdate(id, val); e.target.style.borderColor = 'transparent'; e.target.scrollTop = 0; }}
        onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); e.target.blur(); } }}
        style={{
          width: 160, padding: '5px 8px',
          background: 'transparent', border: '1px dashed transparent',
          borderRadius: 6, color: 'var(--text-0)', font: 'inherit',
          outline: 'none', resize: 'none', overflow: 'hidden',
          lineHeight: '1.5', display: 'block', transition: 'border-color 0.15s', fontSize: 12,
        }}
        onFocus={(e) => e.target.style.borderColor = 'var(--accent-soft)'}
        onMouseEnter={(e) => { if (!val) e.target.style.borderColor = 'var(--line)'; }}
        onMouseLeave={(e) => { if (document.activeElement !== e.target) e.target.style.borderColor = 'transparent'; }}
      />
    </td>
  );
}

// ── Memoized data table ───────────────────────────────────────────────────────
const ReqDataTable = React.memo(function ReqDataTable({
  requested, colOrder, hiddenCols, qcKeys, selectedIds,
  allVisibleSelected, someVisibleSelected, sortCol, sortDir, cbRef,
}) {
  const [followedUpId, setFollowedUpId] = useState(null);
  const [copiedId,     setCopiedId]     = useState(null);
  const [qcCopiedId,   setQcCopiedId]   = useState(null);

  const visibleCols = colOrder.filter(k => !hiddenCols.has(k));

  const renderHeader = (key) => {
    switch (key) {
      case 'product':        return <SortTh key={key} col="name"           sortCol={sortCol} sortDir={sortDir} onSort={k => cbRef.current.toggleSort(k)}>Product</SortTh>;
      case 'asin':           return <SortTh key={key} col="asin"           sortCol={sortCol} sortDir={sortDir} onSort={k => cbRef.current.toggleSort(k)}>ASIN</SortTh>;
      case 'brand':          return <SortTh key={key} col="brand"          sortCol={sortCol} sortDir={sortDir} onSort={k => cbRef.current.toggleSort(k)}>Brand</SortTh>;
      case 'monthlySales':   return <SortTh key={key} col="monthlySales"   sortCol={sortCol} sortDir={sortDir} onSort={k => cbRef.current.toggleSort(k)} style={{ textAlign: 'right' }}>Mo. Sales</SortTh>;
      case 'note':           return <th key={key}>Note</th>;
      case 'price':          return <SortTh key={key} col="price"          sortCol={sortCol} sortDir={sortDir} onSort={k => cbRef.current.toggleSort(k)} style={{ textAlign: 'right' }}>Price</SortTh>;
      case 'cc':             return <SortTh key={key} col="cc"             sortCol={sortCol} sortDir={sortDir} onSort={k => cbRef.current.toggleSort(k)} style={{ textAlign: 'right' }}>CC%</SortTh>;
      case 'ccCommission':   return <SortTh key={key} col="ccCommission"   sortCol={sortCol} sortDir={sortDir} onSort={k => cbRef.current.toggleSort(k)} style={{ textAlign: 'right' }}>Commission</SortTh>;
      case 'campaignDate':   return <th key={key} style={{ whiteSpace: 'nowrap' }}>Campaign Date</th>;
      case 'requestedAt':    return <SortTh key={key} col="requestedAt"    sortCol={sortCol} sortDir={sortDir} onSort={k => cbRef.current.toggleSort(k)}>Requested</SortTh>;
      case 'lastFollowUpAt': return <SortTh key={key} col="lastFollowUpAt" sortCol={sortCol} sortDir={sortDir} onSort={k => cbRef.current.toggleSort(k)}>Last Follow-Up</SortTh>;
      case 'message':        return <th key={key}>Message</th>;
      default: return null;
    }
  };

  const renderCell = (key, r) => {
    switch (key) {
      case 'product':
        return <td key={key}><ReqProductCell r={r}/></td>;
      case 'asin':
        return <td key={key}><ReqCopyableAsin asin={r.asin}/></td>;
      case 'brand':
        return <td key={key}><ReqBrandCell brand={r.brand}/></td>;
      case 'monthlySales':
        return <td key={key} className="num" style={{ textAlign: 'right' }}>{r.monthlySales > 0 ? cbRef.current.fmtInt(r.monthlySales) : <span style={{ color: 'var(--text-3)' }}>—</span>}</td>;
      case 'note':
        return <ReqNoteCell key={key} id={r.id} initialNote={r.note || ''} onUpdate={(...a) => cbRef.current.updateNote(...a)}/>;
      case 'price':
        return <td key={key} className="num" style={{ textAlign: 'right' }}>{r.price > 0 ? cbRef.current.fmtUSD(r.price) : <span style={{ color: 'var(--text-3)' }}>—</span>}</td>;
      case 'cc':
        return <td key={key} style={{ textAlign: 'right' }}>{r.cc > 0 ? <span className="badge badge-success">{r.cc}%</span> : <span style={{ color: 'var(--text-3)' }}>—</span>}</td>;
      case 'ccCommission':
        return <td key={key} className="num" style={{ textAlign: 'right' }}>{r.ccCommission > 0 ? cbRef.current.fmtUSD(r.ccCommission) : <span style={{ color: 'var(--text-3)' }}>—</span>}</td>;
      case 'campaignDate': {
        const dateRange = [r.campaignStart, r.campaignEnd].filter(Boolean).map(reqFmtDateStr).join(' → ');
        if (!dateRange) return <td key={key}><span style={{ color: 'var(--text-3)' }}>—</span></td>;
        const creatorId = localStorage.getItem('aip_creator_id');
        if (r.campaignId && creatorId) {
          const fullId = r.campaignId.startsWith('amzn1.campaign.') ? r.campaignId : `amzn1.campaign.${r.campaignId}`;
          const url = `https://affiliate-program.amazon.com/p/connect/request?creatorId=${creatorId}&adId=${fullId}&campaignId=${fullId}&recc=0&early-acc=0&type=spcc&status=opportunity`;
          return (
            <td key={key} style={{ fontSize: 12, whiteSpace: 'nowrap' }}>
              <a href={url} target="_blank" rel="noreferrer"
                style={{ color: 'var(--accent)', textDecoration: 'none' }}
                onMouseEnter={e => e.target.style.textDecoration = 'underline'}
                onMouseLeave={e => e.target.style.textDecoration = 'none'}>
                {dateRange}
              </a>
            </td>
          );
        }
        return <td key={key} style={{ fontSize: 12, whiteSpace: 'nowrap', color: 'var(--text-2)' }}>{dateRange}</td>;
      }
      case 'requestedAt':
        return <EditableDateCell key={key} iso={r.requestedAt}    onUpdate={(iso) => cbRef.current.updateDate(r.id, 'requestedAt',    iso)}/>;
      case 'lastFollowUpAt':
        return <EditableDateCell key={key} iso={r.lastFollowUpAt} onUpdate={(iso) => cbRef.current.updateDate(r.id, 'lastFollowUpAt', iso)} activeColor="var(--success)" emptyLabel="Not yet"/>;
      case 'message':
        return <td key={key}><MessageCell message={r.messageSent}/></td>;
      default: return null;
    }
  };

  return (
    <div className="card" style={{ overflow: 'auto' }}>
      <table className="data-table">
        <thead>
          <tr>
            <th style={{ width: 44 }}>
              <Checkbox checked={allVisibleSelected} indeterminate={someVisibleSelected && !allVisibleSelected} onChange={() => cbRef.current.toggleSelectAll()}/>
            </th>
            {visibleCols.map(renderHeader)}
            <th style={{ textAlign: 'right', width: 160 }}>Actions</th>
          </tr>
        </thead>
        <tbody>
          {requested.map(r => (
            <tr key={r.id} style={{ background: selectedIds.has(r.id) ? 'rgba(59,79,214,0.08)' : undefined }}>
              <td>
                <Checkbox checked={selectedIds.has(r.id)} onChange={() => cbRef.current.toggleSelect(r.id)}/>
              </td>
              {visibleCols.map(key => renderCell(key, r))}
              <td>
                <div style={{ display: 'flex', gap: 5, justifyContent: 'flex-end', alignItems: 'center' }}>
                  <button
                    title="Follow up — copies template & opens campaign"
                    onClick={() => {
                      setFollowedUpId(r.id);
                      setTimeout(() => setFollowedUpId(null), 1500);
                      cbRef.current.followUp(r.id);
                    }}
                    className="btn btn-sm"
                    style={{
                      background: followedUpId === r.id ? 'var(--success)' : 'var(--accent-soft)',
                      color:      followedUpId === r.id ? '#fff' : 'var(--accent)',
                      border:     `1px solid ${followedUpId === r.id ? 'var(--success)' : 'var(--accent)'}`,
                      fontSize: 11, padding: '4px 8px', gap: 4,
                    }}
                  >
                    {followedUpId === r.id ? <><Icons.check size={11}/> Done</> : <><Icons.arrow size={11}/> Follow Up</>}
                  </button>
                  <button title="Quick copy row" onClick={() => {
                    cbRef.current.quickCopyRow(r, qcKeys);
                    setQcCopiedId(r.id);
                    setTimeout(() => setQcCopiedId(null), 1500);
                  }} className="icon-btn" style={{ width: 26, height: 26, color: qcCopiedId === r.id ? 'var(--success)' : undefined }}>
                    {qcCopiedId === r.id ? <Icons.check size={12}/> : <Icons.copy size={12}/>}
                  </button>
                  <button title="Copy sent message" onClick={() => {
                    cbRef.current.copyMessage(r);
                    setCopiedId(r.id);
                    setTimeout(() => setCopiedId(null), 1500);
                  }} className="icon-btn" style={{ width: 26, height: 26, color: copiedId === r.id ? 'var(--success)' : undefined }}>
                    {copiedId === r.id ? <Icons.check size={12}/> : <Icons.mail size={12}/>}
                  </button>
                  {r.campaignId && localStorage.getItem('aip_creator_id') && (
                    <button title="Open CC campaign" onClick={() => cbRef.current.openCampaign(r)} className="icon-btn" style={{ width: 26, height: 26 }}>
                      <Icons.ext size={12}/>
                    </button>
                  )}
                  <button title="Remove from Requested" onClick={() => cbRef.current.remove(r.id)} className="icon-btn"
                    style={{ width: 26, height: 26, color: 'var(--text-3)' }}
                    onMouseEnter={e => e.currentTarget.style.color = 'var(--danger)'}
                    onMouseLeave={e => e.currentTarget.style.color = 'var(--text-3)'}>
                    <Icons.trash size={12}/>
                  </button>
                </div>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
});

// ── Main Requested view ───────────────────────────────────────────────────────
const RequestedPage = ({ leads, setLeads, setShowTemplatesDrawer }) => {
  const { fmtUSD, fmtInt } = window.AIP_DATA;

  const [sortCol, setSortCol]         = useState('requestedAt');
  const [sortDir, setSortDir]         = useState('desc');
  const [searchInput, setSearchInput] = useState('');
  const [search, setSearch]           = useState('');
  const [selectedIds, setSelectedIds] = useState(new Set());
  const [hiddenCols, setHiddenCols]   = useState(new Set());
  const [colOrder, setColOrder]       = useState(DEFAULT_COL_ORDER);
  const [dragColIdx, setDragColIdx]   = useState(null);
  const [showColDrawer, setShowColDrawer] = useState(false);
  const [showQcPicker, setShowQcPicker]   = useState(false);
  const [qcKeys, setQcKeys]           = useState(new Set(DEFAULT_COL_ORDER));

  useEffect(() => {
    const t = setTimeout(() => setSearch(searchInput), 200);
    return () => clearTimeout(t);
  }, [searchInput]);

  useEffect(() => {
    if (!showColDrawer && !showQcPicker) return;
    const close = (e) => {
      if (e.target.closest('.req-picker')) return;
      setShowColDrawer(false);
      setShowQcPicker(false);
    };
    document.addEventListener('click', close);
    return () => document.removeEventListener('click', close);
  }, [showColDrawer, showQcPicker]);

  const toggleSort = (col) => {
    if (sortCol === col) setSortDir(d => d === 'desc' ? 'asc' : 'desc');
    else { setSortCol(col); setSortDir('desc'); }
  };

  const requested = useMemo(() => {
    const q = search.trim().toLowerCase();
    return [...(leads.requested || [])]
      .filter(r => !q || (r.name || '').toLowerCase().includes(q) || (r.asin || '').toLowerCase().includes(q))
      .sort((a, b) => {
        let av, bv;
        if (sortCol === 'name' || sortCol === 'brand' || sortCol === 'asin') {
          av = (a[sortCol] || '').toLowerCase(); bv = (b[sortCol] || '').toLowerCase();
          return sortDir === 'asc' ? av.localeCompare(bv) : bv.localeCompare(av);
        }
        if      (sortCol === 'cc')             { av = a.cc || 0;              bv = b.cc || 0; }
        else if (sortCol === 'price')          { av = a.price || 0;           bv = b.price || 0; }
        else if (sortCol === 'monthlySales')   { av = a.monthlySales || 0;    bv = b.monthlySales || 0; }
        else if (sortCol === 'ccCommission')   { av = a.ccCommission || 0;    bv = b.ccCommission || 0; }
        else if (sortCol === 'lastFollowUpAt') { av = a.lastFollowUpAt ? new Date(a.lastFollowUpAt).getTime() : 0; bv = b.lastFollowUpAt ? new Date(b.lastFollowUpAt).getTime() : 0; }
        else { av = a.requestedAt ? new Date(a.requestedAt).getTime() : 0; bv = b.requestedAt ? new Date(b.requestedAt).getTime() : 0; }
        return sortDir === 'desc' ? bv - av : av - bv;
      });
  }, [leads.requested, sortCol, sortDir, search]);

  const allVisibleSelected  = requested.length > 0 && requested.every(r => selectedIds.has(r.id));
  const someVisibleSelected = requested.some(r => selectedIds.has(r.id));

  const followUp = (id) => {
    const r = (leads.requested || []).find(rec => rec.id === id);
    setLeads(prev => ({
      ...prev,
      requested: prev.requested.map(rec =>
        rec.id === id ? { ...rec, lastFollowUpAt: new Date().toISOString() } : rec
      ),
    }));
    if (r) {
      const defaultTpl = (leads.templates || []).find(t => t.id === leads.defaultTemplateId);
      if (defaultTpl) navigator.clipboard.writeText(fillTemplate(defaultTpl.body, r, fmtUSD, fmtInt)).catch(() => {});
      openCampaign(r);
    }
  };

  const updateNote = (id, note) => {
    setLeads(prev => ({ ...prev, requested: prev.requested.map(r => r.id === id ? { ...r, note } : r) }));
  };

  const updateDate = (id, field, iso) => {
    setLeads(prev => ({ ...prev, requested: prev.requested.map(r => r.id === id ? { ...r, [field]: iso } : r) }));
  };

  const copyMessage = (r) => { if (r.messageSent) navigator.clipboard.writeText(r.messageSent).catch(() => {}); };

  const quickCopyRow = (r, keys) => {
    const esc = v => { const s = String(v ?? ''); return /[\t\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s; };
    const getVal = (key) => {
      switch (key) {
        case 'product':        return r.name || '';
        case 'asin':           return r.asin || '';
        case 'brand':          return r.brand || '';
        case 'monthlySales':   return r.monthlySales > 0 ? fmtInt(r.monthlySales) : '';
        case 'note':           return r.note || '';
        case 'price':          return r.price > 0 ? fmtUSD(r.price) : '';
        case 'cc':             return r.cc > 0 ? `${r.cc}%` : '';
        case 'ccCommission':   return r.ccCommission > 0 ? fmtUSD(r.ccCommission) : '';
        case 'campaignDate':   return [r.campaignStart, r.campaignEnd].filter(Boolean).map(reqFmtDateStr).join(' → ');
        case 'requestedAt':    return r.requestedAt ? reqFmtDate(r.requestedAt) : '';
        case 'lastFollowUpAt': return r.lastFollowUpAt ? reqFmtDate(r.lastFollowUpAt) : '';
        case 'message':        return r.messageSent || '';
        default:               return '';
      }
    };
    const tsv = colOrder.filter(k => keys.has(k)).map(k => esc(getVal(k))).join('\t');
    navigator.clipboard.writeText(tsv).catch(() => {});
  };

  const openCampaign = (r) => {
    const creatorId = localStorage.getItem('aip_creator_id');
    if (!r.campaignId || !creatorId) return;
    const fullId = r.campaignId.startsWith('amzn1.campaign.') ? r.campaignId : `amzn1.campaign.${r.campaignId}`;
    window.open(`https://affiliate-program.amazon.com/p/connect/request?creatorId=${creatorId}&adId=${fullId}&campaignId=${fullId}&recc=0&early-acc=0&type=spcc&status=opportunity`, '_blank', 'noopener');
  };

  const remove = (id) => {
    setLeads(prev => ({ ...prev, requested: prev.requested.filter(r => r.id !== id) }));
    setSelectedIds(prev => { const s = new Set(prev); s.delete(id); return s; });
  };

  const deleteSelected = () => {
    if (!confirm(`Remove ${selectedIds.size} item${selectedIds.size > 1 ? 's' : ''} from Requested?`)) return;
    setLeads(prev => ({ ...prev, requested: prev.requested.filter(r => !selectedIds.has(r.id)) }));
    setSelectedIds(new Set());
  };

  const toggleSelect = (id) => {
    setSelectedIds(prev => { const s = new Set(prev); s.has(id) ? s.delete(id) : s.add(id); return s; });
  };

  const toggleSelectAll = () => {
    if (allVisibleSelected) {
      setSelectedIds(prev => { const s = new Set(prev); requested.forEach(r => s.delete(r.id)); return s; });
    } else {
      setSelectedIds(prev => { const s = new Set(prev); requested.forEach(r => s.add(r.id)); return s; });
    }
  };

  const exportCSV = () => {
    const visibleColDefs = colOrder.filter(k => !hiddenCols.has(k)).map(k => REQ_COL_MAP[k]).filter(Boolean);
    const esc = v => { const s = String(v ?? ''); return /[,"\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s; };
    const getVal = (key, r) => {
      switch (key) {
        case 'product':        return r.name || '';
        case 'asin':           return r.asin || '';
        case 'brand':          return r.brand || '';
        case 'monthlySales':   return r.monthlySales > 0 ? r.monthlySales : '';
        case 'note':           return r.note || '';
        case 'price':          return r.price > 0 ? fmtUSD(r.price) : '';
        case 'cc':             return r.cc > 0 ? `${r.cc}%` : '';
        case 'ccCommission':   return r.ccCommission > 0 ? fmtUSD(r.ccCommission) : '';
        case 'campaignDate':   return [r.campaignStart, r.campaignEnd].filter(Boolean).map(reqFmtDateStr).join(' → ');
        case 'requestedAt':    return r.requestedAt ? reqFmtDate(r.requestedAt) : '';
        case 'lastFollowUpAt': return r.lastFollowUpAt ? reqFmtDate(r.lastFollowUpAt) : '';
        case 'message':        return r.messageSent || '';
        default:               return '';
      }
    };
    const header = visibleColDefs.map(c => esc(c.label)).join(',');
    const rows   = requested.map(r => visibleColDefs.map(c => esc(getVal(c.key, r))).join(','));
    const blob   = new Blob([[header, ...rows].join('\n')], { type: 'text/csv' });
    const url    = URL.createObjectURL(blob);
    const a      = document.createElement('a');
    a.href = url; a.download = 'requested.csv'; a.click();
    URL.revokeObjectURL(url);
  };

  const cbRef = useRef({});
  cbRef.current = { toggleSort, toggleSelect, toggleSelectAll, followUp, updateNote, updateDate, copyMessage, quickCopyRow, openCampaign, remove, fmtUSD, fmtInt };

  const defaultTpl = (leads.templates || []).find(t => t.id === leads.defaultTemplateId);

  const toggleColVisibility = (key) => {
    setHiddenCols(prev => { const s = new Set(prev); s.has(key) ? s.delete(key) : s.add(key); return s; });
  };

  const reorderCol = (fromIdx, toIdx) => {
    setColOrder(prev => {
      const next = [...prev];
      const [moved] = next.splice(fromIdx, 1);
      next.splice(toIdx, 0, moved);
      return next;
    });
  };

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      {/* ── Page header ─────────────────────────────────────────────────────── */}
      <div style={{ padding: '24px 28px 0', flexShrink: 0 }}>
        <div className="page-header">
          <div className="page-title-block">
            <h1>Requested</h1>
            <div className="subtitle">{requested.length} product{requested.length !== 1 ? 's' : ''} · click any column header to sort</div>
          </div>
          <div className="page-actions">
            {selectedIds.size > 0 && (
              <button className="btn" onClick={deleteSelected} style={{ color: 'var(--danger)', borderColor: 'var(--danger)' }}>
                <Icons.trash size={13}/> Delete {selectedIds.size}
              </button>
            )}
            <button className="btn" onClick={exportCSV}>
              <Icons.download size={13}/> Export
            </button>
            {/* Manage columns */}
            <div className="req-picker" style={{ position: 'relative' }}>
              <button className="btn" onClick={() => { setShowColDrawer(p => !p); setShowQcPicker(false); }}>
                <Icons.columns size={13}/> Manage columns
              </button>
              {showColDrawer && (
                <div style={{
                  position: 'absolute', top: 'calc(100% + 6px)', right: 0, zIndex: 20,
                  background: 'var(--bg-elev)', border: '1px solid var(--line-strong)',
                  borderRadius: 10, padding: 6, minWidth: 210,
                  boxShadow: '0 12px 30px -8px rgba(0,0,0,0.7)',
                }}>
                  <div style={{ fontSize: 11, color: 'var(--text-3)', fontWeight: 600, padding: '4px 8px 6px', letterSpacing: '0.05em' }}>COLUMNS — drag to reorder</div>
                  {colOrder.map((key, idx) => {
                    const col = REQ_COL_MAP[key];
                    if (!col) return null;
                    return (
                      <div key={key}
                        draggable
                        onDragStart={() => setDragColIdx(idx)}
                        onDragOver={e => e.preventDefault()}
                        onDrop={() => { if (dragColIdx !== null && dragColIdx !== idx) reorderCol(dragColIdx, idx); setDragColIdx(null); }}
                        onDragEnd={() => setDragColIdx(null)}
                        style={{
                          display: 'flex', alignItems: 'center', gap: 7,
                          padding: '5px 8px', borderRadius: 6, cursor: 'default',
                          opacity: dragColIdx === idx ? 0.4 : 1,
                        }}
                        onMouseEnter={e => e.currentTarget.style.background = 'var(--line-soft)'}
                        onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                        <span style={{ color: 'var(--text-3)', cursor: 'grab', flexShrink: 0, lineHeight: 0 }}>
                          <Icons.drag size={12}/>
                        </span>
                        <Checkbox checked={!hiddenCols.has(key)} onChange={() => toggleColVisibility(key)}/>
                        <span style={{ flex: 1, fontSize: 12, color: 'var(--text-1)', userSelect: 'none' }}>{col.label}</span>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
            {/* Templates */}
            {setShowTemplatesDrawer && (
              <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 3 }}>
                <button className="btn" onClick={() => setShowTemplatesDrawer(true)}>
                  <Icons.mail size={13}/> Templates
                  {(leads.templates || []).length > 0 && (
                    <span className="badge badge-neutral" style={{ marginLeft: 4, fontSize: 10 }}>{(leads.templates || []).length}</span>
                  )}
                </button>
                {defaultTpl && (
                  <div style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, fontWeight: 600, color: '#f59e0b', paddingRight: 2 }}>
                    <span style={{ width: 6, height: 6, borderRadius: 2, background: '#f59e0b', boxShadow: '0 0 5px #f59e0b' }}/>
                    {defaultTpl.name}
                  </div>
                )}
              </div>
            )}
            {/* Quick copy */}
            <div className="req-picker" style={{ position: 'relative' }}>
              <button className="btn" onClick={() => { setShowQcPicker(p => !p); setShowColDrawer(false); }}>
                <Icons.copy size={13}/> Quick copy
                {qcKeys.size < DEFAULT_COL_ORDER.length && (
                  <span className="badge badge-neutral" style={{ marginLeft: 4, fontSize: 10 }}>{qcKeys.size}</span>
                )}
              </button>
              {showQcPicker && (
                <div style={{
                  position: 'absolute', top: 'calc(100% + 6px)', right: 0, zIndex: 20,
                  background: 'var(--bg-elev)', border: '1px solid var(--line-strong)',
                  borderRadius: 10, padding: 6, minWidth: 210,
                  boxShadow: '0 12px 30px -8px rgba(0,0,0,0.7)',
                }}>
                  <div style={{ fontSize: 11, color: 'var(--text-3)', fontWeight: 600, padding: '4px 8px 6px', letterSpacing: '0.05em' }}>COPY FIELDS</div>
                  {colOrder.map(key => {
                    const col = REQ_COL_MAP[key];
                    if (!col) return null;
                    return (
                      <div key={key}
                        style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '5px 8px', borderRadius: 6, cursor: 'pointer' }}
                        onMouseEnter={e => e.currentTarget.style.background = 'var(--line-soft)'}
                        onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                        <Checkbox checked={qcKeys.has(key)} onChange={() => setQcKeys(prev => { const s = new Set(prev); s.has(key) ? s.delete(key) : s.add(key); return s; })}/>
                        <span style={{ fontSize: 12, color: 'var(--text-1)', userSelect: 'none' }}>{col.label}</span>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          </div>
        </div>
      </div>

      {/* ── Search bar ──────────────────────────────────────────────────────── */}
      <div style={{ padding: '10px 28px 0', flexShrink: 0 }}>
        <div className="card" style={{ padding: '10px 14px' }}>
          <div style={{ position: 'relative' }}>
            <Icons.search size={14} style={{ position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-3)' }}/>
            <input className="field-input" style={{ paddingLeft: 32 }}
              placeholder="Search by title or ASIN…"
              value={searchInput} onChange={e => setSearchInput(e.target.value)}/>
          </div>
        </div>
      </div>

      {/* ── Table ───────────────────────────────────────────────────────────── */}
      <div style={{ flex: 1, overflow: 'auto', padding: '14px 28px 24px' }}>
        {requested.length === 0 ? (
          <div className="card" style={{ padding: '60px 20px', textAlign: 'center' }}>
            <div style={{ width: 52, height: 52, margin: '0 auto', borderRadius: 14, background: 'var(--accent-soft)', display: 'grid', placeItems: 'center', color: 'var(--accent)' }}>
              <Icons.mail size={22}/>
            </div>
            <div style={{ marginTop: 16, fontWeight: 600, fontSize: 15 }}>{search ? 'No results' : 'No requests yet'}</div>
            <div style={{ color: 'var(--text-2)', fontSize: 13, marginTop: 4 }}>
              {search ? 'Try a different search.' : 'Click the Request button on any lead to track it here.'}
            </div>
          </div>
        ) : (
          <ReqDataTable
            requested={requested}
            colOrder={colOrder}
            hiddenCols={hiddenCols}
            qcKeys={qcKeys}
            selectedIds={selectedIds}
            allVisibleSelected={allVisibleSelected}
            someVisibleSelected={someVisibleSelected}
            sortCol={sortCol}
            sortDir={sortDir}
            cbRef={cbRef}
          />
        )}
      </div>
    </div>
  );
};

window.RequestedPage = RequestedPage;
