// Person detail — compact row layout
// Rule: operator must OPEN the profile before Verify is enabled.
// Adjust = just edit the handle. Add = type a handle into an empty row.

const { useState: useStateV, useEffect: useEffectV, useMemo: useMemoV } = React;

function PersonDetail({ person, queue, onSelect, onUpdate, onDelete, onUpdateProfile, onUpdateNote, onClose, onNextPerson, onPrevPerson, onToast, onSave, locks = {}, currentUser, usersMap = {} }) {
  const counts = computeCounts(person, PLATFORMS);
  const profCounts = computeProfileCounts(person);

  // Use predefined category list
  const categorySuggestions = CATEGORIES;

  const setProfileStatus = (key, newStatus, mergedValue = null) => {
    onUpdateProfile(person.id, key, (cur) => {
      // Use provided mergedValue, or local edited value if available, otherwise use current merged value
      const localValue = mergedValue !== null ? mergedValue : getLocalProfileValue(key, undefined);
      const merged = localValue !== undefined ? localValue : cur.merged;
      
      const updated = { ...cur, status: newStatus };
      if (localValue !== undefined) {
        updated.merged = localValue;
      }
      if (newStatus === 'verified') {
        updated.verified_by = currentUser?.id || null;
      } else if (newStatus !== 'qc') {
        updated.verified_by = null;
      }
      return updated;
    });
    clearLocalProfileValue(key);
    onToast(`${key === 'country' ? 'Country' : 'Category'} → ${STATUS_META[newStatus].label}`);
  };

  // Wrapper to confirm reset of QC'd items
  const resetProfileWithWarning = (key) => {
    const profile = person.profile?.[key];
    if (profile?.status === 'qc') {
      if (!window.confirm(`This item has passed QC. Are you sure you want to reset it to unverified?`)) {
        return;
      }
    }
    // Reset to the MC (panel) value
    const panelValue = profile?.panel || '';
    setLocalProfileValue(key, panelValue);
    setProfileStatus(key, 'unverified', panelValue);
  };

  // Wrapper to confirm reset of QC'd handles
  const resetHandleWithWarning = (platformId, handleIndex) => {
    const handles = person.handles[platformId];
    const h = Array.isArray(handles) ? handles[handleIndex] : handles;
    if (h?.status === 'qc') {
      if (!window.confirm(`This handle has passed QC. Are you sure you want to reset it to unverified?`)) {
        return;
      }
    }
    setStatus(platformId, handleIndex, 'unverified');
  };
  const updateProfileMerged = (key, v) => {
    onUpdateProfile(person.id, key, (cur) => {
      const newProfile = { ...cur, merged: v };
      
      // Auto-set to trusted if tool, mc, and selected all match
      const { sports: tool, panel: mc } = newProfile;
      const selected = v;
      
      if (tool && mc && selected && tool === mc && mc === selected) {
        newProfile.status = 'trusted';
      } else if (cur.status === 'trusted' && !(tool === mc && mc === selected)) {
        // If it was trusted but values no longer match, reset to unverified
        newProfile.status = 'unverified';
      } else if (cur.status === 'qc' || cur.status === 'verified') {
        // Reset verified/qc to unverified when merged value changes
        newProfile.status = 'unverified';
      }
      
      return newProfile;
    });
  };
  const [opened, setOpened] = useStateV(() => {
    try { return JSON.parse(sessionStorage.getItem('shqt_opened') || '{}'); }
    catch { return {}; }
  });
  useEffectV(() => { sessionStorage.setItem('shqt_opened', JSON.stringify(opened)); }, [opened]);

  const openKey = (pid, plid, handleIndex, handle) => `${pid}:${plid}:${handleIndex}:${handle}`;
  const isOpened = (pl, handleIndex) => {
    const handles = person.handles[pl.id];
    const h = Array.isArray(handles) ? handles[handleIndex] : handles;
    return !!opened[openKey(person.id, pl.id, handleIndex, h?.merged || '')];
  };
  const markOpened = (pl, handleIndex) => {
    const handles = person.handles[pl.id];
    const h = Array.isArray(handles) ? handles[handleIndex] : handles;
    setOpened(o => ({ ...o, [openKey(person.id, pl.id, handleIndex, h?.merged || '')]: Date.now() }));
  };

  // "Searched" state for EMPTY rows — operator must run a platform search
  // for the person before confirming there's no account on that platform.
  // Keyed per (person, platform) since the handle itself is empty.
  const [searched, setSearched] = useStateV(() => {
    try { return JSON.parse(sessionStorage.getItem('shqt_searched') || '{}'); }
    catch { return {}; }
  });
  useEffectV(() => { sessionStorage.setItem('shqt_searched', JSON.stringify(searched)); }, [searched]);
  const searchKey = (pid, plid, handleIndex = 0) => `${pid}:${plid}:${handleIndex}`;
  const isSearched = (pl, handleIndex = 0) => !!searched[searchKey(person.id, pl.id, handleIndex)];
  const markSearched = (pl, handleIndex = 0) => setSearched(s => ({ ...s, [searchKey(person.id, pl.id, handleIndex)]: Date.now() }));
  const clearSearched = (pl, handleIndex = 0) => setSearched(s => {
    const n = { ...s }; delete n[searchKey(person.id, pl.id, handleIndex)]; return n;
  });

  const [selectedPlatformForAdd, setSelectedPlatformForAdd] = useStateV(null);

  // Local state for handle text inputs — to avoid API calls while typing
  const [localHandleEdits, setLocalHandleEdits] = useStateV({});
  const getLocalHandle = (platformId, handleIndex, defaultValue) => {
    const key = `${person.id}:${platformId}:${handleIndex}`;
    return localHandleEdits.hasOwnProperty(key) ? localHandleEdits[key] : defaultValue;
  };
  const setLocalHandle = (platformId, handleIndex, value) => {
    const key = `${person.id}:${platformId}:${handleIndex}`;
    setLocalHandleEdits(s => {
      const n = { ...s };
      if (value === undefined) {
        delete n[key];
      } else {
        n[key] = value;
      }
      return n;
    });
  };

  // Local state for profile attribute edits (country/category) — to avoid API calls while changing
  const [localProfileEdits, setLocalProfileEdits] = useStateV({});
  const getLocalProfileValue = (key, defaultValue) => {
    const editKey = `${person.id}:${key}`;
    return localProfileEdits.hasOwnProperty(editKey) ? localProfileEdits[editKey] : defaultValue;
  };
  const setLocalProfileValue = (key, value) => {
    const editKey = `${person.id}:${key}`;
    setLocalProfileEdits(s => {
      const n = { ...s };
      if (value === undefined) {
        delete n[editKey];
      } else {
        n[editKey] = value;
      }
      return n;
    });
  };
  const clearLocalProfileValue = (key) => {
    setLocalProfileValue(key, undefined);
  };

  // Extract handle from pasted URL based on platform
  const extractHandleFromUrl = (url, platformId) => {
    try {
      const urlObj = new URL(url);
      const hostname = urlObj.hostname.replace('www.', '');
      const pathname = urlObj.pathname;

      // Platform-specific extraction logic
      switch (platformId) {
        case 'instagram':
        case 'x':
        case 'facebook':
        case 'twitch':
          // Extract last path segment
          return pathname.split('/').filter(p => p).pop() || '';
        case 'youtube':
        case 'tiktok':
          // Extract handle after @
          const match = pathname.match(/@([^/?]+)/);
          return match ? match[1] : pathname.split('/').filter(p => p).pop() || '';
        default:
          return '';
      }
    } catch {
      // Not a valid URL, return as-is
      return '';
    }
  };

  useEffectV(() => {
    const handler = (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      if (e.key === 'Escape') onClose();
      else if (e.key === ']') onNextPerson();
      else if (e.key === '[') onPrevPerson();
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  });

  const setStatus = (platformId, handleIndex, newStatus) => {
    onUpdate(person.id, platformId, handleIndex, (h) => {
      // Get the local merged value if it was edited
      const localMerged = getLocalHandle(platformId, handleIndex, undefined);
      const mergedValue = localMerged !== undefined ? localMerged : h.merged;
      
      const updated = { ...h, status: newStatus };
      // Update merged value if there's a local edit
      if (localMerged !== undefined) {
        updated.merged = localMerged;
      }
      
      if (newStatus === 'verified') {
        updated.verified_by = currentUser?.id || null;
      } else if (newStatus !== 'qc') {
        // Clear verified_by when resetting to unverified/missing, but keep it for QC
        updated.verified_by = null;
      }
      return updated;
    });
    onToast(`${PLATFORMS.find(p=>p.id===platformId).name} #${handleIndex + 1} → ${STATUS_META[newStatus].label}`);
    // Clear local edit after API call
    setLocalHandle(platformId, handleIndex, undefined);
  };

  const addHandle = (platformId) => {
    // Create a new empty handle for this platform
    const newHandle = {
      sports: '',
      panel: '',
      merged: '',
      status: 'missing',
    };
    // Call onUpdate with handleIndex pointing to a new position
    const handles = person.handles[platformId];
    const nextIndex = Array.isArray(handles) ? handles.length : 1;
    
    // Initialize the new handle using the onUpdate callback pattern
    onUpdate(person.id, platformId, nextIndex, () => newHandle);
    onToast(`Added new ${PLATFORMS.find(p=>p.id===platformId).name} handle`);
    setSelectedPlatformForAdd(null);
  };
  // Check if a handle already exists for this platform (case-insensitive)
  const checkDuplicateHandle = (platformId, handleValue, currentHandleIndex) => {
    const handles = person.handles[platformId];
    const handlesArray = Array.isArray(handles) ? handles : [handles];
    const lowerValue = handleValue.toLowerCase();
    
    for (let i = 0; i < handlesArray.length; i++) {
      if (i === currentHandleIndex) continue; // Skip current handle
      const existingHandle = handlesArray[i];
      if (existingHandle.merged && existingHandle.merged.toLowerCase() === lowerValue) {
        return true; // Duplicate found
      }
    }
    return false; // No duplicate
  };  const updateMerged = (platformId, handleIndex, v) => {
    // Only update local state, don't call API
    setLocalHandle(platformId, handleIndex, v);
    // Reset open state when typing
    setOpened(o => {
      const n = {...o};
      Object.keys(n).forEach(k => { if (k.startsWith(`${person.id}:${platformId}:${handleIndex}:`)) delete n[k]; });
      return n;
    });
    // typing a handle invalidates any "searched (no account)" verification
    if (v) clearSearched({ id: platformId }, handleIndex);
  };

  const pct = counts.qc / counts.total;

  return (
    <div className="detail">
      {/* LEFT: queue */}
      <aside className="queue">
        <div className="queue-head">
          <div className="q-title"><Icon name="inbox" size={14}/> Queue <Pill kind="neutral">{queue.length}</Pill></div>
          <div className="q-sub">People with work pending.</div>
        </div>
        <div className="queue-list">
          {queue.map(q => {
            const c = computeCounts(q, PLATFORMS);
            const active = q.id === person.id;
            const o = overallStatus(c);
            return (
              <div key={q.id} className={`queue-row ${active ? 'active' : ''}`} onClick={() => onSelect(q.id)}>
                <div className="qr-name">
                  <div className="nmavatar" style={{width: 22, height: 22, fontSize: 10}}>{q.name.split(' ').map(w=>w[0]).slice(0,2).join('')}</div>
                  <span style={{flex: 1}}>{q.name}</span>
                  {locks[q.id] && <LockChip lock={locks[q.id]} size={16}/>}
                  <Pill kind={o.kind}>{o.label}</Pill>
                </div>
                <div className="qr-tiles">
                  {PLATFORMS.map(pl => {
                    const handles = q.handles[pl.id];
                    const displayHandle = Array.isArray(handles) ? getMostAdvancedStatus(handles) : handles;
                    return (
                      <Tile 
                        key={pl.id} 
                        platform={pl.id} 
                        status={displayHandle.status}
                        title={Array.isArray(handles) && handles.length > 1 ? `${handles.length} handles` : undefined}
                      />
                    );
                  })}
                </div>
                <div className="qr-meta"><span>{q.category}</span> · <span>{q.country}</span> · <span>{c.qc}/{c.total}</span></div>
              </div>
            );
          })}
        </div>
      </aside>

      {/* RIGHT: verification */}
      <section className="verify">
        <div className="verify-head">
          <div style={{display: 'flex', alignItems: 'center', gap: 10}}>
            <button className="btn ghost sm" onClick={onClose}><Icon name="chevL" size={13}/> All records</button>
            <div style={{flex: 1}}/>
            <button className="btn sm" onClick={onPrevPerson} title="Previous ([)"><Icon name="chevL" size={13}/></button>
            <button className="btn sm" onClick={onNextPerson} title="Next (])">Next <Icon name="chevR" size={13}/></button>
          </div>
          <h1 className="vh-name">
            <div className="nmavatar" style={{width: 34, height: 34, fontSize: 13}}>{person.name.split(' ').map(w=>w[0]).slice(0,2).join('')}</div>
            {person.name}
            <Pill kind={overallStatus(counts).kind} dot>{overallStatus(counts).label}</Pill>
          </h1>
          <div className="vh-meta">
            <span>{person.category}{person.profile?.category?.status === 'qc' && <span title="QC passed" style={{color:'var(--ok)', marginLeft:4}}>✓</span>}</span>
            <span>{person.country}{person.profile?.country?.status === 'qc' && <span title="QC passed" style={{color:'var(--ok)', marginLeft:4}}>✓</span>}</span>
            <span>from {person.source}</span>
            <span>{counts.qc} of {counts.total} handles · {profCounts.qc} of {profCounts.total} attributes</span>
          </div>
        </div>

        <div className="verify-body compact">
          {/* === Profile attributes === */}
          <div className="section-label">
            <Icon name="user" size={12}/> Profile
            <span className="section-hint">Confirm country and category — sources sometimes disagree.</span>
            <span className="section-progress">{profCounts.qc}/{profCounts.total} QC</span>
          </div>

          {/* Column header (shared with platforms below) */}
          <div className="prow head">
            <div className="prow-pl">Attribute</div>
            <div className="prow-src">{person.source === 'CultureNet' ? 'CultureNet' : 'SportsNet'}</div>
            <div className="prow-src">MC Info</div>
            <div className="prow-handle">Value used</div>
            <div className="prow-actions">Action</div>
          </div>

          {/* --- Country row --- */}
          {(() => {
            const c = person.profile?.country;
            if (!c) return null;
            const sportsHas = !!c.sports;
            const panelHas  = !!c.panel;
            const mismatch = sportsHas && panelHas && c.sports !== c.panel;
            const partial = (sportsHas || panelHas) && !(sportsHas && panelHas);
            const done = c.status === 'qc' || c.status === 'trusted';
            return (
              <div className={`prow attr ${c.status} ${done ? 'done' : ''}`}>
                <div className="prow-pl">
                  <div className="attr-icon" aria-hidden="true">🌐</div>
                  <div style={{display:'flex', flexDirection:'column', minWidth:0}}>
                    <span className="pl-name">Country</span>
                    <span className="pl-stat">
                      {c.status === 'qc' && '✓✓ QC passed'}
                      {c.status === 'verified' && '✓ Verified'}
                      {c.status === 'trusted' && 'Trusted'}
                      {c.status === 'unverified' && (mismatch ? 'Sources disagree' : 'Needs review')}
                    </span>
                  </div>
                </div>
                <div className={`prow-src ${mismatch ? 'mm' : partial ? 'partial' : ''}`}>
                  {sportsHas ? <span className="mono">{c.sports}</span> : <span className="none">—</span>}
                </div>
                <div className={`prow-src ${mismatch ? 'mm' : partial ? 'partial' : ''}`}>
                  {panelHas ? <span className="mono">{c.panel}</span> : <span className="none">—</span>}
                </div>
                <div className="prow-handle">
                  <div className="handle-input">
                    <select
                      className="attr-select"
                      value={getLocalProfileValue('country', c.merged || '')}
                      onChange={(e) => setLocalProfileValue('country', e.target.value)}
                    >
                      <option value="">— select —</option>
                      {COUNTRIES.map(country => (
                        <option key={country} value={country}>{country}</option>
                      ))}
                    </select>
                    {sportsHas && c.sports !== getLocalProfileValue('country', c.merged || '') && (
                      <button className="chip-mini" onClick={() => setLocalProfileValue('country', c.sports)} title={`Use ${person.source === 'CultureNet' ? 'CultureNet' : 'SportsNet'}: ${c.sports}`}>S</button>
                    )}
                    {panelHas && c.panel !== getLocalProfileValue('country', c.merged || '') && (
                      <button className="chip-mini" onClick={() => setLocalProfileValue('country', c.panel)} title={`Use MC: ${c.panel}`}>MC</button>
                    )}
                  </div>
                  {c.note && <div className="attr-note">{c.note}</div>}
                </div>
                <div className="prow-actions">
                  {c._updating ? (
                    <button className="btn ghost sm" disabled>
                      <Icon name="clock" size={12}/> Updating...
                    </button>
                  ) : (() => {
                    const localValue = getLocalProfileValue('country', c.merged || '');
                    const hasLocalChange = localValue !== c.merged;
                    if (hasLocalChange) {
                      // If user changed the value locally, show Verify button
                      return (
                        <button
                          className="btn ok sm"
                          disabled={!localValue}
                          title={!localValue ? 'Pick a country first' : 'Confirm this is correct'}
                          onClick={() => setProfileStatus('country', 'verified')}
                        >
                          <Icon name="check" size={12}/> Verify
                        </button>
                      );
                    } else if (c.status === 'verified' || c.status === 'qc') {
                      // Original status if no local change
                      return (
                        <>
                          <button className="btn ghost sm" onClick={() => resetProfileWithWarning('country')}>Reset</button>
                          {c.status === 'verified' && (() => {
                            const selfVerified = c.verified_by && currentUser?.id && c.verified_by === currentUser.id;
                            return (
                              <button
                                className="btn ok sm"
                                disabled={!!selfVerified}
                                onClick={() => setProfileStatus('country', 'qc')}
                                title={selfVerified ? 'You verified this — a second reviewer must QC it' : 'Second-reviewer confirm'}
                              >
                                <Icon name="check" size={12}/> {selfVerified ? 'Need 2nd reviewer' : 'QC'}
                              </button>
                            );
                          })()}
                        </>
                      );
                    } else {
                      // Unverified state - show Verify
                      return (
                        <button
                          className={`btn ${c.status === 'trusted' ? 'neutral' : 'ok'} sm`}
                          disabled={!localValue}
                          title={c.status === 'trusted' 
                            ? 'Reset to allow manual verification' 
                            : (!localValue ? 'Pick a country first' : 'Confirm this is correct')}
                          onClick={() => setProfileStatus('country', c.status === 'trusted' ? 'unverified' : 'verified')}
                        >
                          <Icon name={c.status === 'trusted' ? 'refresh' : 'check'} size={12}/> 
                          {c.status === 'trusted' ? 'Reset' : 'Verify'}
                        </button>
                      );
                    }
                  })()}
                </div>
              </div>
            );
          })()}

          {/* --- Category row --- */}
          {(() => {
            const c = person.profile?.category;
            if (!c) return null;
            const sportsHas = !!c.sports;
            const panelHas  = !!c.panel;
            const mismatch = sportsHas && panelHas && c.sports !== c.panel;
            const partial = (sportsHas || panelHas) && !(sportsHas && panelHas);
            const done = c.status === 'qc' || c.status === 'trusted';
            return (
              <div className={`prow attr ${c.status} ${done ? 'done' : ''}`}>
                <div className="prow-pl">
                  <div className="attr-icon" aria-hidden="true"><Icon name="bolt" size={14} stroke="var(--accent)"/></div>
                  <div style={{display:'flex', flexDirection:'column', minWidth:0}}>
                    <span className="pl-name">Category</span>
                    <span className="pl-stat">
                      {c.status === 'qc' && '✓✓ QC passed'}
                      {c.status === 'verified' && '✓ Verified'}
                      {c.status === 'trusted' && 'Trusted'}
                      {c.status === 'unverified' && (mismatch ? 'Sources disagree' : 'Needs review')}
                    </span>
                  </div>
                </div>
                <div className={`prow-src ${mismatch ? 'mm' : partial ? 'partial' : ''}`}>
                  {sportsHas ? <span className="mono">{c.sports}</span> : <span className="none">—</span>}
                </div>
                <div className={`prow-src ${mismatch ? 'mm' : partial ? 'partial' : ''}`}>
                  {panelHas ? <span className="mono">{c.panel}</span> : <span className="none">—</span>}
                </div>
                <div className="prow-handle">
                  <div className="handle-input">
                    <select
                      className="attr-select"
                      value={getLocalProfileValue('category', c.merged || '')}
                      onChange={(e) => setLocalProfileValue('category', e.target.value)}
                    >
                      <option value="">— select —</option>
                      {CATEGORIES.map(category => (
                        <option key={category} value={category}>{category}</option>
                      ))}
                    </select>
                    {sportsHas && c.sports !== getLocalProfileValue('category', c.merged || '') && (
                      <button className="chip-mini" onClick={() => setLocalProfileValue('category', c.sports)} title={`Use ${person.source === 'CultureNet' ? 'CultureNet' : 'SportsNet'}: ${c.sports}`}>S</button>
                    )}
                    {panelHas && c.panel !== getLocalProfileValue('category', c.merged || '') && (
                      <button className="chip-mini" onClick={() => setLocalProfileValue('category', c.panel)} title={`Use MC: ${c.panel}`}>MC</button>
                    )}
                  </div>
                  {c.note && <div className="attr-note">{c.note}</div>}
                </div>
                <div className="prow-actions">
                  {c._updating ? (
                    <button className="btn ghost sm" disabled>
                      <Icon name="clock" size={12}/> Updating...
                    </button>
                  ) : (() => {
                    const localValue = getLocalProfileValue('category', c.merged || '');
                    const hasLocalChange = localValue !== c.merged;
                    if (hasLocalChange) {
                      // If user changed the value locally, show Verify button
                      return (
                        <button
                          className="btn ok sm"
                          disabled={!localValue}
                          title={!localValue ? 'Pick a category first' : 'Confirm this is correct'}
                          onClick={() => setProfileStatus('category', 'verified')}
                        >
                          <Icon name="check" size={12}/> Verify
                        </button>
                      );
                    } else if (c.status === 'verified' || c.status === 'qc') {
                      // Original status if no local change
                      return (
                        <>
                          <button className="btn ghost sm" onClick={() => resetProfileWithWarning('category')}>Reset</button>
                          {c.status === 'verified' && (() => {
                            const selfVerified = c.verified_by && currentUser?.id && c.verified_by === currentUser.id;
                            return (
                              <button
                                className="btn ok sm"
                                disabled={!!selfVerified}
                                onClick={() => setProfileStatus('category', 'qc')}
                                title={selfVerified ? 'You verified this — a second reviewer must QC it' : 'Second-reviewer confirm'}
                              >
                                <Icon name="check" size={12}/> {selfVerified ? 'Need 2nd reviewer' : 'QC'}
                              </button>
                            );
                          })()}
                        </>
                      );
                    } else {
                      // Unverified state - show Verify
                      return (
                        <button
                          className={`btn ${c.status === 'trusted' ? 'neutral' : 'ok'} sm`}
                          disabled={!localValue}
                          title={c.status === 'trusted' 
                            ? 'Reset to allow manual verification'
                            : (!localValue ? 'Pick a category first' : 'Confirm this is correct')}
                          onClick={() => setProfileStatus('category', c.status === 'trusted' ? 'unverified' : 'verified')}
                        >
                          <Icon name={c.status === 'trusted' ? 'refresh' : 'check'} size={12}/> 
                          {c.status === 'trusted' ? 'Reset' : 'Verify'}
                        </button>
                      );
                    }
                  })()}
                </div>
              </div>
            );
          })()}

          {/* === Platforms === */}
          <div className="section-label" style={{marginTop: 18}}>
            <Icon name="bolt" size={12}/> Social handles
            <span className="section-hint">Open each profile, then verify or QC.</span>
            <span className="section-progress">{counts.qc}/{counts.total} done</span>
          </div>

          {/* Column header */}
          <div className="prow head">
            <div className="prow-pl">Platform</div>
            <div className="prow-src">{person.source === 'CultureNet' ? 'CultureNet' : 'SportsNet'}</div>
            <div className="prow-src">MC Info</div>
            <div className="prow-handle">Handle used</div>
            <div className="prow-actions">Action</div>
          </div>

          {PLATFORMS.map((pl) => {
            const handles = person.handles[pl.id];
            const handlesArray = Array.isArray(handles) ? handles : [handles];
            
            return handlesArray.map((h, handleIndex) => {
                  const sportsHas = !!h.sports;
                  const panelHas  = !!h.panel;
                  const handleOpened = isOpened(pl, handleIndex);
                  const handleSearched = isSearched(pl, handleIndex);
                  const localMerged = getLocalHandle(pl.id, handleIndex, h.merged);
                  const isEmpty = !localMerged;
                  const isNewHandle = !sportsHas && !panelHas;
                  const canVerify = !!localMerged && (isNewHandle || handleOpened);
                  const canConfirmAbsent = isEmpty;
                  const url = localMerged ? `https://${URL_ROOT[pl.id]}${localMerged}` : '';
                  const searchUrl = buildSearchUrl(pl.id, person.name);
                  const mismatch = sportsHas && panelHas && h.sports.toLowerCase() !== h.panel.toLowerCase();
                  const partial = (sportsHas || panelHas) && !(sportsHas && panelHas);
                  const done = h.status === 'qc';
                  const isMultipleHandles = handlesArray.length > 1;
                  const isLastHandle = handleIndex === handlesArray.length - 1;

                  return (
                    <div key={`${pl.id}-${handleIndex}`} className={`prow ${h.status} ${done ? 'done' : ''}`}>
                  <div className="prow-pl">
                    <button
                      type="button"
                      className={`tile-toggle ${isEmpty ? 'off' : 'on'}`}
                      onClick={() => isEmpty ? (updateMerged(pl.id, handleIndex, ''), setStatus(pl.id, handleIndex, 'unverified')) : null}
                      title={isEmpty ? `Turn ${pl.name} back on` : 'Toggle disabled for verified handles'}
                      aria-pressed={!isEmpty}
                    >
                      <Tile platform={pl.id} status={h.status}/>
                    </button>
                    <div style={{display: 'flex', flexDirection: 'column', minWidth: 0}}>
                      <span className="pl-name">
                        {pl.name}{isMultipleHandles && ` #${handleIndex + 1}`}
                      </span>
                      <span className="pl-stat">
                        {h.status === 'qc' && '✓✓ QC passed'}
                        {h.status === 'verified' && (isEmpty ? '✓ No account · needs QC' : '✓ Verified')}
                        {h.status === 'unverified' && (isEmpty
                          ? (handleSearched ? 'Searched · confirm no account' : 'Empty — add handle or verify absent')
                          : 'Needs review')}
                        {h.status === 'missing' && (handleSearched ? 'Searched · confirm no account' : 'No data — add or verify absent')}
                      </span>
                    </div>
                  </div>

                  <div className={`prow-src ${mismatch ? 'mm' : partial ? 'partial' : ''}`}>
                    {sportsHas ? <span className="mono">{h.sports}</span> : <span className="none">—</span>}
                  </div>
                  <div className={`prow-src ${mismatch ? 'mm' : partial ? 'partial' : ''}`}>
                    {panelHas ? <span className="mono">{h.panel}</span> : <span className="none">—</span>}
                  </div>

                  <div className="prow-handle">
                    {isEmpty && !isNewHandle ? (
                      <span className="absent-note">
                        <Icon name="ban" size={11}/> No {pl.name} account · confirmed
                      </span>
                    ) : (
                      <div className="handle-input">
                        <span className="prefix">{URL_ROOT[pl.id]}</span>
                        <input
                          value={getLocalHandle(pl.id, handleIndex, h.merged || '')}
                          placeholder={isEmpty ? 'add handle, or verify absent →' : 'handle'}
                          onChange={(e) => updateMerged(pl.id, handleIndex, e.target.value)}
                          onPaste={(e) => {
                            e.preventDefault();
                            const pasted = e.clipboardData.getData('text');
                            const extracted = extractHandleFromUrl(pasted, pl.id);
                            const handle = extracted || pasted;
                            updateMerged(pl.id, handleIndex, handle);
                          }}
                        />
                        {sportsHas && h.sports !== getLocalHandle(pl.id, handleIndex, h.merged || '') && (
                          <button className="chip-mini" onClick={() => updateMerged(pl.id, handleIndex, h.sports)} title={`Use ${person.source === 'CultureNet' ? 'CultureNet' : 'SportsNet'} value`}>S</button>
                        )}
                        {panelHas && h.panel !== getLocalHandle(pl.id, handleIndex, h.merged || '') && (
                          <button className="chip-mini" onClick={() => updateMerged(pl.id, handleIndex, h.panel)} title="Use MC value">MC</button>
                        )}
                      </div>
                    )}
                  </div>

                  <div className="prow-actions">
                    {h._updating ? (
                      <button className="btn ghost sm" disabled>
                        <Icon name="clock" size={12}/> Updating...
                      </button>
                    ) : h.status === 'verified' || h.status === 'qc' ? (
                      <>
                        <button className="btn ghost sm" onClick={() => resetHandleWithWarning(pl.id, handleIndex)}>Reset</button>
                        {h.status === 'verified' && (() => {
                          const selfVerified = h.verified_by && currentUser?.id && h.verified_by === currentUser.id;
                          return (
                            <button
                              className="btn ok sm"
                              disabled={!!selfVerified}
                              onClick={() => setStatus(pl.id, handleIndex, 'qc')}
                              title={selfVerified ? 'You verified this — a second reviewer must QC it' : 'Second-reviewer confirm'}
                            >
                              <Icon name="check" size={12}/> {selfVerified ? 'Need 2nd reviewer' : 'QC'}
                            </button>
                          );
                        })()}
                        {localMerged && <a className="btn sm" href={url} target="_blank" rel="noreferrer"><Icon name="ext" size={11}/></a>}
                        {localMerged && <a className="btn sm" href={url} target="_blank" rel="noreferrer"><Icon name="ext" size={11}/></a>}
                      </>
                    ) : isEmpty ? (
                      /* Empty handle: prove absence via search, then confirm. */
                      <>
                        <a
                          className={`btn sm ${handleSearched ? '' : 'accent'}`}
                          href={searchUrl}
                          target="_blank"
                          rel="noreferrer"
                          onClick={() => markSearched(pl, handleIndex)}
                          title={`Search ${pl.name} for "${person.name}" to confirm no account exists`}
                        >
                          <Icon name="search" size={12}/> {handleSearched ? 'Re-search' : `Search ${pl.name}`}
                        </a>
                        <button
                          className="btn ok sm"
                          disabled={!canConfirmAbsent}
                          title={`Confirm: ${person.name} has no ${pl.name} account`}
                          onClick={() => { updateMerged(pl.id, handleIndex, ''); setStatus(pl.id, handleIndex, 'verified'); }}
                        >
                          <Icon name="check" size={12}/> No account
                        </button>
                      </>
                    ) : (
                      <>
                        <a className={`btn sm ${handleOpened ? '' : 'accent'}`}
                          href={url} target="_blank" rel="noreferrer"
                          onClick={() => markOpened(pl, handleIndex)}>
                          <Icon name="ext" size={12}/> {handleOpened ? 'Reopen' : 'Open'}
                        </a>
                        <button
                          className={`btn ok sm ${checkDuplicateHandle(pl.id, localMerged, handleIndex) ? 'disabled-action' : ''}`}
                          disabled={!canVerify || checkDuplicateHandle(pl.id, localMerged, handleIndex)}
                          title={checkDuplicateHandle(pl.id, localMerged, handleIndex)
                            ? `Cannot add: This ${pl.name} handle already exists for another entry`
                            : (isNewHandle 
                              ? 'Confirm this handle' 
                              : !handleOpened 
                                ? 'Open the profile to check it, then verify' 
                                : 'Confirm this is the right account')}
                          onClick={() => {
                            setStatus(pl.id, handleIndex, 'verified');
                          }}
                        >
                          <Icon name="check" size={12}/> Verify
                        </button>
                      </>
                    )}
                    {handleIndex > 0 && !sportsHas && !panelHas && (
                      <button
                        className="btn ghost sm"
                        onClick={() => onDelete(person.id, pl.id, handleIndex)}
                        title={`Delete this ${pl.name} handle`}
                      >
                        <Icon name="trash" size={12}/>
                      </button>
                    )}
                  </div>
                </div>
              );
            });
          })}

          <div style={{fontSize: 11, color: 'var(--muted)', padding: '10px 4px 2px', display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap'}}>
            <Icon name="ext" size={11}/> Open a profile to verify it.
            <span style={{color: 'var(--border-2)'}}>·</span>
            <span><Icon name="click" size={11}/> Click the <b>platform button</b> to the left for a quick way to say <b>"no account"</b>.</span>
            <span style={{color: 'var(--border-2)'}}>·</span>
            <span><b className="mono" style={{color:'var(--ink-2)'}}>S</b>/<b className="mono" style={{color:'var(--ink-2)'}}>MC</b> chips copy the source value into the handle field.</span>
            <span style={{color: 'var(--border-2)'}}>·</span>
            <span>Editing a handle resets its verification.</span>
          </div>

          {/* Add handle section at bottom */}
          <div style={{padding: '16px 0 0', borderTop: '1px solid var(--border)', marginTop: 16}}>
            <div style={{display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap', padding: '12px 10px'}}>
              <span style={{fontSize: 12, fontWeight: 500, color: 'var(--ink)'}}>Add another handle:</span>
              <select 
                value={selectedPlatformForAdd || ''}
                onChange={(e) => setSelectedPlatformForAdd(e.target.value)}
                style={{
                  padding: '6px 10px',
                  borderRadius: 5,
                  border: '1px solid var(--border)',
                  fontSize: 13,
                  cursor: 'pointer',
                  appearance: 'none',
                  paddingRight: 28,
                  background: `var(--surface) url("data:image/svg+xml,%3Csvg width='12' height='8' viewBox='0 0 12 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1L6 6L11 1' stroke='%2344403C' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 10px center`,
                  fontWeight: selectedPlatformForAdd ? 500 : 400,
                  color: selectedPlatformForAdd ? 'var(--ink)' : 'var(--muted)',
                  transition: 'border-color .1s ease, background-color .1s ease',
                }}
                onFocus={(e) => e.target.style.borderColor = 'var(--accent)'}
                onBlur={(e) => e.target.style.borderColor = 'var(--border)'}
              >
                <option value="" style={{color: 'var(--muted)'}}>Select platform</option>
                {PLATFORMS.map(pl => (
                  <option key={pl.id} value={pl.id} style={{color: 'var(--ink)'}}>{pl.name}</option>
                ))}
              </select>
              <button 
                className="btn sm accent"
                disabled={!selectedPlatformForAdd}
                onClick={() => addHandle(selectedPlatformForAdd)}
                title={selectedPlatformForAdd ? `Add another ${PLATFORMS.find(p=>p.id===selectedPlatformForAdd)?.name} handle` : 'Select a platform first'}
              >
                <Icon name="plus" size={12}/> Add
              </button>
            </div>
          </div>

          {/* Notes section */}
          <Notes 
            notes={person.meta?.notes || []}
            onAdd={(noteData) => onUpdateNote(person.id, 'add', noteData)}
            onEdit={(noteData) => onUpdateNote(person.id, 'edit', noteData)}
            onDelete={(noteData) => onUpdateNote(person.id, 'delete', noteData)}
            currentUser={currentUser}
            usersMap={usersMap}
          />
        </div>

        <div className="verify-foot">
          <div className="progress-inline">
            <span>{counts.qc}/{counts.total} done</span>
            <div className="bar"><span style={{width: `${pct*100}%`}}/></div>
            <span>{Math.round(pct * 100)}%</span>
          </div>
          <button className="btn" onClick={onPrevPerson}><Icon name="chevL" size={13}/> Prev</button>
          <button className="btn primary" onClick={onNextPerson}>Next person <Icon name="chevR" size={13}/></button>
        </div>
      </section>
    </div>
  );
}

window.PersonDetail = PersonDetail;
