// WTS Cyprus — TP: Study detail (running / review / complete), candidate drawer, run summary
// AI = enrichment (Detailed Business Description + evidence + rule-based criteria flags).
// Accept / Reject is a MANUAL analyst verdict with required reasoning.
const { useState: useStateTD, useMemo: useMemoTD, useEffect: useEffectTD, useRef: useRefTD } = React;

const VERDICT_FILTER_OPTS = [
  { value: 'all',      label: 'All' },
  { value: 'pending',  label: 'Pending' },
  { value: 'accept',   label: 'Accepted' },
  { value: 'reject',   label: 'Rejected' },
];
const FLAG_OPTS = [
  { code: 'independence', label: 'Independence', short: 'I' },
  { code: 'activity',     label: 'Activity',     short: 'A' },
  { code: 'geography',    label: 'Geography',    short: 'G' },
  { code: 'size',         label: 'Size',         short: 'S' },
];

const HighlightedDescription = ({ text, quotes }) => {
  if (!quotes || quotes.length === 0) return <>{text}</>;
  const clean = (s) => s.replace(/^"|"$/g, '').trim();
  const cleanQuotes = quotes.map(clean).filter(q => q.length > 8);
  const escaped = cleanQuotes.map(q => q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
  if (!escaped) return <>{text}</>;
  const re = new RegExp(`(${escaped})`, 'gi');
  return (
    <>{text.split(re).map((p, i) => cleanQuotes.some(q => p.toLowerCase() === q.toLowerCase())
      ? <mark key={i} className="wts-highlight">{p}</mark> : <React.Fragment key={i}>{p}</React.Fragment>)}</>
  );
};

const FlagDots = ({ flags }) => (
  <div className="wts-flag-dots">
    {FLAG_OPTS.map(opt => {
      const f = flags?.[opt.code];
      const cls = !f ? 'wts-flag-dot--na' : (f.pass ? 'wts-flag-dot--pass' : 'wts-flag-dot--fail');
      return (
        <Tooltip key={opt.code} content={f ? `${opt.label}: ${f.pass ? 'pass' : 'fail'}` : `${opt.label}: n/a`} side="top">
          <span className={cn('wts-flag-dot', cls)}>{opt.short}</span>
        </Tooltip>
      );
    })}
  </div>
);

const VerdictPill = ({ verdict }) => {
  const map = { accept: ['hsl(142 50% 94%)', 'hsl(142 55% 26%)', 'Accept'], reject: ['hsl(0 85% 96%)', 'hsl(0 72% 40%)', 'Reject'], pending: ['transparent', 'var(--muted-foreground)', 'Pending'] };
  const [bg, color, label] = map[verdict] || map.pending;
  return <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 9px', borderRadius: 6, fontSize: 11.5, fontWeight: 500, background: bg, color, border: verdict === 'pending' ? '1px solid var(--border)' : '1px solid transparent' }}>{label}</span>;
};

// ────────────────────────────────────────────────────────────────────────
// CANDIDATE DRAWER
// ────────────────────────────────────────────────────────────────────────
const CandidateSidePanel = ({ candidate, enrichment, verdictRecord, onClose, onSaveVerdict }) => {
  const [verdict, setVerdict] = useStateTD(verdictRecord?.verdict || null);
  const [reason, setReason]   = useStateTD(verdictRecord?.reason || '');
  const [selectedFlags, setSelectedFlags] = useStateTD(verdictRecord?.flagsSelected || []);
  const [savedFlash, setSavedFlash] = useStateTD(false);
  useEffectTD(() => {
    setVerdict(verdictRecord?.verdict || null);
    setReason(verdictRecord?.reason || '');
    const failing = enrichment ? Object.entries(enrichment.criteriaFlags).filter(([_, f]) => !f.pass).map(([k]) => k) : [];
    setSelectedFlags(verdictRecord?.flagsSelected || failing);
    setSavedFlash(false);
  }, [candidate?.id]);

  if (!candidate || !enrichment) return null;
  const canSave = !!verdict && reason.trim().length > 0;
  const handleSave = () => { if (!canSave) return; onSaveVerdict({ candidateId: candidate.id, verdict, reason: reason.trim(), flagsSelected: selectedFlags }); setSavedFlash(true); setTimeout(() => setSavedFlash(false), 1800); };

  return (
    <div className="wts-panel">
      <div className="wts-panel__header">
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flex: 1, minWidth: 0 }}>
          <span style={{ fontSize: 18 }}>{candidate.countryFlag}</span>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontSize: 14.5, fontWeight: 600, lineHeight: 1.3, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{candidate.companyName}</div>
            <div style={{ fontSize: 11.5, color: 'var(--muted-foreground)', marginTop: 2 }}>
              <span style={{ fontFamily: 'var(--font-mono)' }}>{candidate.naceCode}</span> · {candidate.countryLabel} · {formatEUR(candidate.turnover)}
            </div>
          </div>
        </div>
        <button type="button" className="wts-icon-btn" onClick={onClose} aria-label="Close"><Icon name="x" size={15} /></button>
      </div>

      <div className="wts-panel__body">
        <section className="wts-panel__section" style={{ marginTop: 0 }}>
          <div className="wts-panel__section-label" style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <Icon name="sparkles" size={12} style={{ opacity: 0.6 }} /> AI-generated business description
          </div>
          <div style={{ fontSize: 13, lineHeight: 1.65, color: 'var(--foreground)' }}>
            <HighlightedDescription text={candidate.businessDescription} quotes={[enrichment.primaryEvidenceQuote, ...Object.values(enrichment.criteriaFlags).map(f => f?.evidence).filter(Boolean)]} />
          </div>
          <div style={{ fontSize: 11, color: 'var(--muted-foreground)', marginTop: 8, fontFamily: 'var(--font-mono)' }}>
            Source: {enrichment.fetchUrl} · {enrichment.modelVersion}
          </div>
          <dl className="wts-deflist">
            <div><dt>Independent</dt><dd>{candidate.independent ? 'Yes' : 'No'}</dd></div>
            <div><dt>Loss-making (2024)</dt><dd>{candidate.lossMaking2024 ? 'Yes' : 'No'}</dd></div>
            <div><dt>Employees</dt><dd>{candidate.employees}</dd></div>
            <div><dt>Turnover</dt><dd>{formatEUR(candidate.turnover)}</dd></div>
          </dl>
        </section>

        <section className="wts-panel__section">
          <div className="wts-panel__section-label">Criteria flags</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 9 }}>
            {FLAG_OPTS.map(opt => {
              const f = enrichment.criteriaFlags[opt.code];
              if (!f) return null;
              return (
                <div key={opt.code} className="wts-flag-row">
                  <span className={cn('wts-flag-row__icon', f.pass ? 'wts-flag-row__icon--pass' : 'wts-flag-row__icon--fail')}><Icon name={f.pass ? 'check' : 'x'} size={11} /></span>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 12.5, fontWeight: 500 }}>{opt.label}: <span style={{ color: f.pass ? 'hsl(142 55% 32%)' : 'hsl(0 72% 42%)' }}>{f.pass ? 'pass' : 'fail'}</span></div>
                    {f.evidence && <div className="wts-flag-row__evidence">{f.evidence}</div>}
                  </div>
                </div>
              );
            })}
          </div>
        </section>

        <section className="wts-panel__section">
          <div className="wts-panel__section-label">Primary evidence</div>
          <div className="wts-quote" style={{ fontSize: 13.5 }}>{enrichment.primaryEvidenceQuote.startsWith('"') ? enrichment.primaryEvidenceQuote : `"${enrichment.primaryEvidenceQuote}"`}</div>
        </section>

        {verdictRecord && verdictRecord.history && verdictRecord.history.length > 0 && (
          <section className="wts-panel__section">
            <div className="wts-panel__section-label">Decision history</div>
            <div className="wts-timeline">
              {verdictRecord.history.slice().reverse().map((h, i) => {
                const u = getUserById(h.userId);
                return (
                  <div key={i} className="wts-timeline__item">
                    <div className="wts-timeline__dot"><Icon name={h.verdict === 'accept' ? 'check' : 'x'} size={11} /></div>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 12.5 }}><strong style={{ textTransform: 'capitalize' }}>{h.verdict}</strong> · {u ? u.name : 'Analyst'}</div>
                      <div style={{ fontSize: 11.5, color: 'var(--muted-foreground)', marginTop: 1 }}>{new Date(h.at).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' })}</div>
                      {h.reason && <div style={{ fontSize: 12, color: 'hsl(0 0% 35%)', marginTop: 3, fontStyle: 'italic' }}>“{h.reason}”</div>}
                    </div>
                  </div>
                );
              })}
            </div>
          </section>
        )}
      </div>

      {/* Verdict capture */}
      <div className="wts-panel__footer" style={{ background: 'hsl(220 14% 98%)' }}>
        <div style={{ display: 'flex', flexDirection: 'column', width: '100%', gap: 10 }}>
          <div style={{ fontSize: 12, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--muted-foreground)' }}>Analyst verdict</div>
          <div className="wts-override__radios">
            {[{ v: 'accept', cls: 'accept' }, { v: 'reject', cls: 'reject' }].map(o => (
              <label key={o.v} className={cn('wts-override__radio', verdict === o.v && 'wts-override__radio--on', o.cls)}>
                <input type="radio" name="verdict" value={o.v} checked={verdict === o.v} onChange={() => setVerdict(o.v)} />
                <span style={{ textTransform: 'capitalize' }}>{o.v}</span>
              </label>
            ))}
          </div>
          <div>
            <div style={{ fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--muted-foreground)', marginBottom: 7 }}>Criteria flags considered</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
              {FLAG_OPTS.map(opt => {
                const on = selectedFlags.includes(opt.code);
                const f = enrichment.criteriaFlags[opt.code];
                return (
                  <button key={opt.code} type="button" className={cn('wts-flag-chip', on && 'wts-flag-chip--on')} onClick={() => setSelectedFlags(xs => on ? xs.filter(x => x !== opt.code) : [...xs, opt.code])}>
                    <span className={cn('wts-flag-dot', f ? (f.pass ? 'wts-flag-dot--pass' : 'wts-flag-dot--fail') : 'wts-flag-dot--na')}>{opt.short}</span>
                    {opt.label}
                  </button>
                );
              })}
            </div>
          </div>
          <Textarea placeholder="Reasoning (required) — recorded in the decision history for TP defensibility." value={reason} onChange={e => setReason(e.target.value)} style={{ minHeight: 70 }} />
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <Button onClick={handleSave} disabled={!canSave}><Icon name="check" size={13} /> Save verdict</Button>
            {savedFlash && <span style={{ fontSize: 12, color: 'hsl(142 55% 32%)', display: 'inline-flex', alignItems: 'center', gap: 4 }}><Icon name="check" size={11} /> Saved</span>}
          </div>
          <div className="wts-audit-line">Enriched {enrichment.modelVersion} · Prompt {enrichment.promptVersion} · {new Date(enrichment.enrichedAt).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' })}</div>
        </div>
      </div>
    </div>
  );
};

// ── Candidate row ─────────────────────────────────────────────────────────
const CandidateRow = ({ cand, enrichment, verdictRecord, onOpen, selected, onToggleSelect }) => {
  const verdict = verdictRecord?.verdict || 'pending';
  return (
    <tr className="wts-row-clickable" onClick={() => onOpen(cand.id)}>
      <td onClick={e => e.stopPropagation()} style={{ width: 32, paddingLeft: 16, paddingRight: 0 }}>
        <input type="checkbox" className="wts-checkbox" checked={!!selected} onChange={e => onToggleSelect(cand.id, e.target.checked)} />
      </td>
      <td>
        <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
          <span style={{ fontSize: 14 }}>{cand.countryFlag}</span>
          <div style={{ minWidth: 0, overflow: 'hidden' }}>
            <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--foreground)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{cand.companyName}</div>
            <div style={{ fontSize: 11.5, color: 'var(--muted-foreground)', marginTop: 1, fontFamily: 'var(--font-mono)' }}>{cand.naceCode}</div>
          </div>
        </div>
      </td>
      <td style={{ textAlign: 'right', fontVariantNumeric: 'tabular-nums', fontSize: 13 }}>{formatEUR(cand.turnover)}</td>
      <td><FlagDots flags={enrichment.criteriaFlags} /></td>
      <td><VerdictPill verdict={verdict} /></td>
      <td>
        <div style={{ fontSize: 12.5, color: 'hsl(0 0% 22%)', lineHeight: 1.5, maxWidth: 380, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          {verdictRecord?.reason || <span style={{ color: 'var(--muted-foreground)' }}>—</span>}
        </div>
      </td>
    </tr>
  );
};

// ────────────────────────────────────────────────────────────────────────
// RUN SUMMARY MODAL (replaces Excel export — no file artefact in MVP)
// ────────────────────────────────────────────────────────────────────────
const RunSummaryModal = ({ open, onClose, study, breakdown }) => {
  const toast = useToast();
  const creator = study ? getUserById(study.createdBy) : null;
  if (!open || !study) return null;
  const downloadDoc = () => {
    const L = [
      study.name, 'Study run summary — WTS Operations Platform', '',
      `Engagement: ${study.engagement}`, `Created by: ${creator?.name || '—'}`, '',
      'TESTED PARTY', 'Functional profile: Limited-risk distributor', 'Industry / NACE: 46.46 — Wholesale of pharmaceutical goods',
      'Geographic market: DE · FR · IT · NL · CY', 'Turnover band: EUR 5M — EUR 50M', 'Tested period: 2022 – 2024', '',
      'COMPARABILITY CRITERIA', 'Independence: <25% group ownership', 'Activity strictness: Moderate', 'Geographic strictness: Moderate', '',
      'RUN STATISTICS', `Candidates total: ${study.candidates}`, `Analyst accepted: ${breakdown.accept}`,
      `Analyst rejected: ${breakdown.reject}`, `Pending: ${breakdown.pending}`, 'Enrichment cost: $14.20', 'Model · prompt: claude-sonnet-4 · v1.3',
    ];
    const blob = new Blob([L.join('\n')], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = `${study.name.replace(/[^A-Za-z0-9]+/g, '_')}_run_summary.txt`;
    document.body.appendChild(a); a.click(); a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
    toast.success('Summary downloaded', a.download);
  };
  return (
    <div className="wts-modal-overlay" onClick={onClose}>
      <div className="wts-modal" style={{ maxWidth: 600, width: '95vw' }} onClick={e => e.stopPropagation()}>
        <div className="wts-modal__header">
          <div style={{ fontSize: 15, fontWeight: 600 }}>Study run summary</div>
          <button type="button" className="wts-icon-btn" onClick={onClose}><Icon name="x" size={15} /></button>
        </div>
        <div className="wts-modal__body">
          <div style={{ fontSize: 12.5, color: 'var(--muted-foreground)', marginBottom: 18, lineHeight: 1.55 }}>
            A read-only record of this study. The analyst Accept / Reject decisions and reasoning are retained per candidate.
            No spreadsheet is exported in this version — the client deliverable format is a separate decision.
          </div>
          {[
            { t: 'Tested party', rows: [['Functional profile', 'Limited-risk distributor'], ['Industry / NACE', '46.46 — Wholesale of pharmaceutical goods'], ['Geographic market', 'DE · FR · IT · NL · CY'], ['Turnover band', 'EUR 5M — EUR 50M'], ['Tested period', '2022 – 2024']] },
            { t: 'Comparability criteria', rows: [['Independence', '<25% group ownership'], ['Activity strictness', 'Moderate'], ['Geographic strictness', 'Moderate']] },
            { t: 'Run statistics', rows: [['Candidates total', String(study.candidates)], ['Analyst accepted', String(breakdown.accept)], ['Analyst rejected', String(breakdown.reject)], ['Pending', String(breakdown.pending)], ['Enrichment cost', '$14.20'], ['Model · prompt', 'claude-sonnet-4 · v1.3']] },
          ].map((sec, i) => (
            <div key={i} style={{ marginBottom: 18 }}>
              <div style={{ fontSize: 10.5, fontWeight: 600, color: 'var(--muted-foreground)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 8 }}>{sec.t}</div>
              <dl style={{ display: 'flex', flexDirection: 'column', gap: 5, margin: 0, fontSize: 12.5 }}>
                {sec.rows.map(([k, v], j) => (
                  <div key={j} style={{ display: 'flex', justifyContent: 'space-between', gap: 12 }}>
                    <dt style={{ color: 'var(--muted-foreground)', margin: 0 }}>{k}</dt>
                    <dd style={{ margin: 0, fontWeight: 500, fontVariantNumeric: 'tabular-nums' }}>{v}</dd>
                  </div>
                ))}
              </dl>
            </div>
          ))}
          <div style={{ fontSize: 10.5, color: 'var(--muted-foreground)', fontFamily: 'var(--font-mono)', textAlign: 'center', paddingTop: 8, borderTop: '1px solid var(--border)' }}>
            Created by {creator?.name || '—'} · {study.engagement}
          </div>
        </div>
        <div className="wts-modal__footer">
          <Button variant="outline" onClick={onClose}>Close</Button>
          <Button onClick={downloadDoc}><Icon name="download" size={14} /> Download summary</Button>
        </div>
      </div>
    </div>
  );
};

// ────────────────────────────────────────────────────────────────────────
// STUDY DETAIL
// ────────────────────────────────────────────────────────────────────────
const StudyDetail = ({ study: initialStudy, onBack }) => {
  const toast = useToast();
  const [study, setStudy] = useStateTD(initialStudy);
  const [openCand, setOpenCand] = useStateTD(null);
  const [summaryOpen, setSummaryOpen] = useStateTD(false);
  const [verdictsLocal, setVerdictsLocal] = useStateTD(() =>
    Object.fromEntries(VERDICTS.filter(v => v.studyId === initialStudy.id).map(v => [v.candidateId, v])));
  const [selected, setSelected] = useStateTD({});
  useEffectTD(() => { setStudy(initialStudy); }, [initialStudy.id]);

  const [verdictFilter, setVerdictFilter] = useStateTD('all');
  const [flagFilters, setFlagFilters]     = useStateTD([]);
  const [search, setSearch]               = useStateTD('');

  const isRunning = study.status === 'running';
  const candidatesAll = useMemoTD(() => getCandidatesForStudy(study.id), [study.id]);
  const enrichAll     = useMemoTD(() => ENRICHMENTS.filter(e => e.studyId === study.id), [study.id]);

  // Running → enrichment streaming
  const [processed, setProcessed] = useStateTD(isRunning ? 0 : candidatesAll.length);
  const startTimeRef = useRefTD(Date.now());
  const tickRef = useRefTD(null);
  useEffectTD(() => {
    if (!isRunning) return;
    setProcessed(0); startTimeRef.current = Date.now();
    tickRef.current = setInterval(() => {
      setProcessed(prev => {
        const next = Math.min(prev + Math.floor(2 + Math.random() * 3), candidatesAll.length);
        if (next >= candidatesAll.length) {
          clearInterval(tickRef.current);
          setTimeout(() => { setStudy(s => ({ ...s, status: 'review', reviewed: 0 })); toast.success('Enrichment complete', `${candidatesAll.length} descriptions generated · ready for analyst review`); }, 400);
        }
        return next;
      });
    }, 200);
    return () => { if (tickRef.current) clearInterval(tickRef.current); };
  }, [isRunning, candidatesAll.length]);

  const breakdown = useMemoTD(() => {
    const vs = Object.values(verdictsLocal);
    return { accept: vs.filter(v => v.verdict === 'accept').length, reject: vs.filter(v => v.verdict === 'reject').length, pending: candidatesAll.length - vs.length };
  }, [verdictsLocal, candidatesAll.length]);

  const candidatesVisible = useMemoTD(() => {
    let xs = isRunning ? candidatesAll.slice(0, processed) : candidatesAll;
    if (verdictFilter !== 'all') xs = xs.filter(c => (verdictsLocal[c.id]?.verdict || 'pending') === verdictFilter);
    if (flagFilters.length > 0) xs = xs.filter(c => {
      const e = enrichAll.find(x => x.candidateId === c.id);
      return e && flagFilters.every(fc => e.criteriaFlags[fc] && !e.criteriaFlags[fc].pass);
    });
    if (search) { const q = search.toLowerCase(); xs = xs.filter(c => c.companyName.toLowerCase().includes(q)); }
    return xs;
  }, [candidatesAll, processed, enrichAll, verdictFilter, flagFilters, search, isRunning, verdictsLocal]);

  const TABLE_LIMIT = 60;
  const tableRows = candidatesVisible.slice(0, TABLE_LIMIT);

  const onSaveVerdict = ({ candidateId, verdict, reason, flagsSelected }) => {
    setVerdictsLocal(o => {
      const prev = o[candidateId];
      const history = [...(prev?.history || []), { verdict, reason, userId: study.createdBy, at: '2025-05-16T12:00:00Z' }];
      return { ...o, [candidateId]: { id: `vrd-local-${candidateId}`, candidateId, studyId: study.id, verdict, reason, flagsSelected: flagsSelected || [], userId: study.createdBy, createdAt: '2025-05-16T12:00:00Z', history } };
    });
    toast.success('Verdict saved', 'Decision history updated.');
  };

  const bulkRejectFailing = (code) => {
    let n = 0;
    setVerdictsLocal(o => {
      const next = { ...o };
      candidatesAll.forEach(c => {
        if (next[c.id]) return;
        const e = enrichAll.find(x => x.candidateId === c.id);
        if (e && e.criteriaFlags[code] && !e.criteriaFlags[code].pass) {
          const reason = `Auto-rejected — fails ${code}.`;
          next[c.id] = { id: `vrd-bulk-${c.id}`, candidateId: c.id, studyId: study.id, verdict: 'reject', reason, userId: study.createdBy, createdAt: '2025-05-16T12:00:00Z', history: [{ verdict: 'reject', reason, userId: study.createdBy, at: '2025-05-16T12:00:00Z' }] };
          n++;
        }
      });
      return next;
    });
    toast.success('Bulk verdict applied', `${n} pending candidate(s) rejected on ${code}`);
  };

  const openCandObj = openCand ? candidatesAll.find(c => c.id === openCand) : null;
  const openCandEnr = openCand ? enrichAll.find(x => x.candidateId === openCand) : null;
  const openCandVerdict = openCand ? verdictsLocal[openCand] : null;

  const eta = isRunning ? Math.max(0, Math.round(((candidatesAll.length - processed) * 0.20) / 60 * 10) / 10) : 0;
  const costSoFar = isRunning ? (processed * 0.06).toFixed(2) : '14.20';
  const startedMins = Math.floor((Date.now() - startTimeRef.current) / 60000);
  const reviewedCount = breakdown.accept + breakdown.reject;
  const creator = getUserById(study.createdBy);

  return (
    <div className="ck-page">
      <div className="wts-eng-header">
        <div className="wts-eng-header__top">
          <div style={{ minWidth: 0 }}>
            <button type="button" className="wts-link" style={{ fontSize: 12.5, marginBottom: 8 }} onClick={onBack}>← Back to studies</button>
            <div className="wts-eng-header__title">{study.name}</div>
            <div className="wts-eng-header__client">
              <button type="button" className="wts-link" style={{ fontWeight: 400, color: 'var(--muted-foreground)' }}>{study.engagement}</button>
              {' · '}created by {creator?.name || '—'}{' · '}
              {study.status === 'complete' ? 'completed 15 May' : study.status === 'running' ? 'enriching' : 'in review'}
            </div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 10, flexShrink: 0 }}>
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 7 }}>
              <StatusBadge status={study.status} />
              {study.status === 'running' && <span className="wts-pulse-dot" />}
            </span>
            <div style={{ display: 'flex', gap: 8 }}>
              {study.status === 'running' && <Button variant="outline" onClick={() => toast.info('Run cancelled', 'Partial enrichment discarded.')} style={{ color: 'hsl(0 72% 42%)' }}>Cancel run</Button>}
              {study.status === 'review' && (
                <Button onClick={() => {
                  if (breakdown.pending > 0) { toast.info('Verdicts outstanding', `${breakdown.pending} candidate(s) still pending`); return; }
                  setStudy(s => ({ ...s, status: 'complete', reviewed: candidatesAll.length })); toast.success('Study marked complete', `${candidatesAll.length} candidates reviewed`);
                }}><Icon name="check-circle-2" size={13} /> Mark complete</Button>
              )}
              {study.status === 'complete' && <Button variant="outline" onClick={() => setSummaryOpen(true)}><Icon name="file-text" size={13} /> Run summary</Button>}
            </div>
          </div>
        </div>

        {/* Metrics */}
        {study.status === 'running' ? (
          <>
            <div className="wts-metric-row">
              <div className="wts-metric"><div className="wts-metric__label">Descriptions generated</div><div className="wts-metric__value">{processed} <span style={{ color: 'var(--muted-foreground)', fontWeight: 400, fontSize: 14 }}>/ {candidatesAll.length}</span></div></div>
              <div className="wts-metric"><div className="wts-metric__label">Estimated remaining</div><div className="wts-metric__value-sm">{eta > 0 ? `~${eta} min` : 'finalising…'}</div></div>
              <div className="wts-metric"><div className="wts-metric__label">Cost so far</div><div className="wts-metric__value-sm">${costSoFar}</div></div>
              <div className="wts-metric"><div className="wts-metric__label">Started</div><div className="wts-metric__value-sm">{startedMins === 0 ? 'just now' : `${startedMins} min ago`}</div></div>
            </div>
            <div className="wts-shimmer"><div className="wts-shimmer__bar" style={{ width: `${(processed / candidatesAll.length) * 100}%` }} /><div className="wts-shimmer__pulse" /></div>
          </>
        ) : (
          <div className="wts-metric-row">
            <div className="wts-metric"><div className="wts-metric__label">Candidates</div><div className="wts-metric__value">{candidatesAll.length}</div></div>
            <div className="wts-metric"><div className="wts-metric__label">Accepted</div><div className="wts-metric__value" style={{ display: 'flex', alignItems: 'center', gap: 8 }}><i className="wts-dot wts-dot--green" style={{ width: 9, height: 9 }} />{breakdown.accept}</div></div>
            <div className="wts-metric"><div className="wts-metric__label">Rejected</div><div className="wts-metric__value" style={{ display: 'flex', alignItems: 'center', gap: 8 }}><i className="wts-dot wts-dot--red" style={{ width: 9, height: 9 }} />{breakdown.reject}</div></div>
            <div className="wts-metric"><div className="wts-metric__label">Pending</div><div className="wts-metric__value" style={{ display: 'flex', alignItems: 'center', gap: 8 }}><i className="wts-dot" style={{ width: 9, height: 9, background: 'hsl(220 9% 70%)' }} />{breakdown.pending}</div></div>
            <div className="wts-metric"><div className="wts-metric__label">Reviewed</div><div className="wts-metric__value">{reviewedCount} <span style={{ color: 'var(--muted-foreground)', fontWeight: 400, fontSize: 14 }}>/ {candidatesAll.length}</span></div></div>
            <div className="wts-metric"><div className="wts-metric__label">Enrichment cost</div><div className="wts-metric__value-sm">${costSoFar}</div></div>
          </div>
        )}
      </div>

      {/* Filters */}
      {!isRunning && (
        <div className="wts-filter-row" style={{ gap: 10 }}>
          <Segmented options={VERDICT_FILTER_OPTS} value={verdictFilter} onChange={setVerdictFilter} />
          <div className="wts-flag-filter-wrap">
            <Icon name="flag" size={13} style={{ opacity: 0.4 }} />
            <div style={{ display: 'flex', gap: 4 }}>
              {FLAG_OPTS.map(opt => {
                const active = flagFilters.includes(opt.code);
                return <button key={opt.code} type="button" className={cn('wts-flag-pill', active && 'wts-flag-pill--on')} onClick={() => setFlagFilters(xs => active ? xs.filter(x => x !== opt.code) : [...xs, opt.code])} title={`Failing ${opt.label}`}>{opt.short}</button>;
              })}
            </div>
          </div>
          <div className="wts-search-wrap">
            <Icon name="search" size={14} style={{ opacity: 0.4 }} />
            <input className="wts-search" placeholder="Search company name..." value={search} onChange={e => setSearch(e.target.value)} />
          </div>
          <div style={{ flex: 1 }} />
          <KebabMenu items={[
            { icon: 'x-circle', label: 'Reject all pending failing Independence', onClick: () => bulkRejectFailing('independence') },
            { icon: 'x-circle', label: 'Reject all pending failing Size',         onClick: () => bulkRejectFailing('size') },
            { icon: 'rotate-ccw', label: 'Clear my verdicts (session)', danger: true, onClick: () => { setVerdictsLocal({}); toast.error('Verdicts cleared', 'All analyst verdicts reset for this session'); } },
          ]} />
        </div>
      )}

      {/* Candidate table */}
      <Card style={{ padding: 0, gap: 0 }}>
        <CardContent style={{ padding: 0 }}>
          {isRunning && (
            <div style={{ padding: '10px 18px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 10, background: 'hsl(38 95% 97%)' }}>
              <Icon name="loader-2" size={14} className="wts-spin" style={{ opacity: 0.7 }} />
              <span style={{ fontSize: 12.5, fontWeight: 500, color: 'hsl(28 90% 35%)', whiteSpace: 'nowrap' }}>Enriching… {processed} / {candidatesAll.length}</span>
              <span style={{ fontSize: 12, color: 'var(--muted-foreground)', whiteSpace: 'nowrap' }}>· Playwright fetch + Claude description · streaming live</span>
            </div>
          )}
          <table className="ck-table wts-candidates-table">
            <thead>
              <tr>
                <th style={{ width: 32, paddingLeft: 16, paddingRight: 0 }}></th>
                <th>Company</th>
                <th style={{ width: 100, textAlign: 'right' }}>Turnover</th>
                <th style={{ width: 120 }}>Criteria flags</th>
                <th style={{ width: 110 }}>Verdict</th>
                <th>Reasoning</th>
              </tr>
            </thead>
            <tbody>
              {tableRows.map(c => {
                const e = enrichAll.find(x => x.candidateId === c.id);
                if (!e) return null;
                return <CandidateRow key={c.id} cand={c} enrichment={e} verdictRecord={verdictsLocal[c.id]} onOpen={setOpenCand} selected={selected[c.id]} onToggleSelect={(id, ch) => setSelected(s => ({ ...s, [id]: ch }))} />;
              })}
              {isRunning && processed < TABLE_LIMIT && Array.from({ length: Math.min(6, candidatesAll.length - processed) }).map((_, i) => (
                <tr key={`skel-${i}`} className="wts-skel-row"><td colSpan={6}><div className="wts-skel-line" /></td></tr>
              ))}
              {!isRunning && tableRows.length === 0 && <tr><td colSpan={6} style={{ padding: 48, textAlign: 'center', color: 'var(--muted-foreground)' }}>No candidates match these filters.</td></tr>}
            </tbody>
          </table>
          {!isRunning && candidatesVisible.length > TABLE_LIMIT && (
            <div style={{ padding: '14px 18px', textAlign: 'center', fontSize: 12.5, color: 'var(--muted-foreground)', borderTop: '1px solid var(--border)' }}>
              Showing first {TABLE_LIMIT} of {candidatesVisible.length} candidates. Refine filters to narrow.
            </div>
          )}
        </CardContent>
      </Card>

      <RunSummaryModal open={summaryOpen} onClose={() => setSummaryOpen(false)} study={study} breakdown={breakdown} />

      <Drawer open={!!openCand} onClose={() => setOpenCand(null)} width={500}>
        {openCand && openCandObj && openCandEnr && (
          <CandidateSidePanel candidate={openCandObj} enrichment={openCandEnr} verdictRecord={openCandVerdict} onClose={() => setOpenCand(null)} onSaveVerdict={onSaveVerdict} />
        )}
      </Drawer>
    </div>
  );
};

Object.assign(window, { StudyDetail });
