// ATLAS Accounts Email Agent — views.jsx

// ── VerbChip — action type switcher (must be a component to use useState) ──
function VerbChip({ act, idx, isDone, actionMeta, onChangeType }) {
  const [open, setOpen] = useState(false);
  const meta = actionMeta[act.type] || actionMeta.flag;

  // Close on outside click
  useEffect(() => {
    if (!open) return;
    const handler = () => setOpen(false);
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [open]);

  return (
    <div style={{position:'relative',flexShrink:0}} onMouseDown={e=>e.stopPropagation()}>
      <button
        onClick={e=>{e.stopPropagation();setOpen(o=>!o);}}
        title="Click to change action type"
        style={{
          all:'unset', cursor:'pointer',
          padding:'8px 10px',
          borderRight:'1px solid #e2e8f0',
          background: isDone?'#dcfce7': open?'#e2e8f0':'#f1f5f9',
          fontSize:12, fontWeight:600,
          color: isDone?'#15803d':'#334155',
          whiteSpace:'nowrap', display:'flex', alignItems:'center', gap:5,
        }}>
        <span>{meta.icon}</span>
        <span style={{textDecoration:isDone?'line-through':'none'}}>{meta.verb}</span>
        <span style={{fontSize:9,color:'#94a3b8',marginLeft:1}}>▾</span>
      </button>
      {open && (
        <div style={{
          position:'absolute', top:'100%', left:0, zIndex:200, minWidth:180,
          background:'#fff', border:'1px solid #e2e8f0', borderRadius:8,
          boxShadow:'0 4px 16px rgba(0,0,0,.15)', overflow:'hidden', marginTop:2,
        }}>
          {Object.entries(actionMeta).map(([t, m]) => (
            <button key={t}
              onClick={e=>{e.stopPropagation(); onChangeType(t, m); setOpen(false);}}
              style={{
                all:'unset', display:'flex', alignItems:'flex-start', gap:8,
                width:'100%', padding:'9px 14px', cursor:'pointer', fontSize:12,
                background: t===act.type ? '#f0f9ff' : 'transparent',
                color: t===act.type ? '#0369a1' : '#1e293b',
                fontWeight: t===act.type ? 700 : 400,
                borderBottom:'1px solid #f8fafc',
                boxSizing:'border-box',
              }}
              onMouseEnter={e=>e.currentTarget.style.background='#f8fafc'}
              onMouseLeave={e=>e.currentTarget.style.background=t===act.type?'#f0f9ff':'transparent'}>
              <span style={{flexShrink:0,marginTop:1}}>{m.icon}</span>
              <div style={{flex:1,minWidth:0}}>
                <div style={{fontWeight:600}}>{m.verb}</div>
                <div style={{fontSize:10,color:'#94a3b8',fontWeight:400,marginTop:1,lineHeight:1.3}}>{m.desc}</div>
              </div>
              {t===act.type && <span style={{flexShrink:0,fontSize:11,color:'#0369a1',marginTop:1}}>✓</span>}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

// ── DuplicateThread — shows the original email for a duplicate warning ────────
function DuplicateThread({ matchId, currentItemId }) {
  const [info, setInfo] = React.useState(null);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    if (!matchId) return;
    fetch(`/api/email/${encodeURIComponent(matchId)}`)
      .then(r => r.json())
      .then(d => { setInfo(d && !d.error ? d : null); setLoading(false); })
      .catch(() => setLoading(false));
  }, [matchId]);

  if (loading) return <div style={{fontSize:11,color:'#b91c1c',marginTop:6,fontStyle:'italic'}}>Loading original…</div>;
  if (!info) return null;

  const dateStr = info.firstSeenAt
    ? info.firstSeenAt.slice(0, 10)
    : info.emailDate ? info.emailDate.slice(0, 10) : '';

  const handleDismiss = () => {
    fetch('/api/review/dismiss', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id: currentItemId }),
    }).then(() => window.location.reload()).catch(() => {});
  };

  return (
    <div style={{marginTop:8,padding:'8px 10px',background:'#fff7ed',border:'1px solid #fdba74',borderRadius:6,fontSize:12,color:'#78350f'}}>
      <div style={{fontWeight:600,marginBottom:4}}>📧 Original: <span style={{fontWeight:400}}>{info.subject || '(no subject)'}</span>{dateStr && <span style={{color:'#a16207',marginLeft:6}}>— {dateStr}</span>}</div>
      <div style={{display:'flex',gap:6,flexWrap:'wrap',marginTop:4}}>
        {info.webLink && (
          <a href={info.webLink} target="_blank" rel="noreferrer"
            style={{fontSize:11,padding:'3px 8px',background:'#f97316',color:'#fff',border:'none',borderRadius:4,cursor:'pointer',textDecoration:'none'}}
          >Open original in Outlook ↗</a>
        )}
        {currentItemId && (
          <button
            onClick={handleDismiss}
            style={{fontSize:11,padding:'3px 8px',background:'#fff',color:'#dc2626',border:'1px solid #fca5a5',borderRadius:4,cursor:'pointer'}}
          >Dismiss this duplicate</button>
        )}
      </div>
    </div>
  );
}

// ── LabelsTab ───────────────────────────────────────────────────────────────────────────────────
function LabelsTab({ pushToast }) {
  const [labels, setLabels] = useState([]);
  const [showForm, setShowForm] = useState(false);
  const [editing, setEditing] = useState(null);
  const [form, setForm] = useState({ name: '', color: '#6366f1', matchPrompt: '', suggestedFolder: '' });
  const [saving, setSaving] = useState(false);

  const PRESET_COLORS = ['#6366f1','#0d9488','#dc2626','#d97706','#059669','#7c3aed','#0369a1','#be185d','#374151'];

  const load = useCallback(async () => {
    try { const d = await api.get('/api/labels'); setLabels(d); } catch {}
  }, []);

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

  const resetForm = () => setForm({ name: '', color: '#6366f1', matchPrompt: '', suggestedFolder: '' });

  const handleSave = async () => {
    if (!form.name.trim() || !form.matchPrompt.trim()) return;
    setSaving(true);
    try {
      if (editing) {
        await api.patch(`/api/labels/${editing}`, form);
        pushToast('Label updated');
      } else {
        await api.post('/api/labels', form);
        pushToast('✅ Label created — will apply on next scan');
      }
      resetForm(); setShowForm(false); setEditing(null); load();
    } catch(e) { pushToast('Error: ' + e.message); }
    setSaving(false);
  };

  const handleEdit = (lbl) => {
    setForm({ name: lbl.name, color: lbl.color, matchPrompt: lbl.matchPrompt, suggestedFolder: lbl.suggestedFolder || '' });
    setEditing(lbl.id); setShowForm(true);
  };

  const handleToggle = async (lbl) => {
    await api.patch(`/api/labels/${lbl.id}`, { active: !lbl.active });
    load();
  };

  const handleDelete = async (lbl) => {
    if (!confirm(`Delete label "${lbl.name}"?`)) return;
    await api.delete(`/api/labels/${lbl.id}`);
    pushToast('Label deleted'); load();
  };

  return (
    <div>
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:16}}>
        <div>
          <div style={{fontSize:14,fontWeight:700,color:'#1f2937'}}>Custom Labels</div>
          <div style={{fontSize:12,color:'#6b7280',marginTop:2}}>Labels are applied by Claude during scanning. Each label needs a plain-English match rule.</div>
        </div>
        <button className="btn-primary" onClick={()=>{resetForm();setEditing(null);setShowForm(s=>!s);}}>+ New Label</button>
      </div>

      {showForm && (
        <div style={{background:'#f8fafc',border:'1px solid #e2e8f0',borderRadius:10,padding:18,marginBottom:20}}>
          <div style={{fontSize:13,fontWeight:700,color:'#1f2937',marginBottom:14}}>{editing?'Edit Label':'New Label'}</div>
          <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:12,marginBottom:12}}>
            <div>
              <label style={{fontSize:11,fontWeight:700,color:'#6b7280',display:'block',marginBottom:4}}>LABEL NAME *</label>
              <input value={form.name} onChange={e=>setForm(f=>({...f,name:e.target.value}))}
                placeholder="e.g. Overdue Account, North East Link"
                style={{width:'100%',padding:'8px 10px',borderRadius:7,border:'1px solid #d1d5db',fontSize:13,boxSizing:'border-box'}}/>
            </div>
            <div>
              <label style={{fontSize:11,fontWeight:700,color:'#6b7280',display:'block',marginBottom:4}}>SUGGESTED FOLDER (optional)</label>
              <input value={form.suggestedFolder} onChange={e=>setForm(f=>({...f,suggestedFolder:e.target.value}))}
                placeholder="e.g. Projects/North East Link"
                style={{width:'100%',padding:'8px 10px',borderRadius:7,border:'1px solid #d1d5db',fontSize:13,boxSizing:'border-box'}}/>
            </div>
          </div>
          <div style={{marginBottom:12}}>
            <label style={{fontSize:11,fontWeight:700,color:'#6b7280',display:'block',marginBottom:6}}>COLOUR</label>
            <div style={{display:'flex',gap:8,flexWrap:'wrap',alignItems:'center'}}>
              {PRESET_COLORS.map(c=>(
                <button key={c} onClick={()=>setForm(f=>({...f,color:c}))} style={{
                  width:28,height:28,borderRadius:'50%',background:c,border:'none',cursor:'pointer',
                  outline:form.color===c?`3px solid ${c}`:'none',outlineOffset:2,
                  transform:form.color===c?'scale(1.15)':'scale(1)',transition:'transform 0.1s',
                }}/>
              ))}
              <input type="color" value={form.color} onChange={e=>setForm(f=>({...f,color:e.target.value}))}
                style={{width:28,height:28,borderRadius:'50%',border:'1px solid #d1d5db',padding:0,cursor:'pointer'}}
                title="Custom colour"/>
            </div>
          </div>
          <div style={{marginBottom:16}}>
            <label style={{fontSize:11,fontWeight:700,color:'#6b7280',display:'block',marginBottom:4}}>
              MATCH RULE — plain English description of emails that should get this label *
            </label>
            <textarea value={form.matchPrompt} onChange={e=>setForm(f=>({...f,matchPrompt:e.target.value}))}
              placeholder={"Examples:\n• Emails from suppliers where the account is overdue or they threaten stop-credit\n• Emails related to the North East Link project (mention NEL, North East Link, Transurban)\n• Fuel card invoices and statements from BP or Shell"}
              rows={4}
              style={{width:'100%',padding:'9px 12px',borderRadius:7,border:'1px solid #d1d5db',fontSize:13,resize:'vertical',fontFamily:'inherit',boxSizing:'border-box',lineHeight:1.5}}
            />
            <div style={{fontSize:11,color:'#9ca3af',marginTop:4}}>
              💡 Be specific. Claude reads this rule for every incoming email. More detail = better accuracy.
            </div>
          </div>
          {form.name && (
            <div style={{marginBottom:14,display:'flex',alignItems:'center',gap:8}}>
              <span style={{fontSize:11,color:'#6b7280'}}>Preview:</span>
              <span style={{display:'inline-flex',alignItems:'center',gap:5,fontSize:11,fontWeight:700,padding:'3px 10px',borderRadius:20,
                background:form.color+'22',color:form.color,border:`1px solid ${form.color}55`}}>
                <span style={{width:7,height:7,borderRadius:'50%',background:form.color,flexShrink:0}}/>
                {form.name}
              </span>
            </div>
          )}
          <div style={{display:'flex',gap:8}}>
            <button className="btn-primary" onClick={handleSave} disabled={saving||!form.name.trim()||!form.matchPrompt.trim()}>
              {saving?'Saving…':editing?'Save changes':'Create label'}
            </button>
            <button className="btn-ghost" onClick={()=>{setShowForm(false);setEditing(null);resetForm();}}>Cancel</button>
          </div>
        </div>
      )}

      {labels.length===0&&!showForm ? (
        <div style={{textAlign:'center',padding:'40px 20px',color:'#9ca3af'}}>
          <div style={{fontSize:32,marginBottom:8}}>🏷️</div>
          <div style={{fontSize:14,fontWeight:600,marginBottom:4,color:'#6b7280'}}>No custom labels yet</div>
          <div style={{fontSize:12}}>Create a label to start tagging emails automatically during scans</div>
        </div>
      ) : (
        <div style={{display:'flex',flexDirection:'column',gap:8}}>
          {labels.map(lbl=>(
            <div key={lbl.id} style={{
              background:'#fff',border:'1px solid #e5e7eb',borderRadius:10,padding:'14px 16px',
              display:'flex',alignItems:'flex-start',gap:14,
              opacity:lbl.active?1:0.55,
              borderLeft:`3px solid ${lbl.color}`,
            }}>
              <div style={{flex:1,minWidth:0}}>
                <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:4}}>
                  <span style={{display:'inline-flex',alignItems:'center',gap:5,fontSize:12,fontWeight:700,padding:'2px 9px',borderRadius:20,
                    background:lbl.color+'22',color:lbl.color,border:`1px solid ${lbl.color}55`}}>
                    <span style={{width:6,height:6,borderRadius:'50%',background:lbl.color,flexShrink:0}}/>
                    {lbl.name}
                  </span>
                  {!lbl.active&&<span style={{fontSize:10,fontWeight:700,color:'#9ca3af',background:'#f3f4f6',borderRadius:10,padding:'1px 6px'}}>PAUSED</span>}
                  {lbl.suggestedFolder&&<span style={{fontSize:11,color:'#6b7280'}}>📁 {lbl.suggestedFolder}</span>}
                </div>
                <div style={{fontSize:12,color:'#6b7280',lineHeight:1.5,fontStyle:'italic',marginTop:2}}>
                  "{lbl.matchPrompt}"
                </div>
              </div>
              <div style={{display:'flex',gap:6,flexShrink:0}}>
                <button onClick={()=>handleToggle(lbl)}
                  style={{all:'unset',cursor:'pointer',fontSize:11,padding:'4px 10px',borderRadius:6,
                    border:'1px solid #e5e7eb',background:lbl.active?'#f9fafb':'#f0fdf4',
                    color:lbl.active?'#6b7280':'#16a34a',fontWeight:600}}>
                  {lbl.active?'Pause':'Enable'}
                </button>
                <button onClick={()=>handleEdit(lbl)}
                  style={{all:'unset',cursor:'pointer',fontSize:11,padding:'4px 10px',borderRadius:6,
                    border:'1px solid #e5e7eb',background:'#f9fafb',color:'#374151',fontWeight:600}}>Edit</button>
                <button onClick={()=>handleDelete(lbl)}
                  style={{all:'unset',cursor:'pointer',fontSize:11,padding:'4px 10px',borderRadius:6,
                    border:'1px solid #fca5a5',background:'#fff',color:'#dc2626',fontWeight:600}}
                  onMouseEnter={e=>e.currentTarget.style.background='#fee2e2'}
                  onMouseLeave={e=>e.currentTarget.style.background='#fff'}>Delete</button>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── ItemActions ───────────────────────────────────────────────────────────
function ItemActions({ item, acts, setActions, pushToast, KNOWN_FOLDERS }) {
  const ALLOWED = ['file','forward','folder','reply'];
  const ALLOWED_META = {
    file:    { icon: '\ud83d\udcc1', verb: 'Save Invoice to',  placeholder: 'e.g. Invoices/Boral/2026', isFolder: true },
    forward: { icon: '\u27a1\ufe0f', verb: 'Forward to',       placeholder: 'e.g. abs@eliteroads.com.au' },
    folder:  { icon: '\ud83d\udcc2', verb: 'Move to folder',   placeholder: 'e.g. AP/Statements', isFolder: true },
    reply:   { icon: '\u2709\ufe0f', verb: 'Reply',             placeholder: 'Reply note' },
  };

  const alertText = item.action || (acts.find(a=>a.type==='flag'||a.type==='alert')?.label) || '';
  const [localAlert, setLocalAlert] = useState(alertText);
  const [replyOpen, setReplyOpen] = useState(false);

  const allowedActs = acts.filter(a => ALLOWED.includes(a.type));
  const missingTypes = ALLOWED.filter(t => !acts.some(a=>a.type===t));

  const saveAct = (newActs) => {
    setActions(item, newActs);
    api.post('/api/review/update-actions', {id:item.id, actions:newActs}).catch(()=>{});
  };

  const updateAllowedAct = (idx, patch) => {
    const target = allowedActs[idx];
    const next = acts.map(a => a === target ? {...a, ...patch} : a);
    saveAct(next);
  };

  const deleteAllowedAct = (idx) => {
    const target = allowedActs[idx];
    saveAct(acts.filter(a => a !== target));
  };

  const addAct = (type) => {
    const m = ALLOWED_META[type];
    saveAct([...acts, {type, label: m.verb, target:'', done:false}]);
  };

  return (
    <div style={{marginBottom:16}}>
      <div style={{fontSize:10,fontWeight:700,textTransform:'uppercase',letterSpacing:'0.06em',color:'#9ca3af',marginBottom:8}}>Actions</div>

      {/* Alert card — always shown */}
      <div style={{
        background:'#fffbeb',border:'1px solid #fde68a',borderRadius:8,
        padding:'10px 12px',marginBottom:10,
      }}>
        <div style={{display:'flex',alignItems:'center',gap:6,marginBottom:6}}>
          <span style={{fontSize:14}}>🚨</span>
          <span style={{fontSize:11,fontWeight:700,color:'#92400e',textTransform:'uppercase',letterSpacing:'0.04em'}}>Alert</span>
          <span style={{fontSize:11,color:'#b45309',marginLeft:4,fontStyle:'italic'}}>AI suggested action — edit as needed</span>
        </div>
        <textarea
          value={localAlert}
          onChange={e=>setLocalAlert(e.target.value)}
          onBlur={()=>{
            const next = acts.filter(a=>a.type!=='flag'&&a.type!=='alert');
            if (localAlert.trim()) next.unshift({type:'flag',label:localAlert,target:'',done:false});
            saveAct(next);
          }}
          rows={2}
          style={{
            width:'100%',border:'none',background:'transparent',
            fontSize:12,color:'#92400e',resize:'none',
            fontFamily:'inherit',lineHeight:1.5,outline:'none',
            boxSizing:'border-box',
          }}
          placeholder="Describe what action should be taken..."
        />
      </div>

      {/* Action rows */}
      {allowedActs.map((act, i) => {
        const m = ALLOWED_META[act.type] || ALLOWED_META.file;
        const isReply = act.type === 'reply';
        return (
          <div key={i}>
            <div style={{
              display:'flex',alignItems:'center',gap:0,marginBottom:5,
              borderRadius:7,border:'1px solid #e2e8f0',
              background:'#fff',overflow:'hidden',
            }}>
              <div style={{
                padding:'8px 12px',borderRight:'1px solid #e2e8f0',
                background:'#f8fafc',display:'flex',alignItems:'center',gap:6,
                fontSize:12,fontWeight:600,color:'#334155',whiteSpace:'nowrap',flexShrink:0,
              }}>
                <span>{m.icon}</span><span>{m.verb}</span>
              </div>
              {!isReply && (
                m.isFolder ? (
                  <div style={{flex:1,position:'relative',minWidth:0}}>
                    <input list={`act-folders-${item.id}-${i}`}
                      value={act.target||''}
                      onChange={e=>updateAllowedAct(i,{target:e.target.value,label:`${m.verb} ${e.target.value}`})}
                      placeholder={m.placeholder}
                      style={{width:'100%',border:'none',background:'transparent',padding:'8px 10px',fontSize:12,color:'#1e293b',outline:'none',boxSizing:'border-box'}}
                    />
                    <datalist id={`act-folders-${item.id}-${i}`}>{(KNOWN_FOLDERS||[]).map(f=><option key={f} value={f}/>)}</datalist>
                  </div>
                ) : (
                  <input value={act.target||''}
                    onChange={e=>updateAllowedAct(i,{target:e.target.value,label:`${m.verb} ${e.target.value}`})}
                    placeholder={m.placeholder}
                    style={{flex:1,border:'none',background:'transparent',padding:'8px 10px',fontSize:12,color:'#1e293b',outline:'none',minWidth:0}}
                  />
                )
              )}
              {isReply && (
                <button onClick={()=>setReplyOpen(o=>!o)}
                  style={{flex:1,all:'unset',cursor:'pointer',padding:'8px 10px',fontSize:12,
                    color:replyOpen?'#4338ca':'#64748b',fontWeight:replyOpen?700:400}}>
                  {replyOpen ? 'Hide reply drafter \u25b2' : 'Open reply drafter \u25bc'}
                </button>
              )}
              <button onClick={()=>deleteAllowedAct(i)}
                style={{all:'unset',cursor:'pointer',padding:'8px 10px',color:'#cbd5e1',fontSize:16,lineHeight:1,flexShrink:0}}
                onMouseEnter={e=>e.currentTarget.style.color='#ef4444'}
                onMouseLeave={e=>e.currentTarget.style.color='#cbd5e1'}>×</button>
            </div>
            {isReply && replyOpen && (
              <div style={{marginBottom:5}}>
                <ReplyDrafter item={item} pushToast={pushToast} defaultOpen={true}/>
              </div>
            )}
          </div>
        );
      })}

      {/* Add buttons */}
      {missingTypes.length > 0 && (
        <div style={{display:'flex',gap:6,marginTop:6,flexWrap:'wrap',alignItems:'center'}}>
          <span style={{fontSize:10,color:'#94a3b8',fontWeight:600,letterSpacing:'0.05em'}}>ADD:</span>
          {missingTypes.map(type => {
            const m = ALLOWED_META[type];
            return (
              <button key={type} onClick={()=>addAct(type)}
                style={{all:'unset',cursor:'pointer',fontSize:11,padding:'4px 10px',
                  borderRadius:10,border:'1px dashed #cbd5e1',color:'#64748b',
                  background:'#f8fafc',display:'inline-flex',alignItems:'center',gap:4}}
                onMouseEnter={e=>{e.currentTarget.style.background='#e2e8f0';e.currentTarget.style.color='#1e293b';}}
                onMouseLeave={e=>{e.currentTarget.style.background='#f8fafc';e.currentTarget.style.color='#64748b';}}>
                {m.icon} + {m.verb}
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ── Review Queue ──────────────────────────────────────────────────────────────
function ReviewQueueView({ queue, onRefresh, pushToast, labels = [] }) {
  const [confirming, setConfirming] = useState(null);
  const [overriding, setOverriding] = useState(null);
  const [overrideCat, setOverrideCat] = useState('');
  const [relabeling, setRelabeling] = useState(null); // item being relabeled
  const [relabelCat, setRelabelCat] = useState('');
  const [busy, setBusy] = useState(null);
  const [bodyItem, setBodyItem] = useState(null); // full email body modal
  const [localActions, setLocalActions] = useState({}); // itemId → actions[]
  const [expandedId, setExpandedId] = useState(null); // compact view: which card is open
  const [catFilter, setCatFilter] = useState('all'); // compact view: category filter
  const [search, setSearch] = useState('');
  const [page, setPage] = useState(0);
  const PAGE_SIZE = 20;
  const [relabelling, setRelabelling] = useState(false);

  const getActions = (item) => localActions[item.id] ?? item.actions ?? [];
  const setActions = (item, acts) => setLocalActions(prev => ({ ...prev, [item.id]: acts }));

  const handleSaveActions = async (item) => {
    try {
      await api.post('/api/review/update-actions', { id: item.id, actions: getActions(item) });
    } catch(e) { /* non-critical */ }
  };

  // Action type definitions — fixed verb, editable parameter only
  const ACTION_META = {
    flag:    { icon: '🚨', verb: 'Alert',          desc: 'Flag for attention or add a note for the reviewer', paramLabel: 'Note',          placeholder: 'e.g. Escalate to management' },
    file:    { icon: '📁', verb: 'Save to',         desc: 'Save / file this email into an Outlook folder',     paramLabel: 'Folder',        placeholder: 'e.g. Invoices/Boral/2026', isFolder: true },
    forward: { icon: '➡️', verb: 'Forward to',      desc: 'Forward this email to a team member',               paramLabel: 'Email address', placeholder: 'e.g. alison@eliteroads.com.au' },
    pay:     { icon: '💰', verb: 'Arrange payment', desc: 'Log in Urgent Payments and schedule payment',       paramLabel: 'Amount / ref',  placeholder: 'e.g. $5,839.00 — INV-95340' },
    reply:   { icon: '✉️', verb: 'Reply',            desc: 'Send a reply to the sender',                        paramLabel: 'Reply note',    placeholder: 'e.g. Acknowledge receipt' },
    folder:  { icon: '📂', verb: 'Move to folder',  desc: 'Move email to a specific Outlook folder',           paramLabel: 'Folder path',   placeholder: 'e.g. HR/Superannuation', isFolder: true },
    alert:   { icon: '🔔', verb: 'Notify',           desc: 'Send a Telegram alert to management',               paramLabel: 'Who / what',    placeholder: 'e.g. Notify Deon — overdue' },
  };
  const ACTION_TYPES = Object.entries(ACTION_META).map(([type, m]) => ({ type, ...m }));

  // Known Outlook folders for the Save to / Move to folder picker
  const KNOWN_FOLDERS = [
    'Invoices', 'Invoices/Boral', 'Invoices/Fulton Hogan', 'Invoices/Hanson',
    'Invoices/Coates Hire', 'Invoices/Aspect Personnel', 'Invoices/VicRoads',
    'Statements', 'Dockets', 'Urgent', 'Queries',
    'Fleet', 'Fleet/Registrations', 'Fleet/Fuel', 'Fleet/Repairs',
    'Tenders', 'HR', 'HR/Superannuation', 'HR/Payroll', 'Noise',
    'Suppliers/Aspect Personnel/Queries', 'Suppliers/Boral',
  ];

  const ALL_CATS = [
    'invoice','statement','docket','urgent-payment','supplier-query',
    'route-fleet','route-estimator','route-hr','route-other','noise',
  ];

  const handleApprove = async (item) => {
    setBusy(item.id);
    try {
      // Save latest local actions before approving
      const acts = getActions(item);
      if (acts.length > 0) {
        await api.post('/api/review/update-actions', { id: item.id, actions: acts }).catch(()=>{});
      }
      await api.post('/api/review/approve', { id: item.id });

      // Build toast summary of what was actioned
      const folderAct = acts.find(a => a.type === 'file' || a.type === 'folder');
      const fwdActs   = acts.filter(a => a.type === 'forward' && a.target);
      const payAct    = acts.find(a => a.type === 'pay');
      const parts = ['✅ Approved'];
      if (folderAct?.target) parts.push(`📁 Filed to ${folderAct.target}`);
      if (fwdActs.length)    parts.push(`➡️ Forwarded to ${fwdActs.map(a=>a.target).join(', ')}`);
      if (payAct)            parts.push('💰 Payment logged');
      pushToast(parts.join(' · '));
      onRefresh();
    } catch(e) { pushToast('Error: ' + e.message); }
    setBusy(null);
  };

  const handleDismiss = async (item) => {
    setBusy(item.id);
    try {
      await api.post('/api/review/dismiss', { id: item.id });
      pushToast('Dismissed');
      onRefresh();
    } catch(e) { pushToast('Error: ' + e.message); }
    setBusy(null);
    setConfirming(null);
  };

  const handleOverride = async (item) => {
    if (!overrideCat) return;
    setBusy(item.id);
    try {
      await api.post('/api/review/override', { id: item.id, category: overrideCat });
      pushToast('Category overridden → ' + fmtCatLabel(overrideCat));
      onRefresh();
    } catch(e) { pushToast('Error: ' + e.message); }
    setBusy(null);
    setOverriding(null);
  };

  const handleRelabelItem = async (item) => {
    if (!relabelCat) return;
    setBusy(item.id);
    try {
      await api.post('/api/review/relabel', { id: item.id, category: relabelCat });
      pushToast('Relabelled → ' + fmtCatLabel(relabelCat));
      onRefresh();
    } catch(e) { pushToast('Error: ' + e.message); }
    setBusy(null);
    setRelabeling(null);
  };

  const handleAddCategory = async (item) => {
    const name = item.suggestedCategoryName || '';
    if (!name) return;
    try {
      await api.post('/api/category/add', {
        key: name.toLowerCase().replace(/\s+/g, '-'),
        displayName: name,
        forwardTo: [],
        autoForward: false,
      });
      pushToast('✅ Category added: ' + name);
      onRefresh();
    } catch(e) { pushToast('Error: ' + e.message); }
  };

  // ── Category counts for filter bar ──
  const catCounts = useMemo(() => {
    const c = {};
    (queue||[]).forEach(i => { c[i.category] = (c[i.category]||0)+1; });
    return c;
  }, [queue]);

  // ── Filtered + searched items ──
  const filteredQueue = useMemo(() => {
    let items = queue || [];
    if (catFilter !== 'all') items = items.filter(i => i.category === catFilter);
    if (search.trim()) {
      const q = search.toLowerCase();
      items = items.filter(i =>
        (i.subject||'').toLowerCase().includes(q) ||
        (i.supplierName||i.from||'').toLowerCase().includes(q) ||
        (i.fromEmail||'').toLowerCase().includes(q)
      );
    }
    return items;
  }, [queue, catFilter, search]);

  // Sort: urgent-payment first, then by date desc
  const sortedQueue = useMemo(() => {
    setPage(0); // reset to first page on filter/search change
    return [...filteredQueue].sort((a,b) => {
      if (a.category==='urgent-payment' && b.category!=='urgent-payment') return -1;
      if (b.category==='urgent-payment' && a.category!=='urgent-payment') return 1;
      return new Date(b.emailDate||b.queuedAt||0) - new Date(a.emailDate||a.queuedAt||0);
    });
  }, [filteredQueue]);

  const totalPages = Math.ceil(sortedQueue.length / PAGE_SIZE);
  const pagedQueue = sortedQueue.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);

  // All unique categories present in queue
  const queueCats = useMemo(() => [
    'all',
    ...['urgent-payment','invoice','statement','docket','supplier-query','route-fleet','route-estimator','route-hr','noise']
      .filter(c => catCounts[c])
  ], [catCounts]);

  if (!queue?.length) {
    return (
      <div className="main-inner">
        <div className="page-head"><div><h1 className="page-title">Review Queue</h1><p className="page-sub">Items requiring Mindy's attention</p></div></div>
        <div className="empty-state">
          <div style={{fontSize:48,marginBottom:12}}>✅</div>
          <div style={{fontSize:16,fontWeight:600,color:'var(--navy)',marginBottom:4}}>Queue is clear</div>
          <div style={{fontSize:13,color:'#6b7280'}}>All emails processed with high confidence</div>
        </div>
      </div>
    );
  }

  const handleRelabelQueue = async () => {
    setRelabelling(true);
    pushToast('Re-labelling queue items…');
    try {
      const r = await api.post('/api/relabel', {});
      pushToast(`✅ Re-label done — ${r.updated} items updated`);
      onRefresh();
    } catch(e) { pushToast('Re-label failed: ' + e.message); }
    setRelabelling(false);
  };

  // The selected item for the reading pane
  const selectedItem = expandedId ? sortedQueue.find(i => i.id === expandedId) || queue.find(i => i.id === expandedId) : null;

  return (
    <>
    <div className="queue-split-root" style={{display:'flex',flex:1,height:'100%',gap:0,minHeight:0,overflow:'hidden'}}>

    {/* ── LEFT: list column ── */}
    <div style={{
      flex: selectedItem ? '0 0 52%' : '1 1 100%',
      minWidth:0,
      display:'flex', flexDirection:'column',
      transition:'flex 0.2s ease',
      overflowY:'auto',
      height:'calc(100vh - 52px)',
      maxHeight:'calc(100vh - 52px)',
      padding:'24px 20px 40px 28px',
      boxSizing:'border-box',
    }}>
      {/* ── Header ── */}
      <div className="page-head">
        <div>
          <h1 className="page-title">Review Queue</h1>
          <p className="page-sub">{sortedQueue.length} of {queue.length} item{queue.length!==1?'s':''} · 20/page · click a row to expand</p>
        </div>
        <button onClick={handleRelabelQueue} disabled={relabelling}
          style={{all:'unset',cursor:relabelling?'wait':'pointer',fontSize:12,fontWeight:600,
            padding:'6px 14px',borderRadius:7,border:'1px solid #e5e7eb',
            background:'#f9fafb',color:'#374151',display:'flex',alignItems:'center',gap:6,
            opacity:relabelling?0.6:1}}
          title="Re-run urgency rules and custom labels against all queued items">
          {relabelling ? <Icons.spin style={{width:13,height:13}}/> : '🏷️'}
          {relabelling ? 'Re-labelling…' : 'Re-label Queue'}
        </button>
      </div>

      {/* ── Filter bar ── */}
      <div style={{display:'flex',gap:8,marginBottom:12,flexWrap:'wrap',alignItems:'center'}}>
        {/* Category filter pills */}
        <div style={{display:'flex',gap:6,flexWrap:'wrap',flex:1}}>
          {queueCats.map(c => {
            const isActive = catFilter === c;
            const count = c==='all' ? queue.length : (catCounts[c]||0);
            const cs = c==='all' ? {color:'#1f2937',border:'#d1d5db',bg:'#f9fafb',activeBg:'#1f2937',activeColor:'#fff'} :
              (() => { const s=catStyle(c); return {color:s.color,border:s.border,bg:s.bg,activeBg:s.color,activeColor:'#fff'}; })();
            return (
              <button key={c} onClick={() => setCatFilter(c)} style={{
                all:'unset', cursor:'pointer', fontSize:11, fontWeight:700,
                padding:'4px 10px', borderRadius:20,
                border:`1px solid ${isActive ? cs.activeBg : cs.border}`,
                background: isActive ? cs.activeBg : cs.bg,
                color: isActive ? cs.activeColor : cs.color,
                display:'inline-flex', alignItems:'center', gap:5,
              }}>
                {c==='all' ? 'All' : fmtCatLabel(c)}
                <span style={{fontWeight:800,opacity:0.75}}>{count}</span>
              </button>
            );
          })}
        </div>
        {/* Search */}
        <input
          value={search} onChange={e=>setSearch(e.target.value)}
          placeholder="🔍 Search subject, supplier…"
          style={{fontSize:12,padding:'6px 10px',borderRadius:8,border:'1px solid #d1d5db',minWidth:200,outline:'none'}}
        />
        {(search || catFilter!=='all') && (
          <button onClick={()=>{setSearch('');setCatFilter('all');}} style={{
            all:'unset',cursor:'pointer',fontSize:12,color:'#6b7280',padding:'5px 10px',
            borderRadius:8,border:'1px solid #e5e7eb',background:'#f9fafb'
          }}>× Clear</button>
        )}
      </div>

      {/* ── Compact list ── */}
      <div style={{border:'1px solid #e5e7eb',borderRadius:10,overflow:'hidden',background:'#fff'}}>
        {sortedQueue.length === 0 ? (
          <div style={{padding:'24px',textAlign:'center',color:'#9ca3af',fontSize:13}}>No items match this filter</div>
        ) : pagedQueue.map((item, idx) => {
          const isSelected = expandedId === item.id;
          const isUrgent = item.category === 'urgent-payment' || (item.tags||[]).includes('urgent-payment');
          const isDupe = !!item.isDuplicate;
          const acts = getActions(item);

          const isCritical = !!item.isCritical;
          const urgencyScore = item.urgencyScore || 3;
          // Row background — selected = teal highlight, else urgency colour
          const rowBg = isSelected ? '#e0f2fe' : isCritical ? '#fdf2f8' : isUrgent ? '#fff5f5' : isDupe ? '#fffbf0' : '#fff';
          const borderColor = isSelected ? '#7dd3fc' : isCritical ? '#f9a8d4' : isUrgent ? '#fecaca' : isDupe ? '#fde68a' : '#e5e7eb';

          return (
            <div key={item.id} style={{borderBottom: idx < pagedQueue.length-1 ? `1px solid ${borderColor}` : 'none'}}>

              {/* ── Compact row (always visible) ── */}
              <div
                onClick={() => setExpandedId(isSelected ? null : item.id)}
                style={{
                  display:'flex', alignItems:'center', gap:10, padding:'10px 14px',
                  background: rowBg, cursor:'pointer', userSelect:'none',
                  transition:'background 0.12s',
                  borderLeft: isSelected ? '3px solid #0ea5e9' : '3px solid transparent',
                }}
                onMouseEnter={e=>{ if(!isSelected) e.currentTarget.style.background='#f8fafc'; }}
                onMouseLeave={e=>{ e.currentTarget.style.background=rowBg; }}
              >
                {/* Critical pulsing badge */}
                {isCritical && (
                  <span style={{
                    fontSize:9,fontWeight:900,padding:'2px 6px',borderRadius:10,flexShrink:0,
                    background:'#be185d',color:'#fff',letterSpacing:'0.05em',
                    animation:'pulse 1.5s ease-in-out infinite',
                  }}>⚡ CRITICAL</span>
                )}

                {/* Urgency score dot */}
                <span title={`Urgency ${urgencyScore}/5`} style={{
                  flexShrink:0,width:8,height:8,borderRadius:'50%',
                  background: urgencyScore>=5?'#dc2626':urgencyScore>=4?'#f97316':urgencyScore>=3?'#eab308':urgencyScore>=2?'#6b7280':'#d1d5db',
                }}/>

                {/* Selection indicator */}
                <span style={{fontSize:10,color: isSelected ? '#0ea5e9' : '#9ca3af',flexShrink:0,width:12,textAlign:'center'}}>
                  {isSelected ? '▶' : '›'}
                </span>

                {/* Category badge + tag badges */}
                <div style={{flexShrink:0,display:'flex',gap:4,flexWrap:'nowrap',alignItems:'center',minWidth:0,maxWidth:160,overflow:'hidden'}}>
                  <Badge cat={item.category}>{fmtCatLabel(item.category)}</Badge>
                  {/* Tag badges (urgent-payment, overdue etc) — only if different from category */}
                  {(item.tags||[]).filter(t => t !== item.category).map(tag => (
                    <span key={tag} style={{
                      display:'inline-flex',alignItems:'center',fontSize:10,fontWeight:700,
                      padding:'2px 7px',borderRadius:20,flexShrink:0,whiteSpace:'nowrap',
                      background: tag==='urgent-payment'?'#fee2e2':tag==='overdue'?'#fff7ed':'#f3f4f6',
                      color: tag==='urgent-payment'?'#991b1b':tag==='overdue'?'#92400e':'#374151',
                      border: `1px solid ${tag==='urgent-payment'?'#fca5a5':tag==='overdue'?'#fde68a':'#e5e7eb'}`,
                    }}>
                      {tag==='urgent-payment'?'🔴 Urgent':tag==='overdue'?'⏰ Overdue':tag}
                    </span>
                  ))}
                </div>

                {/* Custom label chips */}
                {(item.customLabels||[]).map(lblId => {
                  const ldef = labels.find(l=>l.id===lblId) || { name: lblId, color:'#6366f1' };
                  return (
                    <span key={lblId} style={{
                      display:'inline-flex',alignItems:'center',gap:4,fontSize:10,fontWeight:700,
                      padding:'2px 7px',borderRadius:20,flexShrink:0,
                      background:ldef.color+'22',color:ldef.color,
                      border:`1px solid ${ldef.color}55`,
                    }}>
                      <span style={{width:5,height:5,borderRadius:'50%',background:ldef.color}}/>
                      {ldef.name}
                    </span>
                  );
                })}

                {/* Subject */}
                <div style={{flex:1,minWidth:0}}>
                  <div style={{
                    fontSize:13, fontWeight:600, color:'#1f2937',
                    overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap',
                  }}>
                    {isDupe && <span style={{marginRight:5,fontSize:11}}>⚠️</span>}
                    {isUrgent && <span style={{marginRight:5,fontSize:11}}>🔴</span>}
                    {item.subject}
                  </div>
                  <div style={{fontSize:11,color:'#9ca3af',marginTop:1,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>
                    {item.supplierName || item.fromName || item.from}
                    {item.invoiceRef && <span style={{marginLeft:8,color:'#6b7280'}}>#{item.invoiceRef}</span>}
                  </div>
                </div>

                {/* Amount */}
                <div style={{flexShrink:0,width:72,textAlign:'right',fontFamily:'var(--mono)',fontSize:12,fontWeight:600,color: item.invoiceAmount ? '#1f2937' : '#d1d5db'}}>
                  {item.invoiceAmount != null ? fmtAmt(item.invoiceAmount) : '—'}
                </div>

                {/* Confidence */}
                <div style={{flexShrink:0,width:44}}>
                  <ConfPill value={item.confidence}/>
                </div>

                {/* Date */}
                <div style={{flexShrink:0,width:68,fontSize:11,color:'#9ca3af',textAlign:'right'}}>
                  {fmtDate(item.emailDate || item.queuedAt)}
                </div>

                {/* Indicators */}
                <div style={{flexShrink:0,display:'flex',gap:4,width:60,justifyContent:'flex-end'}}>
                  {item.hasAttachments && <span title="Has attachment" style={{fontSize:12}}>📎</span>}
                  {acts.length > 0 && <span title={`${acts.length} action${acts.length>1?'s':''}`} style={{fontSize:10,background:'#e0f2fe',color:'#0369a1',borderRadius:10,padding:'1px 5px',fontWeight:700}}>{acts.length}</span>}
                </div>

                {/* Quick actions — stop propagation so row click doesn't toggle expand */}
                <div style={{flexShrink:0,display:'flex',gap:6}} onClick={e=>e.stopPropagation()}>
                  <button
                    onClick={() => handleApprove(item)}
                    disabled={busy===item.id}
                    title="Approve"
                    style={{
                      all:'unset', cursor: busy===item.id ? 'wait' : 'pointer',
                      padding:'5px 12px', borderRadius:6, fontSize:12, fontWeight:700,
                      background:'#16a34a', color:'#fff', display:'flex', alignItems:'center', gap:4,
                      opacity: busy===item.id ? 0.6 : 1,
                    }}
                    onMouseEnter={e=>{ if(busy!==item.id) e.currentTarget.style.background='#15803d'; }}
                    onMouseLeave={e=>{ e.currentTarget.style.background='#16a34a'; }}
                  >
                    {busy===item.id ? <Icons.spin style={{width:12,height:12}}/> : '✓'}
                    {busy!==item.id && ' Approve'}
                  </button>
                  <button
                    onClick={() => setConfirming(item)}
                    title="Dismiss"
                    style={{
                      all:'unset', cursor:'pointer',
                      padding:'5px 8px', borderRadius:6, fontSize:12,
                      color:'#6b7280', border:'1px solid #e5e7eb', background:'#f9fafb',
                    }}
                    onMouseEnter={e=>{ e.currentTarget.style.background='#fee2e2'; e.currentTarget.style.color='#dc2626'; e.currentTarget.style.borderColor='#fca5a5'; }}
                    onMouseLeave={e=>{ e.currentTarget.style.background='#f9fafb'; e.currentTarget.style.color='#6b7280'; e.currentTarget.style.borderColor='#e5e7eb'; }}
                  >✕</button>
                </div>
              </div>
            </div>
          );
        })}

      </div>

      {/* ── Pagination ── */}
      {totalPages > 1 && (
        <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginTop:12,padding:'8px 4px'}}>
          <button
            onClick={()=>setPage(p=>Math.max(0,p-1))}
            disabled={page===0}
            style={{all:'unset',cursor:page===0?'default':'pointer',padding:'6px 16px',borderRadius:7,
              border:'1px solid #d1d5db',background:page===0?'#f3f4f6':'#fff',
              color:page===0?'#9ca3af':'#374151',fontSize:12,fontWeight:600,opacity:page===0?0.5:1}}
          >← Prev</button>
          <span style={{fontSize:12,color:'#6b7280'}}>
            Page {page+1} of {totalPages} &nbsp;&middot;&nbsp; {sortedQueue.length} items
          </span>
          <button
            onClick={()=>setPage(p=>Math.min(totalPages-1,p+1))}
            disabled={page===totalPages-1}
            style={{all:'unset',cursor:page===totalPages-1?'default':'pointer',padding:'6px 16px',borderRadius:7,
              border:'1px solid #d1d5db',background:page===totalPages-1?'#f3f4f6':'#0d9488',
              color:page===totalPages-1?'#9ca3af':'#fff',fontSize:12,fontWeight:600,opacity:page===totalPages-1?0.5:1}}
          >Next →</button>
        </div>
      )}

    </div> {/* end left column */}

    {/* ── RIGHT: reading pane ── */}
    <div style={{
      flex: '0 0 48%',
      borderLeft: '1px solid #e5e7eb',
      background: '#fff',
      display: 'flex',
      flexDirection: 'column',
      overflow: 'hidden',
      position: 'sticky',
      top: 0,
      height: '100vh',
      maxHeight: '100vh',
    }}>
      {!selectedItem ? (
        <div style={{
          flex:1, display:'flex', flexDirection:'column',
          alignItems:'center', justifyContent:'center',
          color:'#d1d5db', padding:40, textAlign:'center', height:'100%',
        }}>
          <div style={{fontSize:52,marginBottom:16}}>📧</div>
          <div style={{fontSize:15,fontWeight:600,color:'#9ca3af',marginBottom:6}}>No email selected</div>
          <div style={{fontSize:13,color:'#d1d5db'}}>Click any row in the queue to read it here</div>
        </div>
      ) : (() => {
        const item = selectedItem;
        const isCrit = !!item.isCritical;
        const acts = getActions(item);

        const updateAct = (i, patch) => {
          const next = acts.map((a, idx2) => idx2 === i ? {...a, ...patch} : a);
          setActions(item, next);
          api.post('/api/review/update-actions', { id: item.id, actions: next }).catch(()=>{});
        };
        const deleteAct = (i) => {
          const next = acts.filter((_, idx2) => idx2 !== i);
          setActions(item, next);
          api.post('/api/review/update-actions', { id: item.id, actions: next }).catch(()=>{});
        };

        return (
          <div style={{display:'flex',flexDirection:'column',height:'100%',overflow:'hidden'}}>

            {/* Pane header — fixed */}
            <div style={{
              padding:'14px 18px 12px',
              borderBottom:'1px solid #e5e7eb',
              background: isCrit ? '#fdf2f8' : '#f8fafc',
              flexShrink:0,
            }}>
              {isCrit && (
                <div style={{display:'flex',alignItems:'center',gap:6,marginBottom:8,padding:'6px 10px',background:'#be185d',borderRadius:6}}>
                  <span style={{fontSize:13}}>⚡</span>
                  <span style={{fontSize:11,fontWeight:800,color:'#fff',letterSpacing:'0.04em'}}>CRITICAL — Internal Invoice Raise Request</span>
                </div>
              )}
              <div style={{display:'flex',gap:5,flexWrap:'wrap',marginBottom:7,alignItems:'center'}}>
                <Badge cat={item.category}>{fmtCatLabel(item.category)}</Badge>
                {(item.tags||[]).filter(t=>t!==item.category).map(tag=>(
                  <span key={tag} style={{
                    display:'inline-flex',alignItems:'center',fontSize:10,fontWeight:700,
                    padding:'2px 7px',borderRadius:20,whiteSpace:'nowrap',
                    background:tag==='urgent-payment'?'#fee2e2':tag==='overdue'?'#fff7ed':'#f3f4f6',
                    color:tag==='urgent-payment'?'#991b1b':tag==='overdue'?'#92400e':'#374151',
                    border:`1px solid ${tag==='urgent-payment'?'#fca5a5':tag==='overdue'?'#fde68a':'#e5e7eb'}`,
                  }}>{tag==='urgent-payment'?'🔴 Urgent':tag==='overdue'?'⏰ Overdue':tag}</span>
                ))}
                {(item.customLabels||[]).map(lblId=>{
                  const ldef=labels.find(l=>l.id===lblId)||{name:lblId,color:'#6366f1'};
                  return(<span key={lblId} style={{display:'inline-flex',alignItems:'center',gap:4,fontSize:10,fontWeight:700,padding:'2px 7px',borderRadius:20,background:ldef.color+'22',color:ldef.color,border:`1px solid ${ldef.color}55`}}><span style={{width:5,height:5,borderRadius:'50%',background:ldef.color}}/>{ldef.name}</span>);
                })}
                <ConfPill value={item.confidence}/>
                {item.urgencyScore && (
                  <span style={{fontSize:10,fontWeight:700,padding:'2px 7px',borderRadius:10,
                    background:item.urgencyScore>=5?'#fee2e2':item.urgencyScore>=4?'#fff7ed':'#fefce8',
                    color:item.urgencyScore>=5?'#991b1b':item.urgencyScore>=4?'#92400e':'#854d0e',
                  }}>Priority {item.urgencyScore}/5</span>
                )}
                <span style={{marginLeft:'auto',fontSize:11,color:'#9ca3af',flexShrink:0}}>{fmtDate(item.emailDate||item.queuedAt)}</span>
              </div>
              <div style={{fontSize:14,fontWeight:700,color:'#0f172a',lineHeight:1.35,marginBottom:6}}>{item.subject}</div>
              <div style={{fontSize:12,color:'#6b7280',display:'flex',gap:10,flexWrap:'wrap',alignItems:'center'}}>
                <span>From: <strong style={{color:'#374151'}}>{item.fromName||item.from}</strong> &lt;{item.fromEmail}&gt;</span>
                {item.supplierName && item.supplierName !== (item.fromName||item.from) && <span>· <strong style={{color:'#374151'}}>{item.supplierName}</strong></span>}
                {item.invoiceRef && <span>· Ref: <strong style={{color:'#374151',fontFamily:'var(--mono)'}}>{item.invoiceRef}</strong></span>}
                {item.invoiceAmount != null && <span>· <strong style={{color:'#1f2937'}}>{fmtAmt(item.invoiceAmount)}</strong></span>}
              </div>

              {item.webLink && (
                <div style={{marginTop:8,display:'flex',gap:8,flexWrap:'wrap',alignItems:'center'}}>
                  <a href={item.webLink} target="_blank" rel="noreferrer" style={{
                    cursor:'pointer',fontSize:12,fontWeight:600,textDecoration:'none',
                    color:'#0d9488',display:'inline-flex',alignItems:'center',gap:5,
                    padding:'4px 10px',borderRadius:6,border:'1px solid #ccfbf1',background:'#f0fdfa',
                  }}>📧 Open in Outlook ↗</a>
                </div>
              )}
            </div>

            {/* Scrollable content area — full body, no height cap */}
            <div style={{flex:1,overflowY:'auto',padding:'16px 18px'}}>

              {/* AI reason */}
              {item.classificationReason && (
                <div style={{fontSize:12,color:'#4b5563',background:'#f0f9ff',border:'1px solid #bae6fd',borderRadius:6,padding:'7px 10px',marginBottom:12,fontStyle:'italic'}}>
                  🧠 {item.classificationReason}
                </div>
              )}

              {/* Email body — scrollable fixed window, HTML-rendered */}
              {(item.body || item.snippet) && (
                <div style={{marginBottom:16}}>
                  <div style={{fontSize:10,fontWeight:700,textTransform:'uppercase',letterSpacing:'0.06em',color:'#9ca3af',marginBottom:6}}>Email Body</div>
                  <div style={{
                    border:'1px solid #e5e7eb',borderRadius:7,overflow:'hidden',
                    height:380,position:'relative',
                  }}>
                    {(() => {
                      const body = item.body || item.snippet || '';
                      const isHtml = /<html|<body|<div|<p|<table|<br/i.test(body);
                      if (isHtml) {
                        const htmlDoc = `<!DOCTYPE html><html><head><meta charset="utf-8"><style>
                          body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;font-size:13px;line-height:1.6;color:#1f2937;padding:12px 16px;margin:0;}
                          img{max-width:100%;height:auto;}
                          a{color:#0d9488;}
                          table{border-collapse:collapse;width:100%;}
                          td,th{padding:4px 8px;border:1px solid #e5e7eb;}
                        </style></head><body>${body}</body></html>`;
                        return <iframe srcDoc={htmlDoc} sandbox="allow-same-origin"
                          style={{width:'100%',height:'100%',border:'none',display:'block'}}
                          title="Email body"
                        />;
                      }
                      return (
                        <div style={{
                          height:'100%',overflowY:'auto',padding:'12px 16px',
                          fontSize:13,color:'#1f2937',lineHeight:1.65,
                          whiteSpace:'pre-wrap',wordBreak:'break-word',fontFamily:'inherit',
                          background:'#fff',
                        }}>{body}</div>
                      );
                    })()}
                  </div>
                </div>
              )}

              {/* Duplicate warning */}
              {item.isDuplicate && (
                <div style={{background:'#fef2f2',border:'1px solid #fca5a5',borderRadius:6,padding:'8px 12px',marginBottom:12,fontSize:12,color:'#991b1b',display:'flex',alignItems:'flex-start',gap:6}}>
                  <span>⚠️</span>
                  <div><strong>Possible duplicate</strong> — {item.duplicateReason||'Similar invoice already processed'}
                    {item.duplicateMatchId&&<DuplicateThread matchId={item.duplicateMatchId} currentItemId={item.id}/>}
                  </div>
                </div>
              )}

              {/* Related doc */}
              {item.isRelated && !item.isDuplicate && (
                <div style={{background:'#e6f7f6',border:'1px solid #40c2bb',borderRadius:6,padding:'8px 12px',marginBottom:12,fontSize:12,color:'#00263a'}}>
                  <div style={{fontWeight:700,marginBottom:4}}>📎 Related document</div>
                  {item.relatedSubject && <div style={{marginBottom:6,fontWeight:600}}>{item.relatedSubject}</div>}
                  {item.relatedWebLink && (
                    <a href={item.relatedWebLink} target="_blank" rel="noreferrer"
                      style={{fontSize:11,padding:'3px 8px',borderRadius:4,border:'1px solid #40c2bb',background:'#fff',color:'#00263a',cursor:'pointer',textDecoration:'none'}}>Open related in Outlook ↗</a>
                  )}
                </div>
              )}

              {/* ── ACTIONS SECTION ── */}
              <ItemActions
                item={item}
                acts={acts}
                setActions={setActions}
                pushToast={pushToast}
                KNOWN_FOLDERS={KNOWN_FOLDERS}
              />

            </div>{/* end scrollable */}

            {/* Sticky footer */}
            <div style={{
              padding:'12px 18px',borderTop:'1px solid #e5e7eb',
              background:'#f8fafc',flexShrink:0,
              display:'flex',gap:8,flexWrap:'wrap',alignItems:'center',
            }}>
              <button className="btn-approve" onClick={()=>handleApprove(item)} disabled={busy===item.id}>
                {busy===item.id?<Icons.spin style={{width:13,height:13}}/>:<Icons.check style={{width:13,height:13}}/>} Approve
              </button>
              <button className="btn-override" onClick={()=>{setOverriding(item);setOverrideCat(item.category);}}>
                <Icons.edit style={{width:12,height:12}}/> Override
              </button>
              <button
                onClick={()=>{setRelabeling(item);setRelabelCat(item.category);}}
                style={{
                  all:'unset', cursor:'pointer', fontSize:12, fontWeight:600,
                  padding:'6px 12px', borderRadius:6, display:'flex', alignItems:'center', gap:5,
                  background:'#f0f9ff', color:'#0369a1', border:'1px solid #bae6fd',
                }}
                onMouseEnter={e=>{e.currentTarget.style.background='#e0f2fe';}}
                onMouseLeave={e=>{e.currentTarget.style.background='#f0f9ff';}}
                title="Change category label without approving"
              >🏷️ Relabel</button>
              <button className="btn-dismiss" onClick={()=>setConfirming(item)}>
                <Icons.trash style={{width:12,height:12}}/> Dismiss
              </button>
              <button onClick={()=>setExpandedId(null)}
                style={{all:'unset',cursor:'pointer',marginLeft:'auto',fontSize:12,color:'#9ca3af',padding:'5px 10px',borderRadius:6,border:'1px solid #e5e7eb'}}>
                ✕ Close
              </button>
            </div>
          </div>
        );
      })()}
    </div>{/* end right pane */}

    {/* Modals */}
    {overriding && (
      <Modal title="Override Category" onClose={() => setOverriding(null)}>
        <div style={{padding:'16px 24px'}}>
          <p style={{margin:'0 0 12px',fontSize:13,color:'#374151'}}>
            Change category for: <strong>{overriding.subject}</strong>
          </p>
          <select value={overrideCat} onChange={e=>setOverrideCat(e.target.value)}
            style={{width:'100%',padding:'8px 10px',borderRadius:6,border:'1px solid #d1d5db',fontSize:13,marginBottom:16}}>
            {['invoice','statement','docket','urgent-payment','supplier-query',
              'route-fleet','route-estimator','route-hr','route-other','noise'].map(c => (
              <option key={c} value={c}>{fmtCatLabel(c)}</option>
            ))}
          </select>
          <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}>
            <button onClick={()=>setOverriding(null)} className="btn-ghost">Cancel</button>
            <button onClick={()=>handleOverride(overriding)} className="btn-primary">Apply Override</button>
          </div>
        </div>
      </Modal>
    )}
    {confirming && (
      <ConfirmDialog
        title="Dismiss this item?"
        body="It will be removed from the queue and marked as dismissed."
        confirmLabel="Yes, dismiss"
        danger
        onCancel={() => setConfirming(null)}
        onConfirm={() => handleDismiss(confirming)}
      />
    )}
    {relabeling && (
      <Modal title="Relabel Category" onClose={() => setRelabeling(null)}>
        <div style={{padding:'16px 24px'}}>
          <p style={{margin:'0 0 4px',fontSize:13,color:'#374151'}}>
            Change category for: <strong>{relabeling.subject}</strong>
          </p>
          <p style={{margin:'0 0 12px',fontSize:12,color:'#6b7280'}}>
            The item stays in the queue at 100% confidence with the new label.
          </p>
          <select value={relabelCat} onChange={e=>setRelabelCat(e.target.value)}
            style={{width:'100%',padding:'8px 10px',borderRadius:6,border:'1px solid #d1d5db',fontSize:13,marginBottom:16}}>
            {['invoice','statement','docket','urgent-payment','supplier-query',
              'route-fleet','route-estimator','route-hr','route-other','noise'].map(c => (
              <option key={c} value={c}>{fmtCatLabel(c)}</option>
            ))}
          </select>
          <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}>
            <button onClick={()=>setRelabeling(null)} className="btn-ghost">Cancel</button>
            <button
              onClick={()=>handleRelabelItem(relabeling)}
              disabled={busy===relabeling.id}
              style={{all:'unset',cursor:'pointer',padding:'7px 16px',borderRadius:6,fontSize:13,fontWeight:700,
                background:'#0369a1',color:'#fff',display:'inline-flex',alignItems:'center',gap:6,
                opacity:busy===relabeling.id?0.6:1}}
            >
              {busy===relabeling.id?<Icons.spin style={{width:12,height:12}}/>:null}
              Apply Relabel
            </button>
          </div>
        </div>
      </Modal>
    )}
    </div>{/* end split wrapper */}
    </>
  );
}


// ── Processed View ────────────────────────────────────────────────────────────

Object.assign(window, { ReviewQueueView });