// ── بایگانی کنار (aside) ─────────────────────────────────
const ArchiveAside = ({ onShowAll, onSelect }) => {
  const { Icon, useToast } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const toast = useToast();
  const [items, setItems] = useState([]);
  const [filter, setFilter] = useState('all'); // all | campaign | script

  const load = () => {
    window.api('/lab/populations').then(data => {
      if (Array.isArray(data)) setItems(data.filter(p => p.conv && p.conv !== '0'));
    }).catch(() => {});
  };
  useEffect(() => { load(); }, []);

  const del = async (id, e) => {
    e.stopPropagation();
    if (!window.confirm('حذف بشه؟')) return;
    await window.api('/lab/populations/' + id, { method: 'DELETE' }).catch(() => {});
    load();
    toast('حذف شد', 'info');
  };

  const convColor = v => parseFloat(v) >= 30 ? '#10B981' : parseFloat(v) >= 15 ? '#F59E0B' : '#6B7280';

  const filtered = filter === 'all' ? items : items.filter(p => p.test_mode === filter);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 0, height: '100%' }}>
      {/* header */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
        <div className="row gap-6">
          <Icon name="archive" size={14} color="var(--primary-2)" />
          <span className="bold text-sm">بایگانی</span>
          <span className="mono text-xs text-3">({fa(filtered.length)})</span>
        </div>
        <div className="row gap-4">
          <button className="icon-btn" style={{ width: 26, height: 26 }} onClick={load} title="رفرش"><Icon name="refresh-cw" size={11} /></button>
        </div>
      </div>

      {/* فیلتر */}
      <div className="row gap-4" style={{ marginBottom: 10 }}>
        {[['all','همه'],['script','اسکریپت'],['campaign','کمپین']].map(([v,l]) => (
          <button key={v} onClick={() => setFilter(v)}
            style={{ flex: 1, padding: '4px 0', fontSize: 11, borderRadius: 6, cursor: 'pointer', border: `1px solid ${filter===v ? 'rgba(108,99,255,0.5)' : 'var(--border-soft)'}`, background: filter===v ? 'rgba(108,99,255,0.12)' : 'transparent', color: filter===v ? '#a5b4fc' : 'var(--text-3)' }}>{l}
          </button>
        ))}
      </div>

      {/* لیست */}
      <div style={{ flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 6 }}>
        {filtered.length === 0 ? (
          <div style={{ textAlign: 'center', padding: '24px 0', color: 'var(--text-3)', fontSize: 12 }}>تستی ثبت نشده</div>
        ) : filtered.map(p => (
          <div key={p.id} onClick={() => onSelect(p.id)}
            style={{ padding: '8px 10px', borderRadius: 8, border: '1px solid var(--border-soft)', background: 'rgba(15,15,26,0.4)', display: 'flex', flexDirection: 'column', gap: 4, cursor: 'pointer', transition: 'border-color 0.15s' }}
            onMouseEnter={e => e.currentTarget.style.borderColor = 'rgba(108,99,255,0.5)'}
            onMouseLeave={e => e.currentTarget.style.borderColor = 'var(--border-soft)'}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 6 }}>
              <span style={{ fontSize: 12, fontWeight: 600, flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.name}</span>
              <span style={{ fontSize: 12, fontWeight: 700, color: convColor(p.conv), flexShrink: 0 }}>{fa(p.conv)}%</span>
            </div>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
              <span style={{ fontSize: 10, color: 'var(--text-3)' }}>{fa(p.total)} نفر • {p.test_mode === 'campaign' ? '📢' : '📄'} {p.test_mode === 'campaign' ? (p.campaign_name || 'کمپین') : (p.script_name || 'اسکریپت')}</span>
              <button onClick={e => del(p.id, e)} style={{ fontSize: 10, color: '#F87171', background: 'none', border: 'none', cursor: 'pointer', padding: '1px 4px' }}>حذف</button>
            </div>
          </div>
        ))}
      </div>

      {/* دکمه همه */}
      <button onClick={onShowAll}
        style={{ marginTop: 10, width: '100%', padding: '8px', borderRadius: 8, border: '1px solid rgba(108,99,255,0.3)', background: 'rgba(108,99,255,0.08)', color: '#a5b4fc', fontSize: 12, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}>
        <Icon name="list" size={13} />مشاهده همه
      </button>
    </div>
  );
};

// Lab page — طراحی جدید
const LAB_TABS = [
  { id: 'test',     label: 'اجرای تست',   icon: 'play' },
  { id: 'community',label: 'جامعه',        icon: 'users' },
  { id: 'persona',  label: 'پرسونا',       icon: 'user-circle' },
  { id: 'scenario', label: 'نقشه سناریو', icon: 'git-fork' },
  { id: 'checkup',  label: 'چکاپ سیستم',  icon: 'activity' },
];

const Lab = () => {
  const { Icon } = window.SB_UI;
  const [savedPops, setSavedPops] = useState([]);
  const [activeTab, setActiveTab] = useState('test');
  const [showAllArchive, setShowAllArchive] = useState(false);
  const [archiveInitId, setArchiveInitId] = useState(null);

  const refreshSavedPops = () => {
    window.api('/lab/populations').then(data => {
      if (Array.isArray(data)) setSavedPops(data);
    }).catch(() => {});
  };

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

  const deleteSavedPop = async (id, e) => {
    e && e.stopPropagation();
    if (!window.confirm('این جامعه حذف بشه؟')) return;
    await window.api('/lab/populations/' + id, { method: 'DELETE' }).catch(() => {});
    refreshSavedPops();
  };

  if (showAllArchive) {
    return (
      <div>
        <button onClick={() => { setShowAllArchive(false); setArchiveInitId(null); }}
          style={{ display: 'flex', alignItems: 'center', gap: 8, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-3)', fontSize: 13, marginBottom: 16, padding: 0 }}>
          <Icon name="arrow-right" size={15} />بازگشت
        </button>
        <ArchiveTab initialId={archiveInitId} />
      </div>
    );
  }

  const isCheckup = activeTab === 'checkup';

  return (
    <div className="col gap-16">

      {/* ── نوار تب ── */}
      <div style={{ display: 'flex', gap: 4, borderBottom: '1px solid var(--border-soft)', paddingBottom: 0 }}>
        {LAB_TABS.map(t => (
          <button key={t.id} onClick={() => setActiveTab(t.id)}
            style={{
              display: 'flex', alignItems: 'center', gap: 7,
              padding: '9px 16px',
              background: 'none', border: 'none', cursor: 'pointer',
              fontSize: 13, fontWeight: activeTab === t.id ? 600 : 400,
              color: activeTab === t.id
                ? (t.id === 'checkup' ? '#10B981' : 'var(--primary-2)')
                : 'var(--text-3)',
              borderBottom: activeTab === t.id
                ? `2px solid ${t.id === 'checkup' ? '#10B981' : 'var(--primary-2)'}`
                : '2px solid transparent',
              marginBottom: -1,
              transition: 'color 0.15s',
            }}>
            <Icon name={t.icon} size={14}
              color={activeTab === t.id
                ? (t.id === 'checkup' ? '#10B981' : 'var(--primary-2)')
                : 'var(--text-3)'} />
            {t.label}
          </button>
        ))}
      </div>

      {/* ── محتوای تب ── */}
      {activeTab === 'test' && (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 260px', gap: 20, alignItems: 'start' }}>
          <RunTestTab savedPops={savedPops} onRefresh={refreshSavedPops} />
          <div style={{ position: 'sticky', top: 16, maxHeight: 'calc(100vh - 120px)' }}>
            <div className="card" style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
              <ArchiveAside
                onShowAll={() => setShowAllArchive(true)}
                onSelect={id => { setArchiveInitId(id); setShowAllArchive(true); }}
              />
            </div>
          </div>
        </div>
      )}

      {activeTab === 'community' && (
        <CommunityBuilderTab savedPops={savedPops} onRefresh={refreshSavedPops} onDelete={deleteSavedPop} />
      )}

      {activeTab === 'persona' && (
        <PersonaMgmtTab />
      )}

      {activeTab === 'scenario' && (
        <div>
          {window.ScenarioMap
            ? <window.ScenarioMap />
            : <div className="text-xs text-3">در حال بارگذاری...</div>}
        </div>
      )}

      {activeTab === 'checkup' && (
        <div className="card" style={{ border: '1px solid rgba(16,185,129,0.2)' }}>
          {window.LabCheckup
            ? <window.LabCheckup />
            : <div className="text-xs text-3">در حال بارگذاری...</div>}
        </div>
      )}

    </div>
  );
};


// ---- Population helpers ----
const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
const weightedPersona = (weights, personas) => {
  const r = Math.random() * weights.reduce((s, w) => s + w, 0);
  let acc = 0;
  for (let i = 0; i < weights.length; i++) {
    acc += weights[i];
    if (r <= acc) return personas[i];
  }
  return personas[personas.length - 1];
};

const BUDGET_BY_INCOME = {
  low: [1, 2, 3, 5],
  medium: [8, 10, 12, 15, 18],
  high: [20, 25, 30, 40, 45],
  very_high: [50, 60, 80, 100],
};
const CHANNELS_BY_REGION = {
  tehran: ['اینستاگرام', 'تلگرام', 'دایرکت', 'سایت', 'واتساپ'],
  big_city: ['تلگرام', 'اینستاگرام', 'واتساپ', 'سایت', 'دایرکت'],
  small_city: ['تلگرام', 'واتساپ', 'اینستاگرام', 'سایت'],
  rural: ['واتساپ', 'تلگرام', 'اینستاگرام'],
};
const CITIES_BY_REGION = {
  tehran: ['تهران'],
  big_city: ['مشهد', 'اصفهان', 'شیراز', 'تبریز', 'کرج', 'اهواز'],
  small_city: ['قم', 'رشت', 'یزد', 'اردبیل', 'ساری', 'کرمان', 'بندرعباس'],
  rural: ['شهرستان', 'شهر کوچک', 'روستا'],
};

const buildPopulation = (total, weights, personas, names1, names2, channels, cities) => {
  const people = [];
  for (let i = 0; i < total; i++) {
    const persona = weightedPersona(weights, personas);
    const [a, b] = persona.age.split('-').map(Number);
    const age = Math.floor(Math.random() * ((b || 40) - (a || 25) + 1)) + (a || 25);
    const budgetList = BUDGET_BY_INCOME[persona.income] || [3, 8, 12, 18, 25, 45];
    const budget = pick(budgetList) * 1_000_000;
    const channelList = CHANNELS_BY_REGION[persona.region] || channels;
    const cityList = CITIES_BY_REGION[persona.region] || cities;
    people.push({
      id: i,
      name: pick(names1) + ' ' + pick(names2),
      persona,
      age,
      channel: pick(channelList),
      city: pick(cityList),
      budget,
    });
  }
  return people;
};

// ─── نمایش read-only جامعه ──────────────────────────────
const PopulationReadOnly = ({ population, personas, popName, fa, faMoney, onBack, onNext }) => {
  const { Icon, Button } = window.SB_UI;
  const byPersona = personas.map(p => ({ p, n: population.filter(x => x.persona.id === p.id).length })).filter(x => x.n > 0);
  const byRegion = Object.entries(
    population.reduce((acc, p) => { const k = { tehran:'تهران', big_city:'شهر بزرگ', small_city:'شهر کوچک', rural:'روستا' }[p.persona.region] || 'نامشخص'; acc[k] = (acc[k]||0)+1; return acc; }, {})
  );
  const byIncome = Object.entries(
    population.reduce((acc, p) => { const k = { low:'کم', medium:'متوسط', high:'بالا', very_high:'مرفه' }[p.persona.income] || '—'; acc[k] = (acc[k]||0)+1; return acc; }, {})
  );
  const INCOME_COLORS = { 'کم': '#6B7280', 'متوسط': '#3B82F6', 'بالا': '#10B981', 'مرفه': '#F59E0B' };

  return (
    <div className="col gap-16">
      <div className="card" style={{ border: '1px solid rgba(108,99,255,0.25)', background: 'rgba(108,99,255,0.04)' }}>
        <div className="row between">
          <div>
            <div className="row gap-10" style={{ alignItems: 'center' }}>
              <Icon name="users" size={16} color="var(--primary-2)" />
              <span className="bold" style={{ fontSize: 15 }}>{popName || 'جامعه آزمایشی'}</span>
              <span className="mono text-xs text-3" style={{ padding: '2px 8px', background: 'rgba(255,255,255,0.07)', borderRadius: 6 }}>{fa(population.length)} نفر</span>
            </div>
            <div className="text-xs text-3 mt-6">این نمایش فقط خواندنی است — برای ویرایش برگرد</div>
          </div>
          <div className="row gap-8">
            <Button kind="ghost" size="sm" icon="arrow-right" onClick={onBack}>ویرایش جامعه</Button>
            <Button kind="primary" size="sm" icon="arrow-left" onClick={onNext}>انتخاب تست ←</Button>
          </div>
        </div>
      </div>

      <div className="grid grid-3 gap-16">
        {/* Persona distribution */}
        <div className="card" style={{ gridColumn: 'span 2' }}>
          <div className="text-xs text-3 semi" style={{ marginBottom: 12, textTransform: 'uppercase', letterSpacing: '0.05em' }}>توزیع پرسوناها</div>
          <div className="col gap-10">
            {byPersona.map(({ p, n }) => {
              const pct = Math.round((n / population.length) * 100);
              return (
                <div key={p.id}>
                  <div className="row between" style={{ marginBottom: 4 }}>
                    <div className="row gap-8">
                      <span style={{ width: 20, height: 20, borderRadius: '50%', background: `linear-gradient(135deg, ${p.color}, ${p.color}66)`, display: 'grid', placeItems: 'center', fontSize: 11 }}>{p.emoji}</span>
                      <span className="text-sm">{p.name}</span>
                      {p.occupation && <span className="text-xs text-3" style={{ padding: '1px 6px', background: 'rgba(255,255,255,0.05)', borderRadius: 4 }}>{p.occupation}</span>}
                    </div>
                    <span className="mono text-sm semi">{fa(n)} <span className="text-3 text-xs">({pct}%)</span></span>
                  </div>
                  <div className="bar"><div style={{ width: pct + '%', height: '100%', background: p.color, borderRadius: 999 }} /></div>
                </div>
              );
            })}
          </div>
        </div>

        {/* Side stats */}
        <div className="col gap-16">
          <div className="card">
            <div className="text-xs text-3 semi" style={{ marginBottom: 10, textTransform: 'uppercase', letterSpacing: '0.05em' }}>منطقه جغرافیایی</div>
            <div className="col gap-8">
              {byRegion.map(([k, n]) => (
                <div key={k} className="row between">
                  <span className="text-sm">{k}</span>
                  <span className="mono text-sm semi">{fa(n)}</span>
                </div>
              ))}
            </div>
          </div>
          <div className="card">
            <div className="text-xs text-3 semi" style={{ marginBottom: 10, textTransform: 'uppercase', letterSpacing: '0.05em' }}>سطح درآمد</div>
            <div className="col gap-8">
              {byIncome.map(([k, n]) => (
                <div key={k} className="row between">
                  <div className="row gap-6"><span style={{ width: 10, height: 10, borderRadius: 3, background: INCOME_COLORS[k] || '#6B7280' }} /><span className="text-sm">{k}</span></div>
                  <span className="mono text-sm semi">{fa(n)}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>

      {/* Sample people */}
      <div className="card">
        <div className="card-title"><Icon name="users" size={14} color="var(--primary-2)" />نمونه افراد ({fa(Math.min(12, population.length))} نفر از {fa(population.length)})</div>
        <div className="grid grid-3 gap-10 mt-12">
          {population.slice(0, 12).map(p => (
            <div key={p.id} className="row gap-10" style={{ padding: '10px 12px', background: 'rgba(15,15,26,0.4)', border: '1px solid var(--border-soft)', borderRadius: 10, alignItems: 'center' }}>
              <div style={{ width: 32, height: 32, borderRadius: '50%', background: `linear-gradient(135deg, ${p.persona.color}, ${p.persona.color}66)`, display: 'grid', placeItems: 'center', fontSize: 14, flexShrink: 0 }}>{p.persona.emoji}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="text-sm semi" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.name}</div>
                <div className="text-xs text-3 mono mt-3">{fa(p.age)} ساله • {p.city}</div>
                <div className="text-xs text-3 mono">{faMoney(Math.round(p.budget / 1_000_000))}M • {p.channel}</div>
              </div>
            </div>
          ))}
        </div>
        <div className="row gap-8 mt-16" style={{ justifyContent: 'flex-end' }}>
          <Button kind="ghost" size="sm" icon="arrow-right" onClick={onBack}>ویرایش جامعه</Button>
          <Button kind="primary" icon="arrow-left" onClick={onNext}>انتخاب اسکریپت / کمپین ←</Button>
        </div>
      </div>
    </div>
  );
};

// ─── پیش‌نمایش اسکریپت ──────────────────────────────────
const ScriptPreviewModal = ({ open, onClose, scriptCtx, scriptName }) => {
  const { Modal } = window.SB_UI;
  if (!open) return null;
  return (
    <Modal open={open} onClose={onClose} title={`اسکریپت: ${scriptName || ''}`} width={700}>
      <div className="col gap-14">
        <div className="row gap-12">
          {[
            { label: 'سوالات', val: (scriptCtx?.questions || []).length, color: '#6C63FF' },
            { label: 'خط قرمز', val: (scriptCtx?.redLines || []).length, color: '#F87171' },
            { label: 'راهنمایی', val: (scriptCtx?.guidelines || []).length, color: '#10B981' },
          ].map(s => (
            <div key={s.label} style={{ padding: '10px 16px', borderRadius: 10, border: `1px solid ${s.color}44`, background: `${s.color}11`, textAlign: 'center' }}>
              <div className="bold" style={{ fontSize: 20, color: s.color }}>{s.val}</div>
              <div className="text-xs text-3 mt-2">{s.label}</div>
            </div>
          ))}
        </div>

        {scriptCtx?.systemPrompt && (
          <div>
            <div className="label" style={{ marginBottom: 8 }}>محتوای اسکریپت</div>
            <div style={{ padding: 14, background: 'rgba(15,15,26,0.7)', borderRadius: 10, border: '1px solid var(--border-soft)', maxHeight: 280, overflowY: 'auto', fontSize: 12, lineHeight: 1.9, whiteSpace: 'pre-wrap', color: 'var(--text-2)', direction: 'rtl' }}>
              {scriptCtx.systemPrompt}
            </div>
          </div>
        )}

        {(scriptCtx?.questions || []).length > 0 && (
          <div>
            <div className="label" style={{ marginBottom: 8 }}>سوالات فروش</div>
            <div className="col gap-6">
              {scriptCtx.questions.map((q, i) => (
                <div key={i} style={{ padding: '8px 12px', background: 'rgba(108,99,255,0.08)', borderRadius: 8, border: '1px solid rgba(108,99,255,0.2)', fontSize: 13, color: 'var(--text-2)' }}>
                  <span style={{ color: '#a5b4fc', fontWeight: 700, marginLeft: 8 }}>{i + 1}.</span>{q}
                </div>
              ))}
            </div>
          </div>
        )}

        {(scriptCtx?.redLines || []).length > 0 && (
          <div>
            <div className="label" style={{ marginBottom: 8, color: '#F87171' }}>🚫 خط قرمزها</div>
            <div className="col gap-6">
              {scriptCtx.redLines.map((r, i) => (
                <div key={i} style={{ padding: '7px 12px', background: 'rgba(248,113,113,0.07)', border: '1px solid rgba(248,113,113,0.2)', borderRadius: 8, fontSize: 12, color: '#FCA5A5' }}>{r}</div>
              ))}
            </div>
          </div>
        )}

        {(scriptCtx?.guidelines || []).length > 0 && (
          <div>
            <div className="label" style={{ marginBottom: 8, color: '#34D399' }}>✅ راهنمایی‌های ربات</div>
            <div className="col gap-6">
              {scriptCtx.guidelines.map((g, i) => (
                <div key={i} style={{ padding: '7px 12px', background: 'rgba(52,211,153,0.07)', border: '1px solid rgba(52,211,153,0.2)', borderRadius: 8, fontSize: 12, color: '#6EE7B7' }}>{g}</div>
              ))}
            </div>
          </div>
        )}
      </div>
    </Modal>
  );
};

// ─── مرحله ۲: تنظیمات تست ───────────────────────────────
const TestSetupStep = ({
  testMode, setTestMode,
  realScripts, selectedScript, onScriptChange, scriptCtx,
  activeCampaigns, campaignsLoading, campaignsError, onLoadCampaigns,
  selectedCampaign, setSelectedCampaign,
  paceMode, setPaceMode, batchSize, setBatchSize, paceInterval, setPaceInterval,
  onBack, onRun, running, population, fa, SCRIPTS
}) => {
  const { Icon, Button } = window.SB_UI;
  const [showScriptPreview, setShowScriptPreview] = useState(false);
  const [showPace, setShowPace] = useState(false);

  return (
    <div className="col gap-16">
      {/* Header */}
      <div className="card">
        <div className="row between">
          <div>
            <div className="bold" style={{ fontSize: 15 }}>تنظیمات تست</div>
            <div className="text-xs text-3 mt-4">روی {fa(population.length)} نفر اجرا می‌شه</div>
          </div>
          <Button kind="ghost" icon="arrow-right" onClick={onBack}>برگشت به جامعه</Button>
        </div>

        {/* Mode tabs */}
        <div className="row gap-8 mt-16" style={{ alignItems: 'center' }}>
          <span className="label" style={{ margin: 0, flexShrink: 0 }}>اجرا با:</span>
          <button className={`pill ${testMode === 'script' ? 'active' : ''}`} onClick={() => setTestMode('script')}>📄 اسکریپت</button>
          <button className={`pill ${testMode === 'campaign' ? 'active' : ''}`} onClick={() => { setTestMode('campaign'); if (!activeCampaigns.length) onLoadCampaigns(); }}>📢 کمپین</button>
        </div>

        {/* Script selector */}
        {testMode === 'script' && (
          <div className="col gap-10 mt-14">
            <div className="row gap-10" style={{ alignItems: 'flex-end' }}>
              <div style={{ flex: 1 }}>
                <div className="label">اسکریپت</div>
                {realScripts.length > 0 ? (
                  <select className="select" value={selectedScript?.id || ''} onChange={e => { const s = realScripts.find(x => x.id === e.target.value); if (s) onScriptChange(s); }}>
                    {realScripts.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
                  </select>
                ) : (
                  <select className="select">
                    {(SCRIPTS || []).map(s => <option key={s.id}>{s.name}</option>)}
                  </select>
                )}
              </div>
              {selectedScript && (
                <Button kind="ghost" size="sm" icon="eye" onClick={() => setShowScriptPreview(true)}>مشاهده اسکریپت</Button>
              )}
            </div>

            {scriptCtx && (
              <div className="row gap-12" style={{ padding: '10px 14px', background: 'rgba(108,99,255,0.06)', borderRadius: 8, border: '1px solid rgba(108,99,255,0.18)', alignItems: 'center' }}>
                <Icon name="file-text" size={14} color="var(--primary-2)" />
                <div style={{ fontSize: 12, color: 'var(--text-2)' }}>
                  {scriptCtx.scriptName}
                  <span className="text-3"> • {fa(scriptCtx.questions.length)} سوال</span>
                  {scriptCtx.redLines.length > 0 && <span style={{ color: '#F87171' }}> • {fa(scriptCtx.redLines.length)} خط قرمز</span>}
                  {scriptCtx.guidelines.length > 0 && <span style={{ color: '#34D399' }}> • {fa(scriptCtx.guidelines.length)} راهنمایی</span>}
                </div>
              </div>
            )}
          </div>
        )}

        {/* Campaign selector */}
        {testMode === 'campaign' && (
          <div className="col gap-8 mt-14">
            {campaignsLoading ? (
              <div className="row gap-8" style={{ padding: 10, color: 'var(--text-3)', fontSize: 13 }}><Icon name="loader" size={14} />در حال بارگذاری...</div>
            ) : campaignsError ? (
              <div className="col gap-8" style={{ padding: 12, border: '1px solid rgba(248,113,113,0.3)', borderRadius: 8 }}>
                <span className="text-xs" style={{ color: '#F87171' }}>⚠ {campaignsError}</span>
                <Button kind="ghost" size="sm" icon="refresh-cw" onClick={onLoadCampaigns}>تلاش دوباره</Button>
              </div>
            ) : activeCampaigns.length === 0 ? (
              <div className="col gap-8" style={{ padding: 12, border: '1px solid var(--border-soft)', borderRadius: 8 }}>
                <span className="text-xs text-3">کمپینی بارگذاری نشده</span>
                <Button kind="ghost" size="sm" icon="refresh-cw" onClick={onLoadCampaigns}>بارگذاری کمپین‌ها</Button>
              </div>
            ) : (
              <div className="col gap-6">
                {activeCampaigns.map(c => {
                  const isSelected = selectedCampaign?.id === c.id;
                  return (
                    <button key={c.id} onClick={() => setSelectedCampaign(c)}
                      style={{ padding: '12px 14px', borderRadius: 10, cursor: 'pointer', textAlign: 'right', border: `1px solid ${isSelected ? '#6C63FF' : 'var(--border-soft)'}`, background: isSelected ? 'rgba(108,99,255,0.18)' : 'rgba(255,255,255,0.04)', display: 'flex', alignItems: 'center', gap: 12, color: 'var(--text)', width: '100%' }}>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 13, fontWeight: 600, color: isSelected ? '#a5b4fc' : 'var(--text)' }}>{c.name}</div>
                        {c.goal && <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 4 }}>{c.goal}</div>}
                        <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 4, fontFamily: 'monospace' }}>
                          {c.lead_count != null && <span>{fa(c.lead_count)} لید</span>}
                          {c.start_date && <span style={{ marginRight: 8 }}>• {c.start_date}</span>}
                          {c.end_date && <span>← {c.end_date}</span>}
                        </div>
                      </div>
                      <div style={{ width: 18, height: 18, borderRadius: '50%', border: `2px solid ${isSelected ? '#6C63FF' : 'var(--border-soft)'}`, background: isSelected ? '#6C63FF' : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                        {isSelected && <Icon name="check" size={10} color="#fff" strokeWidth={3} />}
                      </div>
                    </button>
                  );
                })}
              </div>
            )}
          </div>
        )}

        {/* Pacing (collapsible) */}
        <div className="mt-16" style={{ borderTop: '1px solid var(--border-soft)', paddingTop: 14 }}>
          <button onClick={() => setShowPace(!showPace)} style={{ display: 'flex', alignItems: 'center', gap: 8, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-3)', fontSize: 13 }}>
            <Icon name={showPace ? 'chevron-up' : 'chevron-down'} size={14} />
            تنظیمات وقفه بین اجراها (اجرای زمان‌بندی‌شده)
          </button>
          {showPace && (
            <div className="col gap-14 mt-12">
              <div className="row gap-8" style={{ alignItems: 'center' }}>
                <span className="label" style={{ margin: 0 }}>حالت:</span>
                <button className={`pill ${paceMode === 'instant' ? 'active' : ''}`} onClick={() => setPaceMode('instant')}>⚡ فوری</button>
                <button className={`pill ${paceMode === 'paced' ? 'active' : ''}`} onClick={() => setPaceMode('paced')}>⏱ زمان‌بندی‌شده</button>
              </div>
              {paceMode === 'paced' && (
                <div className="grid grid-2 gap-14">
                  <div>
                    <div className="label">{fa(batchSize)} نفر هر دفعه</div>
                    <input type="range" min={1} max={50} step={1} value={batchSize} onChange={e => setBatchSize(Number(e.target.value))} style={{ width: '100%', accentColor: '#6C63FF' }} />
                  </div>
                  <div>
                    <div className="label">هر {fa(paceInterval)} ثانیه</div>
                    <input type="range" min={5} max={300} step={5} value={paceInterval} onChange={e => setPaceInterval(Number(e.target.value))} style={{ width: '100%', accentColor: '#6C63FF' }} />
                  </div>
                  <div className="col" style={{ gridColumn: '1/-1', padding: '8px 12px', background: 'rgba(108,99,255,0.07)', borderRadius: 8, border: '1px solid rgba(108,99,255,0.2)' }}>
                    <span className="text-xs" style={{ color: 'var(--primary-2)' }}>📊 {fa(batchSize)} نفر هر {fa(paceInterval)} ثانیه — زمان کل: ~{fa(Math.ceil((population.length / batchSize) * paceInterval))} ثانیه</span>
                  </div>
                </div>
              )}
            </div>
          )}
        </div>

        {/* Run button */}
        <div className="row gap-8 mt-16" style={{ justifyContent: 'flex-end' }}>
          <Button kind="primary" icon="play" loading={running} onClick={onRun}>
            {running ? 'در حال اجرا...' : `اجرای تست روی ${fa(population.length)} نفر ←`}
          </Button>
        </div>
      </div>

      {showScriptPreview && (
        <ScriptPreviewModal open={showScriptPreview} onClose={() => setShowScriptPreview(false)} scriptCtx={scriptCtx} scriptName={selectedScript?.name} />
      )}
    </div>
  );
};

// ─── تاریخچه تست‌ها — همیشه بالای صفحه ─────────────────
const TestHistory = ({ savedPops, onLoad, onDelete, onRefresh, fa }) => {
  const { Icon, Button } = window.SB_UI;
  const [open, setOpen] = useState(true);

  // جداسازی تست‌های کامل (با نتیجه) از جامعه‌های بدون نتیجه
  const withResults = savedPops.filter(p => p.conv && p.conv !== '0');
  const withoutResults = savedPops.filter(p => !p.conv || p.conv === '0');

  const CAT_COLOR = { ready: '#10B981', warm: '#F59E0B', cold: '#3B82F6', unfit: '#6B7280' };

  const convColor = (conv) => {
    const v = parseFloat(conv);
    if (v >= 30) return '#10B981';
    if (v >= 15) return '#F59E0B';
    return '#6B7280';
  };

  const fmtDate = (d) => {
    if (!d) return '';
    try { return new Date(d).toLocaleDateString('fa-IR', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); }
    catch { return d.slice(0, 16); }
  };

  return (
    <div className="card" style={{ border: '1px solid var(--border-soft)' }}>
      <button onClick={() => setOpen(o => !o)} style={{ display: 'flex', alignItems: 'center', gap: 10, width: '100%', background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}>
        <Icon name="history" size={15} color="var(--primary-2)" />
        <span className="bold text-sm" style={{ flex: 1, textAlign: 'right', color: 'var(--text)' }}>تاریخچه تست‌ها</span>
        <span className="mono text-xs text-3">{fa(savedPops.length)} مورد</span>
        <Icon name={open ? 'chevron-up' : 'chevron-down'} size={14} color="var(--text-3)" />
        <button onClick={e => { e.stopPropagation(); onRefresh(); }} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '2px 4px' }} title="رفرش">
          <Icon name="refresh-cw" size={12} color="var(--text-3)" />
        </button>
      </button>

      {open && (
        <div className="mt-14">
          {savedPops.length === 0 ? (
            <div className="row gap-8" style={{ padding: '14px 0', color: 'var(--text-3)', fontSize: 13 }}>
              <Icon name="inbox" size={16} color="var(--text-3)" />
              هنوز تستی ذخیره نشده — بعد از اجرای تست، به‌صورت خودکار ذخیره می‌شه
            </div>
          ) : (
            <>
              {withResults.length > 0 && (
                <div className="col gap-6">
                  <div className="text-xs text-3 semi" style={{ marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.05em' }}>
                    گزارش‌های کامل ({fa(withResults.length)})
                  </div>
                  {withResults.map(p => (
                    <div key={p.id}
                      onClick={() => onLoad(p.id)}
                      style={{ padding: '10px 14px', borderRadius: 10, cursor: 'pointer', border: '1px solid var(--border-soft)', background: 'rgba(15,15,26,0.4)', display: 'flex', gap: 14, alignItems: 'center', transition: 'border-color 0.15s' }}
                      onMouseEnter={e => e.currentTarget.style.borderColor = 'rgba(108,99,255,0.5)'}
                      onMouseLeave={e => e.currentTarget.style.borderColor = 'var(--border-soft)'}>
                      <div style={{ width: 42, height: 42, borderRadius: 10, background: `${convColor(p.conv)}18`, border: `1px solid ${convColor(p.conv)}44`, display: 'grid', placeItems: 'center', flexShrink: 0 }}>
                        <span className="mono bold" style={{ fontSize: 13, color: convColor(p.conv) }}>{fa(p.conv)}%</span>
                      </div>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div className="row gap-8" style={{ alignItems: 'center' }}>
                          <div className="text-sm semi" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: 'var(--text)' }}>{p.name}</div>
                          {p.test_mode === 'campaign'
                            ? <span style={{ fontSize: 10, padding: '2px 7px', borderRadius: 5, background: 'rgba(251,146,60,0.15)', color: '#FB923C', border: '1px solid rgba(251,146,60,0.3)', flexShrink: 0 }}>📢 کمپین</span>
                            : <span style={{ fontSize: 10, padding: '2px 7px', borderRadius: 5, background: 'rgba(99,102,241,0.12)', color: '#818CF8', border: '1px solid rgba(99,102,241,0.25)', flexShrink: 0 }}>📄 اسکریپت</span>
                          }
                        </div>
                        <div className="text-xs text-3 mono mt-3">
                          {fa(p.total)} نفر
                          {p.test_mode === 'campaign' ? ` • ${p.campaign_name || '—'}` : ` • ${p.script_name || '—'}`}
                          {p.avg_msg && p.avg_msg !== '0' && <span> • میانگین {fa(p.avg_msg)} پیام</span>}
                        </div>
                        <div className="text-xs text-3 mt-2">{fmtDate(p.created_at)}</div>
                      </div>
                      <div className="col gap-4" style={{ alignItems: 'flex-end' }}>
                        <button onClick={e => { e.stopPropagation(); onDelete(p.id, e); }}
                          style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-3)', fontSize: 11, padding: '2px 6px' }}>حذف</button>
                        <Icon name="chevron-left" size={13} color="var(--text-3)" />
                      </div>
                    </div>
                  ))}
                </div>
              )}

              {withoutResults.length > 0 && (
                <div className="col gap-6 mt-12">
                  <div className="text-xs text-3 semi" style={{ marginBottom: 6, textTransform: 'uppercase', letterSpacing: '0.05em' }}>
                    جامعه‌های بدون تست ({fa(withoutResults.length)})
                  </div>
                  {withoutResults.map(p => (
                    <div key={p.id}
                      onClick={() => onLoad(p.id)}
                      style={{ padding: '8px 14px', borderRadius: 10, cursor: 'pointer', border: '1px solid var(--border-soft)', background: 'rgba(255,255,255,0.03)', display: 'flex', gap: 12, alignItems: 'center' }}
                      onMouseEnter={e => e.currentTarget.style.borderColor = 'rgba(108,99,255,0.4)'}
                      onMouseLeave={e => e.currentTarget.style.borderColor = 'var(--border-soft)'}>
                      <Icon name="users" size={16} color="var(--text-3)" style={{ flexShrink: 0 }} />
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div className="text-sm" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', color: 'var(--text-2)' }}>{p.name}</div>
                        <div className="text-xs text-3 mono mt-2">{fa(p.total)} نفر • {fmtDate(p.created_at)}</div>
                      </div>
                      <div className="row gap-8" style={{ alignItems: 'center' }}>
                        <button onClick={e => { e.stopPropagation(); onDelete(p.id, e); }}
                          style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-3)', fontSize: 11 }}>حذف</button>
                        <Icon name="chevron-left" size={13} color="var(--text-3)" />
                      </div>
                    </div>
                  ))}
                </div>
              )}
            </>
          )}
        </div>
      )}
    </div>
  );
};

const SavedPopSelector = ({ savedPops, onLoad, onDelete, onRefresh, fa }) => {
  const { Icon, Button } = window.SB_UI;
  const [selectedId, setSelectedId] = useState('');
  const selected = savedPops.find(p => p.id === selectedId);

  return (
    <div className="card" style={{ border: '1px solid var(--border-soft)', background: 'rgba(108,99,255,0.04)' }}>
      <div className="row between" style={{ alignItems: 'center', marginBottom: 14 }}>
        <div className="row gap-8" style={{ alignItems: 'center' }}>
          <Icon name="folder-open" size={15} color="var(--primary-2)" />
          <span className="bold text-sm">بارگذاری جامعه ذخیره‌شده</span>
        </div>
        <button className="icon-btn" style={{ width: 28, height: 28 }} onClick={onRefresh} title="رفرش لیست">
          <Icon name="refresh-cw" size={12} />
        </button>
      </div>

      {savedPops.length === 0 ? (
        <div className="row gap-8" style={{ padding: '10px 14px', border: '1px dashed var(--border-soft)', borderRadius: 10, alignItems: 'center' }}>
          <Icon name="inbox" size={16} color="var(--text-3)" />
          <span className="text-xs text-3">هنوز جامعه‌ای ذخیره نشده — بعد از ساخت جامعه روی «ذخیره» کلیک کن</span>
        </div>
      ) : (
        <div className="col gap-10">
          {/* Dropdown */}
          <div className="row gap-10">
            <select className="select" style={{ flex: 1 }} value={selectedId} onChange={e => { const id = e.target.value; setSelectedId(id); if (id) onLoad(id); }}>
              <option value="">— انتخاب جامعه —</option>
              {savedPops.map(p => (
                <option key={p.id} value={p.id}>
                  {p.name} ({fa(p.total)} نفر{p.conv && p.conv !== '0' ? ` · نرخ ${fa(p.conv)}%` : ''})
                </option>
              ))}
            </select>
          </div>

          {/* Preview of selected */}
          {selected && (
            <div className="row gap-12" style={{ padding: '10px 14px', border: '1px solid rgba(108,99,255,0.3)', borderRadius: 10, background: 'rgba(108,99,255,0.08)', alignItems: 'center' }}>
              <Icon name="users" size={16} color="var(--primary-2)" />
              <div style={{ flex: 1 }}>
                <div className="text-sm semi">{selected.name}</div>
                <div className="text-xs text-3 mono mt-4">
                  {fa(selected.total)} نفر
                  {' • '}
                  {selected.test_mode === 'campaign' ? `📢 ${selected.campaign_name || 'کمپین'}` : `📄 ${selected.script_name || 'اسکریپت'}`}
                  {selected.conv && selected.conv !== '0' && <span style={{ color: '#34D399' }}> • نرخ تبدیل: {fa(selected.conv)}%</span>}
                </div>
              </div>
              <button onClick={e => { onDelete(selected.id, e); setSelectedId(''); }}
                style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#F87171', fontSize: 12, padding: '4px 8px' }}>
                حذف
              </button>
            </div>
          )}
        </div>
      )}
    </div>
  );
};

// کلمات کلیدی هر دغدغه برای تطبیق با خط قرمزها
const CONCERN_KEYWORDS = {
  price:      ['قیمت','هزینه','گران','ارزان','تخفیف','پول','بودجه'],
  trust:      ['ضمانت','اثبات','مدرک','مطمئن','اعتماد','تضمین'],
  family:     ['خانواده','مشورت','همسر','پدر','مادر','والدین'],
  roi:        ['بازگشت','سود','درآمد','نتیجه','ROI'],
  comparison: ['رقیب','مقایسه','بهتر از','جای دیگه','آلترناتیو'],
  security:   ['کلاهبرداری','امنیت','ریسک','ضرر','از دست'],
  time:       ['وقت','زمان','مشغله','سریع','فوری'],
  proof:      ['علمی','تحقیق','منبع','مستندات','دانشگاه'],
  support:    ['پشتیبانی','کمک','اشکال','مشکل','تماس'],
  social:     ['دیگران','دوستام','نظر','بقیه'],
  learning:   ['یاد گرفتن','سخت','پیچیده','بلد نیستم'],
  urgency:    ['عجله','سریع','الان','فوری'],
};

const concernMatchesRedLine = (concern, redLines) => {
  const kws = CONCERN_KEYWORDS[concern] || [concern];
  return redLines.find(rl => kws.some(kw => rl.includes(kw))) || null;
};

const generateConversation = (person, cat, campaignCtx = null, scriptCtx = null) => {
  const { persona, budget, channel } = person;
  let h = 9 + Math.floor(Math.random() * 9);
  let m = Math.floor(Math.random() * 40);
  const tick = (d = 1 + Math.floor(Math.random() * 3)) => {
    m += d; if (m >= 60) { h = Math.min(h + 1, 22); m -= 60; }
    return `${h}:${String(m).padStart(2, '0')}`;
  };
  const hasConcern = id => Array.isArray(persona.concerns) && persona.concerns.includes(id);
  const budgetM = Math.round(budget / 1_000_000);
  const gT = { male: 'آقا', female: 'خانم', any: '' }[persona.gender] || '';
  const msgs = [];

  // سوالات واقعی از اسکریپت — اگه نبود، فالبک generic
  const scriptQs = (scriptCtx?.questions || []).filter(q => q && q.trim().length > 3);
  const redLines = scriptCtx?.redLines || [];
  const guidelines = scriptCtx?.guidelines || [];

  // ─── سلام ───────────────────────────────────────
  const greeting = campaignCtx
    ? `سلام${gT ? ' ' + gT : ''}! کمپین «${campaignCtx.name}» رو دیدم 👋\nخوش اومدید، چطور می‌تونم کمکتون کنم؟`
    : `سلام${gT ? ' ' + gT : ''}! خوش اومدید 👋\nچطور می‌تونم کمکتون کنم؟`;
  msgs.push({ from: 'bot', text: greeting, time: tick(0) });

  // ─── معرفی کاربر ────────────────────────────────
  const openers = { 'اینستاگرام': 'از پستتون اومدم.', 'تلگرام': 'از کانالتون آدرس گرفتم.', 'واتساپ': 'شمارتون رو از یه دوست گرفتم.', 'دایرکت': 'محتواتون رو دیدم.', 'سایت': 'از سایتتون فرم پر کردم.' };
  msgs.push({ from: 'user', text: openers[channel] || 'می‌خواستم اطلاعات بگیرم.', time: tick() });

  // ─── سوالات واقعی از اسکریپت ───────────────────
  let qIdx = 0;
  const nextQ = () => scriptQs[qIdx++] || null;

  // سوال اول از اسکریپت یا fallback
  const q1 = nextQ();
  msgs.push({ from: 'bot', text: q1 || 'برای اینکه بهتر کمکتون کنم، هدف اصلیتون از این کار چیه؟', time: tick() });

  // پاسخ کاربر (بر اساس سطح درآمد)
  const answersByIncome = {
    low:       ['می‌خوام یاد بگیرم ولی بودجه محدودم.', 'دنبال یه راه‌حل ارزون‌تری هستم.'],
    medium:    ['می‌خوام تغییر ملموسی ایجاد کنم.', 'نتیجه‌ای می‌خوام که ارزش هزینه‌اش رو داشته باشه.'],
    high:      ['به نتیجه می‌خوام برسم، هزینه مشکلی نیست.', 'بهترین گزینه رو می‌خوام.'],
    very_high: ['وقتم محدوده، می‌خوام سریع نتیجه بگیرم.', 'تیمم نیاز داره.'],
  };
  const incomeAnss = answersByIncome[persona.income] || answersByIncome.medium;
  msgs.push({ from: 'user', text: incomeAnss[Math.floor(Math.random() * incomeAnss.length)], time: tick() });

  // سوال دوم از اسکریپت
  const q2 = nextQ();
  if (q2) {
    msgs.push({ from: 'bot', text: q2, time: tick() });
    msgs.push({ from: 'user', text: persona.occupation ? `${persona.occupation} هستم، ${budgetM > 15 ? 'بودجه خوبی دارم' : 'بودجه‌ام محدوده'}.` : 'بذارید فکر کنم...', time: tick() });
  }

  // ─── دغدغه‌ها — با تطبیق خط قرمز ──────────────
  const activeConcerns = (persona.concerns || []).slice(0, 3);
  for (const concern of activeConcerns) {
    const matchedRedLine = concernMatchesRedLine(concern, redLines);
    if (matchedRedLine) {
      // خط قرمز فعال شد — ربات نمی‌تونه وارد این بحث بشه
      const concernUserText = {
        price: 'راستش قیمتش برام مهمه.', trust: 'چطور مطمئن بشم؟',
        family: 'باید با خانواده‌ام صحبت کنم.', roi: 'بازگشت سرمایه‌اش چیه؟',
        comparison: 'با رقباتون چه فرقی دارید؟', security: 'ضمانتی هست؟',
        time: 'وقتم خیلی کمه.', proof: 'مستندات علمی دارید؟',
      }[concern] || 'یه سوال داشتم.';
      msgs.push({ from: 'user', text: concernUserText, time: tick() });
      msgs.push({ from: 'bot', text: `⚠️ [خط قرمز: ${matchedRedLine}]\nاین موضوع خارج از حوزه‌ای هست که می‌تونم کمک کنم. بذارید به سوال بعدی برگردیم.`, time: tick() });
    } else {
      // دغدغه عادی — ربات پاسخ می‌ده
      const responses = {
        price:      ['متوجه‌ام. ارزشی که می‌گیرید رو بذارید با هم بررسی کنیم.', 'بیشتر از هزینه، ارزش بلند‌مدتی که می‌گیرید مهمه.'],
        trust:      ['سوال منطقیه. می‌تونم نمونه نتایج واقعی نشون بدم.', 'سابقه خوبی داریم، می‌تونم مستندات بفرستم.'],
        family:     ['کاملا درک می‌کنم. می‌تونم یه تماس با حضور خانواده داشته باشیم.', 'بروشور کامل می‌فرستم که با هم بررسی کنید.'],
        roi:        ['بازگشت سرمایه بستگی داره به نحوه استفاده. مثال واقعی می‌زنم.', 'مشتریان قبلی چه تجربه‌ای داشتن؟ نشون می‌دم.'],
        time:       ['برنامه طراحی شده برای آدم‌های پرمشغله. روزانه ۲۰ دقیقه کافیه.', 'فشرده‌ترین مسیر ممکن رو انتخاب می‌کنیم.'],
        support:    ['پشتیبانی تمام وقت دارید. هر وقت مشکلی بود تماس بگیرید.', 'تیم پشتیبانی ۷ روز هفته در دسترسه.'],
        security:   ['ضمانت بازگشت وجه داریم. ریسکی نیست.', 'قرارداد کامل می‌بندیم.'],
        comparison: ['هر کدوم نقاط قوت خودشون رو دارن. تخصص ما اینه که...', 'مقایسه‌ای آماده دارم که کمک می‌کنه.'],
        proof:      ['بله مستندات داریم. case study‌های مشابه می‌فرستم.'],
        social:     ['خیلی از مشتریانمون همین مسیر رو رفتن. نتایجشون رو نشون می‌دم.'],
        urgency:    ['اگه الان تصمیم بگیرید می‌تونیم سریع‌تر شروع کنیم.'],
      };
      const resp = responses[concern];
      if (resp) {
        const cUserText = { price: 'این برام گرونه...', trust: 'چطور مطمئن بشم؟', family: 'باید مشورت کنم.', roi: 'بازگشت سرمایه‌اش چیه؟', time: 'وقتم کمه.', support: 'اگه مشکلی پیش بیاد چی؟', security: 'ریسکش زیاده.', comparison: 'با بقیه چه فرقی دارید؟', proof: 'دلیل علمی دارید؟', social: 'دوستام چی می‌گن؟', urgency: 'باید سریع تصمیم بگیرم؟' }[concern] || 'یه نکته داشتم...';
        msgs.push({ from: 'user', text: cUserText, time: tick() });
        msgs.push({ from: 'bot', text: resp[Math.floor(Math.random() * resp.length)], time: tick() });
      }
    }
  }

  // ─── سوال سوم از اسکریپت ─────────────────────
  const q3 = nextQ();
  if (q3) {
    msgs.push({ from: 'bot', text: q3, time: tick() });
    msgs.push({ from: 'user', text: budgetM > 15 ? 'بله، کافیه.' : 'سعی می‌کنم جور کنم.', time: tick() });
  }

  // ─── پایان‌بندی بر اساس cat ───────────────────
  if (cat === 'ready') {
    msgs.push({ from: 'bot', text: guidelines.length ? `${guidelines[0]} — می‌خواید ادامه بدیم؟` : 'عالیه! می‌خواید همین الان شروع کنیم؟', time: tick(2) });
    msgs.push({ from: 'user', text: 'بله، بفرمایید.', time: tick() });
    msgs.push({ from: 'bot', text: 'خوشحال می‌شیم همراهتون باشیم ✅', time: tick() });
  } else if (cat === 'warm') {
    msgs.push({ from: 'bot', text: q3 ? 'ممنون از پاسخ‌هاتون. می‌تونم پیگیری کنم؟' : 'چه چیزی مانع تصمیم‌گیریه؟', time: tick(2) });
    msgs.push({ from: 'user', text: 'بذارید فکر کنم. خبر می‌دم.', time: tick() });
    msgs.push({ from: 'bot', text: 'حتما. منتظرم 🙏', time: tick() });
  } else if (cat === 'cold') {
    msgs.push({ from: 'user', text: 'فعلا نه، ممنون.', time: tick(2) });
    msgs.push({ from: 'bot', text: 'اشکالی نداره. اگه نظرتون عوض شد در خدمتم.', time: tick() });
  } else {
    msgs.push({ from: 'user', text: 'فکر نکنم به دردم بخوره.', time: tick(2) });
    msgs.push({ from: 'bot', text: 'ممنون از صداقتتون. موفق باشید.', time: tick() });
  }

  return msgs;
};

// ─── تب ساخت جامعه ──────────────────────────────────────
const CommunityBuilderTab = ({ savedPops, onRefresh, onDelete }) => {
  const { Icon, Button, useToast } = window.SB_UI;
  const { PERSONAS, FAKE_FIRST_NAMES, FAKE_LAST_NAMES, FAKE_CHANNELS, FAKE_CITIES, fa } = window.SB_DATA;
  const toast = useToast();
  const [total, setTotal] = useState(100);
  const [personas, setPersonas] = useState(PERSONAS);
  const [weights, setWeights] = useState(PERSONAS.map(() => 25));
  const [building, setBuilding] = useState(false);
  const [addOpen, setAddOpen] = useState(false);
  const [editIdx, setEditIdx] = useState(null);
  const [popName, setPopName] = useState('');
  const weightSum = weights.reduce((s, w) => s + w, 0);

  const PALETTE = ['#6C63FF', '#FF6B35', '#10B981', '#F59E0B', '#3B82F6', '#8B5CF6', '#EC4899', '#06B6D4', '#84CC16', '#F97316'];
  const EMOJIS = ['👔', '🎨', '🚀', '🎓', '💼', '🧑‍💻', '🛍️', '📊', '🏢', '🎯', '🧠', '🦄', '🛠️', '📱', '💎', '🌟', '🏡', '👴', '👩', '📚', '🏛️', '🩺', '⚡', '🎭', '👨‍🌾', '🧑‍🍳', '👷', '🧑‍🎓', '🎪', '🌾', '🏥', '✂️', '🛒', '🧕', '👩‍💼', '🧓'];

  const upsertPersona = (data) => {
    if (editIdx !== null) {
      const nextP = [...personas]; nextP[editIdx] = { ...nextP[editIdx], ...data };
      setPersonas(nextP);
      toast('پرسونا ویرایش شد', 'success');
    } else {
      setPersonas(prev => [...prev, { id: Date.now(), custom: true, ...data }]);
      setWeights(prev => [...prev, 20]);
      toast('پرسونای جدید اضافه شد', 'success');
    }
    setAddOpen(false);
    setEditIdx(null);
  };

  const deletePersona = (i) => {
    if (personas.length <= 2) return toast('حداقل باید ۲ پرسونا داشته باشی', 'error');
    setPersonas(personas.filter((_, idx) => idx !== i));
    setWeights(weights.filter((_, idx) => idx !== i));
  };

  const build = () => {
    const trimmed = popName.trim();
    if (!trimmed) return toast('یک نام برای جامعه بنویس', 'error');
    if (savedPops.some(p => p.name === trimmed)) return toast(`جامعه‌ای با نام «${trimmed}» قبلاً ثبت شده`, 'error');
    setBuilding(true);
    setTimeout(async () => {
      const pop = buildPopulation(total, weights, personas, FAKE_FIRST_NAMES, FAKE_LAST_NAMES, FAKE_CHANNELS, FAKE_CITIES);
      try {
        const result = await window.api('/lab/populations', { method: 'POST', body: {
          name: trimmed,
          total: pop.length,
          personas,
          weights,
          people: pop,
        }});
        if (result?.error) { toast(result.error, 'error'); setBuilding(false); return; }
        onRefresh();
        setPopName('');
        toast(`جامعه «${trimmed}» با ${fa(total)} نفر ساخته و ذخیره شد ✓`, 'success');
      } catch (e) {
        toast('خطا در ذخیره', 'error');
      }
      setBuilding(false);
    }, 900);
  };

  return (
    <div className="col gap-16">

      {/* ─── لیست جامعه‌های ذخیره‌شده ─── */}
      <div className="card">
        <div className="row between" style={{ marginBottom: 12 }}>
          <div className="row gap-8" style={{ alignItems: 'center' }}>
            <Icon name="folder" size={15} color="var(--primary-2)" />
            <span className="bold text-sm">جامعه‌های ذخیره‌شده</span>
            <span className="mono text-xs text-3">({fa(savedPops.length)} مورد)</span>
          </div>
          <button className="icon-btn" style={{ width: 28, height: 28 }} onClick={onRefresh} title="رفرش">
            <Icon name="refresh-cw" size={12} />
          </button>
        </div>
        {savedPops.length === 0 ? (
          <div className="row gap-8" style={{ padding: '10px 14px', border: '1px dashed var(--border-soft)', borderRadius: 10, alignItems: 'center' }}>
            <Icon name="inbox" size={16} color="var(--text-3)" />
            <span className="text-xs text-3">هنوز جامعه‌ای ساخته نشده</span>
          </div>
        ) : (
          <div style={{ maxHeight: 220, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 6 }}>
            {savedPops.map(p => (
              <div key={p.id} className="row gap-10" style={{ padding: '8px 12px', border: '1px solid var(--border-soft)', borderRadius: 8, background: 'rgba(15,15,26,0.3)', alignItems: 'center', flexShrink: 0 }}>
                <Icon name="users" size={13} color="var(--primary-2)" />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <span className="text-sm semi">{p.name}</span>
                  <span className="mono text-xs text-3" style={{ marginRight: 8 }}>{fa(p.total)} نفر</span>
                  {p.conv && p.conv !== '0' && <span className="text-xs" style={{ color: '#34D399' }}>· {fa(p.conv)}%</span>}
                </div>
                <button onClick={e => onDelete(p.id, e)} style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#F87171', padding: '2px 6px', fontSize: 11, flexShrink: 0 }}>حذف</button>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* ─── ساخت جامعه جدید ─── */}
      <div className="card">
        <div className="row between" style={{ alignItems: 'flex-start' }}>
          <div>
            <div className="bold" style={{ fontSize: 15 }}>ساخت جامعه جدید</div>
            <div className="text-xs text-3 mt-4">پرسوناها، توزیع و تعداد رو مشخص کن</div>
            <div className="row gap-8 mt-10" style={{ alignItems: 'center' }}>
              <Icon name="tag" size={13} color="var(--text-3)" />
              <input className="input" placeholder="نام جامعه — مثلا: تهران بهار ۱۴۰۳" value={popName} onChange={e => setPopName(e.target.value)} style={{ width: 280, padding: '6px 10px', fontSize: 12 }} />
            </div>
          </div>
          <div className="col gap-8" style={{ alignItems: 'flex-end' }}>
            <Button kind="primary" icon="sparkles" loading={building} onClick={build}>{building ? 'در حال ساخت...' : `ساخت جامعه (${fa(total)} نفر) ←`}</Button>
            <div className="row gap-8">
              {[10, 50, 100, 500, 1000].map(n => (
                <button key={n} className={`pill ${total === n ? 'active' : ''}`} onClick={() => setTotal(n)}>{fa(n)}</button>
              ))}
            </div>
          </div>
        </div>
        <div className="divider"></div>
        <div className="label">تعداد کل: <span className="mono bold" style={{ color: 'var(--primary-2)' }}>{fa(total)}</span> نفر</div>
        <input type="range" min={10} max={1000} step={10} value={total} onChange={e => setTotal(Number(e.target.value))} style={{ width: '100%', accentColor: '#6C63FF' }} />
        <div className="row between text-xs text-3 mono mt-4"><span>{fa(10)}</span><span>{fa(250)}</span><span>{fa(500)}</span><span>{fa(750)}</span><span>{fa(1000)}</span></div>
        <div className="divider"></div>
        <div className="row between">
          <div className="label" style={{ margin: 0 }}>توزیع پرسوناها</div>
          <div className="row gap-8">
            <button className="pill" onClick={() => setWeights(personas.map(() => 25))}>یکنواخت</button>
            <button className="pill" onClick={() => { const arr = [40, 30, 20, 10]; setWeights(personas.map((_, i) => arr[i] ?? 5)); }}>واقع‌گرایانه</button>
            <button className="pill" onClick={() => setWeights(personas.map(() => Math.round(Math.random() * 40 + 10)))}>تصادفی</button>
          </div>
        </div>
        <div className="col gap-12 mt-12">
          {personas.map((p, i) => {
            const pct = weightSum > 0 ? Math.round((weights[i] / weightSum) * 100) : 0;
            const planned = Math.round((weights[i] / weightSum) * total);
            return (
              <div key={p.id} className="row gap-16" style={{ padding: 12, background: 'rgba(15,15,26,0.4)', border: '1px solid var(--border-soft)', borderRadius: 12 }}>
                <div style={{ width: 38, height: 38, borderRadius: 50, background: `linear-gradient(135deg, ${p.color}, ${p.color}66)`, display: 'grid', placeItems: 'center', fontSize: 18, flexShrink: 0 }}>{p.emoji}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div className="row between">
                    <div className="row gap-8">
                      <span className="text-sm semi">{p.name}</span>
                      {p.custom && <span className="badge sold solid" style={{ fontSize: 10, background: 'rgba(255,107,53,0.16)', color: '#FB923C' }}>سفارشی</span>}
                    </div>
                    <span className="mono text-xs"><span className="bold" style={{ color: p.color }}>{fa(pct)}%</span><span className="text-3"> • {fa(planned)} نفر</span></span>
                  </div>
                  <div className="row gap-6 mt-4" style={{ flexWrap: 'wrap' }}>
                    {p.occupation && <span className="text-xs" style={{ padding: '1px 6px', background: 'rgba(255,255,255,0.06)', borderRadius: 4, color: 'var(--text-3)' }}>{p.occupation}</span>}
                    {p.region && <span className="text-xs" style={{ padding: '1px 6px', background: 'rgba(255,255,255,0.06)', borderRadius: 4, color: 'var(--text-3)' }}>{{ tehran:'تهران', big_city:'شهر بزرگ', small_city:'شهر کوچک', rural:'روستا' }[p.region]}</span>}
                    {p.income && <span className="text-xs" style={{ padding: '1px 6px', background: `${p.color}22`, borderRadius: 4, color: p.color }}>{{ low:'کم', medium:'متوسط', high:'بالا', very_high:'مرفه' }[p.income]}</span>}
                    {Array.isArray(p.concerns) && p.concerns.length > 0 && <span className="text-xs" style={{ padding: '1px 6px', background: 'rgba(255,255,255,0.04)', borderRadius: 4, color: 'var(--text-3)' }}>⚡ {fa(p.concerns.length)} دغدغه</span>}
                  </div>
                  <input type="range" min={0} max={100} step={5} value={weights[i]} onChange={e => { const next = [...weights]; next[i] = Number(e.target.value); setWeights(next); }} style={{ width: '100%', accentColor: p.color, marginTop: 8 }} />
                </div>
                <div className="col gap-4">
                  <button className="icon-btn" style={{ width: 28, height: 28 }} onClick={() => { setEditIdx(i); setAddOpen(true); }}><Icon name="edit-3" size={12} /></button>
                  <button className="icon-btn" style={{ width: 28, height: 28 }} onClick={() => deletePersona(i)}><Icon name="trash-2" size={12} color="#F87171" /></button>
                </div>
              </div>
            );
          })}
        </div>
        <PersonaModal open={addOpen} onClose={() => { setAddOpen(false); setEditIdx(null); }} initial={editIdx !== null ? personas[editIdx] : null} palette={PALETTE} emojis={EMOJIS} onSave={upsertPersona} />
      </div>
    </div>
  );
};

// ─── تب اجرای تست ───────────────────────────────────────
const RunTestTab = ({ savedPops, onRefresh }) => {
  const { Icon, Button, useToast } = window.SB_UI;
  const { SCRIPTS, fa } = window.SB_DATA;
  const toast = useToast();
  const [selectedPopId, setSelectedPopId] = useState('');
  const [population, setPopulation] = useState([]);
  const [popMeta, setPopMeta] = useState(null);
  const [loadingPop, setLoadingPop] = useState(false);
  const [testMode, setTestMode] = useState('script');
  const [selectedScript, setSelectedScript] = useState(null);
  const [scriptCtx, setScriptCtx] = useState(null);
  const [realScripts, setRealScripts] = useState([]);
  const [selectedCampaign, setSelectedCampaign] = useState(null);
  const [activeCampaigns, setActiveCampaigns] = useState([]);
  const [campaignsLoading, setCampaignsLoading] = useState(false);
  const [campaignsError, setCampaignsError] = useState('');
  const [paceMode, setPaceMode] = useState('instant');
  const [batchSize, setBatchSize] = useState(10);
  const [paceInterval, setPaceInterval] = useState(30);
  const [running, setRunning] = useState(false);
  const [results, setResults] = useState(null);
  const [progress, setProgress] = useState(null);
  const [autoSavedId, setAutoSavedId] = useState(null);
  const [showPace, setShowPace] = useState(false);
  const [showScriptPreview, setShowScriptPreview] = useState(false);
  const intervalRef = useRef(null);
  const processedRef = useRef(0);
  const enrichedRef = useRef([]);
  const testConfigRef = useRef({});
  const personasRef = useRef([]);

  useEffect(() => {
    window.api('/lab/scripts').then(data => {
      if (Array.isArray(data) && data.length) {
        setRealScripts(data);
        setSelectedScript(data[0]);
        loadScriptCtx(data[0].id);
      }
    }).catch(() => {});
  }, []);

  const loadScriptCtx = (scriptId) => {
    if (!scriptId) return;
    window.api('/lab/script-context/' + scriptId).then(data => {
      if (data && !data.error) setScriptCtx(data);
    }).catch(() => {});
  };

  const loadCampaigns = () => {
    setCampaignsLoading(true);
    setCampaignsError('');
    window.api('/campaigns/campaigns').then(data => {
      setCampaignsLoading(false);
      if (Array.isArray(data)) {
        const active = data.filter(c => c.is_active);
        setActiveCampaigns(active);
        if (active.length === 0) setCampaignsError('هیچ کمپین فعالی وجود نداره');
      } else {
        setCampaignsError('خطا در بارگذاری');
      }
    }).catch(() => { setCampaignsLoading(false); setCampaignsError('خطای شبکه'); });
  };

  const selectPop = async (id) => {
    setSelectedPopId(id);
    setResults(null);
    if (!id) { setPopulation([]); setPopMeta(null); return; }
    setLoadingPop(true);
    try {
      const data = await window.api('/lab/populations/' + id);
      if (data && Array.isArray(data.people)) {
        setPopulation(data.people);
        setPopMeta(data);
        personasRef.current = data.personas || [];
        toast(`جامعه «${data.name}» انتخاب شد`, 'success');
      }
    } catch (e) { toast('خطا در بارگذاری جامعه', 'error'); }
    setLoadingPop(false);
  };

  const PERSONA_BASE = { 1: 0.18, 2: 0.32, 3: 0.45, 4: 0.12, 5: 0.22, 6: 0.08, 7: 0.35 };
  const processOnePerson = (p, mode, campaign, ctx) => {
    const baseConv = p.persona.custom ? 0.20 + Math.random() * 0.2 : (PERSONA_BASE[p.persona.id] || 0.25);
    const budgetBoost = p.budget >= 15_000_000 ? 0.15 : p.budget >= 8_000_000 ? 0.05 : -0.05;
    const channelBoost = p.channel === 'اینستاگرام' ? 0.05 : p.channel === 'دایرکت' ? 0.08 : 0;
    const techBoost = p.persona.techLevel ? (p.persona.techLevel - 3) * 0.025 : 0;
    const incomeBoost = { low: -0.04, medium: 0, high: 0.06, very_high: 0.10 }[p.persona.income] || 0;
    const socialBoost = { lower: -0.08, working: -0.04, middle: 0, upper_middle: 0.05, upper: 0.08 }[p.persona.socialClass] || 0;
    const regionBoost = { tehran: 0.04, big_city: 0.02, small_city: -0.02, rural: -0.05 }[p.persona.region] || 0;
    const concernPenalty = Array.isArray(p.persona.concerns) ? p.persona.concerns.filter(c => ['price', 'trust', 'family', 'security'].includes(c)).length * -0.015 : 0;
    const campaignBoost = mode === 'campaign' ? 0.08 : 0;
    const score = Math.min(0.95, Math.max(0.02, baseConv + budgetBoost + channelBoost + techBoost + incomeBoost + socialBoost + regionBoost + concernPenalty + campaignBoost + (Math.random() - 0.5) * 0.2));
    const r = Math.random();
    let cat;
    if (r < score * 0.4) cat = 'ready';
    else if (r < score * 0.4 + score * 0.5) cat = 'warm';
    else if (r < 0.85) cat = 'cold';
    else cat = 'unfit';
    const msgCount = Math.round(6 + Math.random() * 18);
    const conversation = generateConversation(p, cat, mode === 'campaign' && campaign ? campaign : null, ctx);
    return { ...p, cat, score, msgCount, conversation };
  };

  const computeStats = (enriched, n) => {
    const stats = {
      ready: enriched.filter(p => p.cat === 'ready').length,
      warm: enriched.filter(p => p.cat === 'warm').length,
      cold: enriched.filter(p => p.cat === 'cold').length,
      unfit: enriched.filter(p => p.cat === 'unfit').length,
    };
    const total = n || enriched.length;
    const conv = total > 0 ? ((stats.ready / total) * 100).toFixed(1) : '0';
    const avgMsg = enriched.length > 0 ? (enriched.reduce((s, p) => s + p.msgCount, 0) / enriched.length).toFixed(1) : '0';
    return { stats, conv, avgMsg };
  };

  const autoSaveTest = (res) => {
    const now = new Date();
    const d = now.toLocaleDateString('fa-IR', { year: 'numeric', month: '2-digit', day: '2-digit' });
    const t = now.toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' });
    const tName = testMode === 'campaign' ? (selectedCampaign?.name || 'کمپین') : (selectedScript?.name || 'اسکریپت');
    const autoName = `${tName} × ${popMeta?.name || 'جامعه'} — ${d} ${t}`;
    window.api('/lab/populations', { method: 'POST', body: {
      name: autoName, total: res.people.length,
      personas: personasRef.current, weights: popMeta?.weights || [],
      people: res.people, stats: res.stats, conv: res.conv, avgMsg: res.avgMsg,
      testMode: res.testMode, campaignId: selectedCampaign?.id || '',
      campaignName: res.campaignName || '', scriptName: res.scriptName || '',
    }}).then(r => { if (r?.id) { setAutoSavedId(r.id); onRefresh(); } }).catch(() => {});
  };

  const runTest = () => {
    if (!population.length) return toast('یک جامعه انتخاب کن', 'error');
    clearInterval(intervalRef.current);
    setAutoSavedId(null);
    const campaignCtx = testMode === 'campaign' ? selectedCampaign : null;
    const activeScriptCtx = scriptCtx;
    const baseResult = { testMode, campaignName: campaignCtx?.name, scriptName: selectedScript?.name };

    if (paceMode === 'instant') {
      setRunning(true);
      setTimeout(() => {
        const enriched = population.map(p => processOnePerson(p, testMode, campaignCtx, activeScriptCtx));
        const { stats, conv, avgMsg } = computeStats(enriched, population.length);
        const finalRes = { people: enriched, stats, conv, avgMsg, ...baseResult };
        setResults(finalRes);
        setRunning(false);
        setProgress(null);
        toast(`تست ${fa(population.length)} نفر کامل شد ✓`, 'success');
        autoSaveTest(finalRes);
      }, 800);
    } else {
      processedRef.current = 0;
      enrichedRef.current = [];
      testConfigRef.current = { pop: population, bs: batchSize, pi: paceInterval, testMode, campaign: campaignCtx, scriptCtx: activeScriptCtx, baseResult };
      setProgress({ processed: 0, total: population.length, paused: false, done: false });
      setResults({ people: [], stats: { ready:0, warm:0, cold:0, unfit:0 }, conv: '0', avgMsg: '0', ...baseResult });
      const runBatch = () => {
        const cfg = testConfigRef.current;
        const start = processedRef.current;
        const batch = cfg.pop.slice(start, start + cfg.bs);
        if (batch.length === 0) {
          clearInterval(intervalRef.current);
          setProgress(prev => prev ? { ...prev, done: true } : null);
          toast(`تست ${fa(cfg.pop.length)} نفر کامل شد ✓`, 'success');
          return;
        }
        const newBatch = batch.map(p => processOnePerson(p, cfg.testMode, cfg.campaign, cfg.scriptCtx));
        const all = [...enrichedRef.current, ...newBatch];
        enrichedRef.current = all;
        processedRef.current = start + batch.length;
        const { stats, conv, avgMsg } = computeStats(all, cfg.pop.length);
        const partialRes = { people: all, stats, conv, avgMsg, ...cfg.baseResult };
        setResults(partialRes);
        setProgress({ processed: processedRef.current, total: cfg.pop.length, paused: false, done: processedRef.current >= cfg.pop.length });
        if (processedRef.current >= cfg.pop.length) {
          clearInterval(intervalRef.current);
          toast(`تست ${fa(cfg.pop.length)} نفر کامل شد ✓`, 'success');
          autoSaveTest(partialRes);
        }
      };
      runBatch();
      if (processedRef.current < population.length) intervalRef.current = setInterval(runBatch, paceInterval * 1000);
    }
  };

  const pauseTest = () => { clearInterval(intervalRef.current); setProgress(prev => prev ? { ...prev, paused: true } : null); };
  const resumeTest = () => {
    const cfg = testConfigRef.current;
    if (!cfg.pop) return;
    setProgress(prev => prev ? { ...prev, paused: false } : null);
    const runBatch = () => {
      const start = processedRef.current;
      const batch = cfg.pop.slice(start, start + cfg.bs);
      if (batch.length === 0) { clearInterval(intervalRef.current); setProgress(prev => prev ? { ...prev, done: true } : null); return; }
      const all = [...enrichedRef.current, ...batch.map(p => processOnePerson(p, cfg.testMode, cfg.campaign, cfg.scriptCtx))];
      enrichedRef.current = all;
      processedRef.current = start + batch.length;
      const { stats, conv, avgMsg } = computeStats(all, cfg.pop.length);
      setResults({ people: all, stats, conv, avgMsg, ...cfg.baseResult });
      setProgress({ processed: processedRef.current, total: cfg.pop.length, paused: false, done: processedRef.current >= cfg.pop.length });
      if (processedRef.current >= cfg.pop.length) clearInterval(intervalRef.current);
    };
    intervalRef.current = setInterval(runBatch, cfg.pi * 1000);
  };
  const stopTest = () => { clearInterval(intervalRef.current); setProgress(prev => prev ? { ...prev, done: true, paused: false } : null); };

  return (
    <div className="col gap-16">

      {/* ─── پیکربندی تست ─── */}
      <div className="card">
        <div className="bold" style={{ fontSize: 15, marginBottom: 16 }}>پیکربندی تست</div>

        {/* انتخاب جامعه */}
        <div className="col gap-6" style={{ marginBottom: 16 }}>
          <div className="label">جامعه آزمایشی</div>
          <select className="select" value={selectedPopId} onChange={e => selectPop(e.target.value)}>
            <option value="">— انتخاب جامعه —</option>
            {savedPops.map(p => (
              <option key={p.id} value={p.id}>
                {p.name} ({fa(p.total)} نفر{p.conv && p.conv !== '0' ? ` · نرخ قبلی: ${fa(p.conv)}%` : ''})
              </option>
            ))}
          </select>
          {loadingPop && <div className="text-xs text-3 row gap-6"><Icon name="loader" size={12} /> در حال بارگذاری...</div>}
          {popMeta && !loadingPop && (
            <div className="row gap-10" style={{ padding: '8px 12px', background: 'rgba(108,99,255,0.08)', border: '1px solid rgba(108,99,255,0.2)', borderRadius: 8, alignItems: 'center' }}>
              <Icon name="users" size={14} color="var(--primary-2)" />
              <span className="text-xs" style={{ color: 'var(--primary-2)' }}>{fa(population.length)} نفر آماده برای تست</span>
            </div>
          )}
        </div>

        <div className="divider"></div>

        {/* انتخاب نوع تست */}
        <div className="col gap-10 mt-14">
          <div className="row gap-8" style={{ alignItems: 'center' }}>
            <span className="label" style={{ margin: 0, flexShrink: 0 }}>اجرا با:</span>
            <button className={`pill ${testMode === 'script' ? 'active' : ''}`} onClick={() => setTestMode('script')}>📄 اسکریپت</button>
            <button className={`pill ${testMode === 'campaign' ? 'active' : ''}`} onClick={() => { setTestMode('campaign'); if (!activeCampaigns.length) loadCampaigns(); }}>📢 کمپین</button>
          </div>

          {testMode === 'script' && (
            <div className="col gap-8">
              <div className="row gap-10" style={{ alignItems: 'flex-end' }}>
                <div style={{ flex: 1 }}>
                  {realScripts.length > 0 ? (
                    <select className="select" value={selectedScript?.id || ''} onChange={e => { const s = realScripts.find(x => x.id === e.target.value); if (s) { setSelectedScript(s); loadScriptCtx(s.id); } }}>
                      {realScripts.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
                    </select>
                  ) : (
                    <select className="select">
                      {(SCRIPTS || []).map(s => <option key={s.id}>{s.name}</option>)}
                    </select>
                  )}
                </div>
                {selectedScript && <Button kind="ghost" size="sm" icon="eye" onClick={() => setShowScriptPreview(true)}>مشاهده</Button>}
              </div>
              {scriptCtx && (
                <div className="row gap-10" style={{ padding: '8px 12px', background: 'rgba(108,99,255,0.06)', borderRadius: 8, border: '1px solid rgba(108,99,255,0.18)', alignItems: 'center' }}>
                  <Icon name="file-text" size={13} color="var(--primary-2)" />
                  <span className="text-xs text-2">{fa(scriptCtx.questions.length)} سوال{scriptCtx.redLines.length > 0 && <span style={{ color: '#F87171' }}> • {fa(scriptCtx.redLines.length)} خط قرمز</span>}</span>
                </div>
              )}
            </div>
          )}

          {testMode === 'campaign' && (
            <div className="col gap-8">
              {campaignsLoading ? (
                <div className="row gap-8 text-xs text-3"><Icon name="loader" size={13} />در حال بارگذاری...</div>
              ) : campaignsError ? (
                <div className="col gap-6" style={{ padding: 10, border: '1px solid rgba(248,113,113,0.3)', borderRadius: 8 }}>
                  <span className="text-xs" style={{ color: '#F87171' }}>⚠ {campaignsError}</span>
                  <Button kind="ghost" size="sm" icon="refresh-cw" onClick={loadCampaigns}>تلاش دوباره</Button>
                </div>
              ) : activeCampaigns.length === 0 ? (
                <Button kind="ghost" size="sm" icon="refresh-cw" onClick={loadCampaigns}>بارگذاری کمپین‌ها</Button>
              ) : (
                <select className="select" value={selectedCampaign?.id || ''} onChange={e => { const c = activeCampaigns.find(x => x.id === e.target.value); setSelectedCampaign(c || null); }}>
                  <option value="">— انتخاب کمپین —</option>
                  {activeCampaigns.map(c => <option key={c.id} value={c.id}>{c.name}{c.goal ? ` — ${c.goal}` : ''}</option>)}
                </select>
              )}
            </div>
          )}
        </div>

        {/* تنظیمات وقفه (collapsible) */}
        <div className="mt-16" style={{ borderTop: '1px solid var(--border-soft)', paddingTop: 14 }}>
          <button onClick={() => setShowPace(!showPace)} style={{ display: 'flex', alignItems: 'center', gap: 8, background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-3)', fontSize: 13 }}>
            <Icon name={showPace ? 'chevron-up' : 'chevron-down'} size={14} />
            تنظیمات اجرای زمان‌بندی‌شده
          </button>
          {showPace && (
            <div className="col gap-12 mt-12">
              <div className="row gap-8">
                <button className={`pill ${paceMode === 'instant' ? 'active' : ''}`} onClick={() => setPaceMode('instant')}>⚡ فوری</button>
                <button className={`pill ${paceMode === 'paced' ? 'active' : ''}`} onClick={() => setPaceMode('paced')}>⏱ زمان‌بندی</button>
              </div>
              {paceMode === 'paced' && (
                <div className="grid grid-2 gap-14">
                  <div><div className="label">{fa(batchSize)} نفر هر دفعه</div><input type="range" min={1} max={50} step={1} value={batchSize} onChange={e => setBatchSize(Number(e.target.value))} style={{ width: '100%', accentColor: '#6C63FF' }} /></div>
                  <div><div className="label">هر {fa(paceInterval)} ثانیه</div><input type="range" min={5} max={300} step={5} value={paceInterval} onChange={e => setPaceInterval(Number(e.target.value))} style={{ width: '100%', accentColor: '#6C63FF' }} /></div>
                </div>
              )}
            </div>
          )}
        </div>

        {/* دکمه اجرا */}
        <div className="row gap-8 mt-16" style={{ justifyContent: 'flex-end' }}>
          <Button kind="primary" icon="play" loading={running} disabled={!population.length} onClick={runTest}>
            {running ? 'در حال اجرا...' : population.length ? `اجرای تست روی ${fa(population.length)} نفر ←` : 'ابتدا جامعه انتخاب کن'}
          </Button>
        </div>
      </div>

      {showScriptPreview && (
        <ScriptPreviewModal open={showScriptPreview} onClose={() => setShowScriptPreview(false)} scriptCtx={scriptCtx} scriptName={selectedScript?.name} />
      )}

      {/* ─── نتایج ─── */}
      {results && (
        <Results results={results} total={population.length} back={() => setResults(null)} rerun={runTest}
          personas={personasRef.current} popName={popMeta?.name} progress={progress}
          onPause={pauseTest} onResume={resumeTest} onStop={stopTest} autoSavedId={autoSavedId}
        />
      )}
    </div>
  );
};

const SectionBox = ({ title, children }) => (
  <div style={{ padding: 14, border: '1px solid var(--border-soft)', borderRadius: 12 }}>
    <div className="text-xs text-3 semi" style={{ marginBottom: 12, textTransform: 'uppercase', letterSpacing: '0.05em' }}>{title}</div>
    {children}
  </div>
);

const PersonaModal = ({ open, onClose, initial, palette, emojis, onSave }) => {
  const { Modal, Field, Button, Icon } = window.SB_UI;
  const [name, setName] = useState('');
  const [emoji, setEmoji] = useState('🧑');
  const [ageMin, setAgeMin] = useState(25);
  const [ageMax, setAgeMax] = useState(40);
  const [gender, setGender] = useState('any');
  const [occupation, setOccupation] = useState('');
  const [education, setEducation] = useState('bachelor');
  const [income, setIncome] = useState('medium');
  const [socialClass, setSocialClass] = useState('middle');
  const [region, setRegion] = useState('big_city');
  const [techLevel, setTechLevel] = useState(3);
  const [concerns, setConcerns] = useState([]);
  const [customConcern, setCustomConcern] = useState('');
  const [traits, setTraits] = useState('');
  const [color, setColor] = useState(palette[0]);

  const EDU_OPTIONS = [
    { value: 'school', label: 'زیر دیپلم' },
    { value: 'diploma', label: 'دیپلم' },
    { value: 'associate', label: 'فوق‌دیپلم' },
    { value: 'bachelor', label: 'لیسانس' },
    { value: 'master', label: 'فوق‌لیسانس' },
    { value: 'phd', label: 'دکترا' },
  ];
  const INCOME_OPTIONS = [
    { value: 'low', label: 'کم', sub: 'زیر ۱۰M', color: '#6B7280' },
    { value: 'medium', label: 'متوسط', sub: '۱۰–۳۰M', color: '#3B82F6' },
    { value: 'high', label: 'بالا', sub: '۳۰–۸۰M', color: '#10B981' },
    { value: 'very_high', label: 'خیلی بالا', sub: 'بالای ۸۰M', color: '#F59E0B' },
  ];
  const SOCIAL_OPTIONS = [
    { value: 'lower', label: 'محروم', color: '#9CA3AF' },
    { value: 'working', label: 'کارگری', color: '#6B7280' },
    { value: 'middle', label: 'متوسط', color: '#3B82F6' },
    { value: 'upper_middle', label: 'رو به بالا', color: '#10B981' },
    { value: 'upper', label: 'مرفه', color: '#F59E0B' },
  ];
  const REGION_OPTIONS = [
    { value: 'tehran', label: 'تهران', icon: '🏙️' },
    { value: 'big_city', label: 'شهر بزرگ', icon: '🌆' },
    { value: 'small_city', label: 'شهر کوچک', icon: '🏘️' },
    { value: 'rural', label: 'روستا', icon: '🌾' },
  ];
  const CONCERN_OPTIONS = [
    { id: 'price', label: 'قیمت و هزینه', icon: '💰' },
    { id: 'time', label: 'کمبود وقت', icon: '⏰' },
    { id: 'quality', label: 'کیفیت محصول', icon: '🔍' },
    { id: 'trust', label: 'اعتماد به برند', icon: '🤝' },
    { id: 'family', label: 'تایید خانواده', icon: '👨‍👩‍👧' },
    { id: 'roi', label: 'بازگشت سرمایه', icon: '📈' },
    { id: 'learning', label: 'یادگیری دشوار', icon: '📚' },
    { id: 'support', label: 'ضمانت و پشتیبانی', icon: '🛡️' },
    { id: 'social', label: 'نظر دیگران', icon: '👥' },
    { id: 'security', label: 'امنیت مالی', icon: '🔒' },
    { id: 'proof', label: 'نیاز به اثبات', icon: '💡' },
    { id: 'urgency', label: 'عجله برای نتیجه', icon: '🏃' },
    { id: 'complexity', label: 'پیچیدگی فرآیند', icon: '🧩' },
    { id: 'comparison', label: 'مقایسه با رقبا', icon: '⚖️' },
  ];
  const TECH_LABELS = ['', 'خیلی ضعیف', 'ضعیف', 'متوسط', 'خوب', 'خبره'];
  const OCCUPATION_LIST = ['خانه‌دار', 'دانشجو', 'دانش‌آموز', 'پزشک متخصص', 'پزشک عمومی', 'دندانپزشک', 'داروساز', 'پرستار', 'معلم', 'استاد دانشگاه', 'مهندس نرم‌افزار', 'مهندس عمران', 'کارمند دولتی', 'کارمند بانک', 'کارآفرین', 'فریلنسر', 'مدیر', 'طراح گرافیک', 'برنامه‌نویس', 'وکیل', 'حسابدار', 'بازنشسته', 'راننده', 'کاسب', 'کشاورز', 'خیاط', 'آرایشگر', 'ورزشکار', 'هنرمند', 'روانپزشک', 'متخصص مغز و اعصاب', 'مدیر مالی', 'مدیر بازاریابی', 'صاحب کسب‌وکار'];

  useEffect(() => {
    if (open) {
      if (initial) {
        setName(initial.name || '');
        setEmoji(initial.emoji || '🧑');
        const [a, b] = (initial.age || '25-40').split('-').map(Number);
        setAgeMin(a || 25); setAgeMax(b || 40);
        setGender(initial.gender || 'any');
        setOccupation(initial.occupation || '');
        setEducation(initial.education || 'bachelor');
        setIncome(initial.income || 'medium');
        setSocialClass(initial.socialClass || 'middle');
        setRegion(initial.region || 'big_city');
        setTechLevel(initial.techLevel || 3);
        setConcerns(initial.concerns || []);
        setTraits(initial.traits || '');
        setColor(initial.color || palette[0]);
      } else {
        setName(''); setEmoji('🧑'); setAgeMin(25); setAgeMax(40);
        setGender('any'); setOccupation(''); setEducation('bachelor');
        setIncome('medium'); setSocialClass('middle'); setRegion('big_city');
        setTechLevel(3); setConcerns([]); setTraits('');
        setColor(palette[Math.floor(Math.random() * palette.length)]);
      }
    }
  }, [open]);

  const toggleConcern = (id) => setConcerns(prev => prev.includes(id) ? prev.filter(c => c !== id) : [...prev, id]);
  const addCustom = () => {
    const val = customConcern.trim();
    if (!val || concerns.includes(val)) return;
    setConcerns(prev => [...prev, val]);
    setCustomConcern('');
  };
  const submit = () => {
    if (!name.trim()) return;
    onSave({ name, emoji, age: `${ageMin}-${ageMax}`, gender, occupation, education, income, socialClass, region, techLevel, concerns, traits, color });
  };

  const genderLabel = { male: 'آقا', female: 'خانم', any: '' }[gender];
  const incomeOpt = INCOME_OPTIONS.find(o => o.value === income);
  const eduLabel = EDU_OPTIONS.find(o => o.value === education)?.label || '';
  const socialLabel = SOCIAL_OPTIONS.find(o => o.value === socialClass)?.label || '';
  const regionLabel = REGION_OPTIONS.find(o => o.value === region)?.label || '';
  const concernLabels = concerns.map(c => CONCERN_OPTIONS.find(o => o.id === c)?.label || c);

  return (
    <Modal open={open} onClose={onClose} title={initial ? 'ویرایش پرسونا' : 'پرسونای جدید'} width={660} footer={
      <>
        <Button kind="primary" onClick={submit} icon={initial ? 'save' : 'plus'}>{initial ? 'ذخیره تغییرات' : 'افزودن پرسونا'}</Button>
        <Button kind="ghost" onClick={onClose}>انصراف</Button>
      </>
    }>
      <div className="col gap-14">

        {/* Live Preview */}
        <div style={{ padding: 14, background: 'rgba(15,15,26,0.5)', border: `1px solid ${color}44`, borderRadius: 14, display: 'flex', gap: 14, alignItems: 'flex-start' }}>
          <div style={{ width: 52, height: 52, borderRadius: 50, background: `linear-gradient(135deg, ${color}, ${color}66)`, display: 'grid', placeItems: 'center', fontSize: 24, flexShrink: 0, boxShadow: `0 4px 14px ${color}55` }}>{emoji}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div className="bold text-sm">{name || 'پرسونای بدون اسم'}</div>
            <div className="text-xs text-3 mono mt-4">
              {genderLabel && <span>{genderLabel} • </span>}
              سن {ageMin}–{ageMax}
              {occupation && <span> • {occupation}</span>}
            </div>
            <div className="text-xs text-3 mt-2">{eduLabel} • {socialLabel} • {regionLabel} • درآمد {incomeOpt?.label} • فناوری {TECH_LABELS[techLevel]}</div>
            {concernLabels.length > 0 && (
              <div className="row gap-4 mt-6" style={{ flexWrap: 'wrap' }}>
                {concernLabels.map((c, i) => <span key={i} style={{ padding: '2px 7px', borderRadius: 6, background: `${color}22`, color, fontSize: 10, border: `1px solid ${color}33` }}>{c}</span>)}
              </div>
            )}
          </div>
        </div>

        {/* Identity */}
        <SectionBox title="هویت">
          <div className="grid grid-2 gap-12">
            <Field label="نام پرسونا">
              <input className="input" placeholder="مثلا «خانم خانه‌دار محتاط»" value={name} onChange={e => setName(e.target.value)} />
            </Field>
            <Field label="ایموجی نشانگر">
              <div className="row gap-5" style={{ flexWrap: 'wrap' }}>
                {emojis.map(e => (
                  <button type="button" key={e} onClick={() => setEmoji(e)} style={{ width: 32, height: 32, borderRadius: 8, border: `1px solid ${emoji === e ? color : 'var(--border-soft)'}`, background: emoji === e ? `${color}22` : 'rgba(15,15,26,0.4)', fontSize: 15, cursor: 'pointer' }}>{e}</button>
                ))}
                <input className="input" value={emoji} onChange={e => setEmoji(e.target.value.slice(0, 2))} style={{ width: 54, textAlign: 'center', fontSize: 16 }} placeholder="✨" />
              </div>
            </Field>
          </div>
          <div className="row gap-8 mt-12" style={{ alignItems: 'center' }}>
            <span className="label" style={{ margin: 0, flexShrink: 0, fontSize: 11 }}>رنگ:</span>
            {palette.map(c => <button type="button" key={c} onClick={() => setColor(c)} style={{ width: 26, height: 26, borderRadius: 8, background: c, border: `2px solid ${color === c ? '#fff' : 'transparent'}`, boxShadow: color === c ? `0 0 0 2px ${c}` : 'none', cursor: 'pointer' }} />)}
          </div>
        </SectionBox>

        {/* Demographics */}
        <SectionBox title="جمعیت‌شناسی">
          <div className="grid grid-2 gap-12">
            <Field label={`حداقل سن: ${ageMin}`}>
              <input type="range" min={10} max={74} step={1} value={ageMin} onChange={e => setAgeMin(Math.min(ageMax - 1, Number(e.target.value)))} style={{ width: '100%', accentColor: color }} />
            </Field>
            <Field label={`حداکثر سن: ${ageMax}`}>
              <input type="range" min={11} max={80} step={1} value={ageMax} onChange={e => setAgeMax(Math.max(ageMin + 1, Number(e.target.value)))} style={{ width: '100%', accentColor: color }} />
            </Field>
          </div>

          <Field label="جنسیت" style={{ marginTop: 12 }}>
            <div className="row gap-8">
              {[['any', '🧑 نامشخص'], ['male', '👨 آقا'], ['female', '👩 خانم']].map(([v, l]) => (
                <button type="button" key={v} onClick={() => setGender(v)} style={{ flex: 1, padding: '8px 0', borderRadius: 10, cursor: 'pointer', fontSize: 13, border: `1px solid ${gender === v ? color : 'var(--border-soft)'}`, background: gender === v ? `${color}22` : 'rgba(15,15,26,0.4)', color: gender === v ? 'var(--text)' : 'var(--text-3)' }}>{l}</button>
              ))}
            </div>
          </Field>

          <div className="grid grid-2 gap-12 mt-12">
            <Field label="شغل / موقعیت">
              <input className="input" placeholder="پزشک، معلم، خانه‌دار، دانشجو..." value={occupation} onChange={e => setOccupation(e.target.value)} list="pm-occ-list" />
              <datalist id="pm-occ-list">{OCCUPATION_LIST.map(o => <option key={o} value={o} />)}</datalist>
            </Field>
            <Field label="تحصیلات">
              <select className="select" value={education} onChange={e => setEducation(e.target.value)}>
                {EDU_OPTIONS.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
              </select>
            </Field>
          </div>

          <Field label="منطقه جغرافیایی" style={{ marginTop: 12 }}>
            <div className="row gap-8">
              {REGION_OPTIONS.map(o => (
                <button type="button" key={o.value} onClick={() => setRegion(o.value)} style={{ flex: 1, padding: '8px 4px', borderRadius: 10, cursor: 'pointer', fontSize: 12, textAlign: 'center', border: `1px solid ${region === o.value ? color : 'var(--border-soft)'}`, background: region === o.value ? `${color}22` : 'rgba(15,15,26,0.4)', color: region === o.value ? 'var(--text)' : 'var(--text-3)' }}>
                  <div style={{ fontSize: 18 }}>{o.icon}</div>
                  <div style={{ marginTop: 2 }}>{o.label}</div>
                </button>
              ))}
            </div>
          </Field>
        </SectionBox>

        {/* Socioeconomic */}
        <SectionBox title="اقتصادی — اجتماعی">
          <Field label="سطح درآمد">
            <div className="row gap-8">
              {INCOME_OPTIONS.map(o => (
                <button type="button" key={o.value} onClick={() => setIncome(o.value)} style={{ flex: 1, padding: '8px 4px', borderRadius: 10, cursor: 'pointer', textAlign: 'center', border: `1px solid ${income === o.value ? o.color : 'var(--border-soft)'}`, background: income === o.value ? `${o.color}22` : 'rgba(15,15,26,0.4)' }}>
                  <div className="text-sm semi" style={{ color: income === o.value ? o.color : 'var(--text-3)' }}>{o.label}</div>
                  <div className="text-xs" style={{ color: 'var(--text-3)', marginTop: 2 }}>{o.sub}</div>
                </button>
              ))}
            </div>
          </Field>
          <Field label="طبقه اجتماعی" style={{ marginTop: 12 }}>
            <div className="row gap-6">
              {SOCIAL_OPTIONS.map(o => (
                <button type="button" key={o.value} onClick={() => setSocialClass(o.value)} style={{ flex: 1, padding: '7px 4px', borderRadius: 10, cursor: 'pointer', fontSize: 12, textAlign: 'center', border: `1px solid ${socialClass === o.value ? o.color : 'var(--border-soft)'}`, background: socialClass === o.value ? `${o.color}22` : 'rgba(15,15,26,0.4)', color: socialClass === o.value ? o.color : 'var(--text-3)' }}>{o.label}</button>
              ))}
            </div>
          </Field>
        </SectionBox>

        {/* Behavioral */}
        <SectionBox title="رفتار و دغدغه‌ها">
          <Field label={`آشنایی با فناوری: ${TECH_LABELS[techLevel]}`}>
            <input type="range" min={1} max={5} step={1} value={techLevel} onChange={e => setTechLevel(Number(e.target.value))} style={{ width: '100%', accentColor: color }} />
            <div className="row between text-xs text-3 mt-4">{TECH_LABELS.slice(1).map(l => <span key={l}>{l}</span>)}</div>
          </Field>

          <Field label="دغدغه‌ها (انتخاب چندتایی)" style={{ marginTop: 12 }}>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 7 }}>
              {CONCERN_OPTIONS.map(c => (
                <button type="button" key={c.id} onClick={() => toggleConcern(c.id)} style={{ padding: '5px 11px', borderRadius: 20, cursor: 'pointer', fontSize: 12, border: `1px solid ${concerns.includes(c.id) ? color : 'var(--border-soft)'}`, background: concerns.includes(c.id) ? `${color}22` : 'rgba(15,15,26,0.4)', color: concerns.includes(c.id) ? 'var(--text)' : 'var(--text-3)' }}>
                  {c.icon} {c.label}
                </button>
              ))}
            </div>
            {concerns.filter(c => !CONCERN_OPTIONS.find(o => o.id === c)).map((c, i) => (
              <span key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 4, margin: '4px 4px 0 0', padding: '4px 10px', borderRadius: 20, background: `${color}22`, border: `1px solid ${color}44`, fontSize: 12, color: 'var(--text-2)' }}>
                {c}
                <button type="button" onClick={() => setConcerns(prev => prev.filter(x => x !== c))} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-3)', fontSize: 14, lineHeight: 1 }}>×</button>
              </span>
            ))}
            <div className="row gap-8 mt-8">
              <input className="input" placeholder="دغدغه سفارشی..." value={customConcern} onChange={e => setCustomConcern(e.target.value)} onKeyDown={e => e.key === 'Enter' && addCustom()} style={{ flex: 1 }} />
              <Button kind="ghost" size="sm" icon="plus" onClick={addCustom}>اضافه</Button>
            </div>
          </Field>

          <Field label="خصوصیات اضافی" style={{ marginTop: 12 }}>
            <textarea className="textarea" rows={2} placeholder="هر توضیح اضافه‌ای درباره این پرسونا..." value={traits} onChange={e => setTraits(e.target.value)} />
          </Field>
        </SectionBox>

      </div>
    </Modal>
  );
};

const Stepper = ({ n, label, active, done }) => (
  <div className="row gap-10">
    <div style={{
      width: 28, height: 28, borderRadius: 50,
      background: done ? 'linear-gradient(135deg, #10B981, #34D399)' : active ? 'linear-gradient(135deg, var(--primary), #4F46E5)' : 'rgba(255,255,255,0.04)',
      border: '1px solid ' + (active || done ? 'transparent' : 'var(--border-soft)'),
      display: 'grid', placeItems: 'center', fontSize: 12, fontWeight: 700,
      color: active || done ? '#fff' : 'var(--text-3)',
      boxShadow: active ? '0 0 12px var(--primary-glow)' : 'none',
    }}>{done ? <window.SB_UI.Icon name="check" size={12} strokeWidth={3} /> : n}</div>
    <span className="text-sm semi" style={{ color: active || done ? 'var(--text)' : 'var(--text-3)' }}>{label}</span>
  </div>
);
const StepLine = ({ done }) => <div style={{ flex: 1, height: 1, background: done ? 'linear-gradient(90deg, #10B981, transparent)' : 'var(--border-soft)' }} />;

const PopulationView = ({ population, script, setScript, runTest, running, back, filter, setFilter, personas, testMode, setTestMode, selectedCampaign, setSelectedCampaign, activeCampaigns, campaignsLoading, campaignsError, onLoadCampaigns, paceMode, setPaceMode, batchSize, setBatchSize, paceInterval, setPaceInterval, onSave, savingPop, realScripts, selectedScript, onScriptChange }) => {
  const { Icon, Button } = window.SB_UI;
  const { SCRIPTS, fa, faMoney } = window.SB_DATA;
  const visible = filter === 'all' ? population : population.filter(p => p.persona.id === filter);

  const byPersona = personas.map(p => ({ p, n: population.filter(x => x.persona.id === p.id).length }));
  const byChannel = [...new Set(population.map(p => p.channel))].map(ch => ({ ch, n: population.filter(p => p.channel === ch).length }));

  return (
    <>
      <div className="card">
        <div className="row between">
          <div>
            <div className="bold" style={{ fontSize: 15 }}>جامعه ساخته شده — {fa(population.length)} نفر</div>
            <div className="text-xs text-3 mt-4">می‌تونی روی هر نفر کلیک کنی تا جزئیاتش رو ببینی، یا مستقیم تست رو اجرا کنی.</div>
          </div>
          <Button kind="ghost" icon="arrow-right" onClick={back}>برگشت به تنظیمات</Button>
        </div>

        <div className="grid grid-2 gap-16 mt-16">
          <div style={{ padding: 14, background: 'rgba(15,15,26,0.4)', border: '1px solid var(--border-soft)', borderRadius: 12 }}>
            <div className="text-xs text-3 semi" style={{ textTransform: 'uppercase', letterSpacing: 0.04, marginBottom: 10 }}>توزیع پرسونا</div>
            <div className="col gap-10">
              {byPersona.map(({ p, n }) => {
                const pct = (n / population.length) * 100;
                return (
                  <div key={p.id}>
                    <div className="row between">
                      <div className="row gap-8">
                        <span style={{ width: 18, height: 18, borderRadius: 50, background: `linear-gradient(135deg, ${p.color}, ${p.color}66)`, display: 'grid', placeItems: 'center', fontSize: 10 }}>{p.emoji}</span>
                        <span className="text-sm">{p.name}</span>
                      </div>
                      <span className="mono text-sm semi">{fa(n)} <span className="text-3 text-xs">({pct.toFixed(0)}%)</span></span>
                    </div>
                    <div className="bar mt-4"><div style={{ width: pct + '%', height: '100%', background: p.color, borderRadius: 999 }} /></div>
                  </div>
                );
              })}
            </div>
          </div>
          <div style={{ padding: 14, background: 'rgba(15,15,26,0.4)', border: '1px solid var(--border-soft)', borderRadius: 12 }}>
            <div className="text-xs text-3 semi" style={{ textTransform: 'uppercase', letterSpacing: 0.04, marginBottom: 10 }}>توزیع کانال</div>
            <div className="col gap-10">
              {byChannel.map(({ ch, n }) => {
                const pct = (n / population.length) * 100;
                return (
                  <div key={ch}>
                    <div className="row between">
                      <span className="text-sm">{ch}</span>
                      <span className="mono text-sm semi">{fa(n)} <span className="text-3 text-xs">({pct.toFixed(0)}%)</span></span>
                    </div>
                    <div className="bar mt-4"><div className="bar-fill" style={{ width: pct + '%' }} /></div>
                  </div>
                );
              })}
            </div>
          </div>
        </div>

        <div className="divider"></div>

        <div className="row between">
          <div className="row gap-8" style={{ flexWrap: 'wrap' }}>
            <button className={`pill ${filter === 'all' ? 'active' : ''}`} onClick={() => setFilter('all')}>همه<span className="count mono">{fa(population.length)}</span></button>
            {personas.map(p => {
              const n = population.filter(x => x.persona.id === p.id).length;
              return <button key={p.id} className={`pill ${filter === p.id ? 'active' : ''}`} onClick={() => setFilter(p.id)}>{p.emoji} {p.name}<span className="count mono">{fa(n)}</span></button>;
            })}
          </div>
        </div>

        <div className="grid grid-3 mt-16" style={{ maxHeight: 360, overflowY: 'auto', paddingLeft: 4 }}>
          {visible.slice(0, 60).map(p => (
            <div key={p.id} className="row gap-12" style={{ padding: 12, background: 'rgba(15,15,26,0.5)', border: '1px solid var(--border-soft)', borderRadius: 10, alignItems: 'center' }}>
              <div style={{ width: 36, height: 36, borderRadius: 50, background: `linear-gradient(135deg, ${p.persona.color}, ${p.persona.color}66)`, display: 'grid', placeItems: 'center', fontSize: 16, flexShrink: 0 }}>{p.persona.emoji}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="text-sm semi" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.name}</div>
                <div className="text-xs text-3 mono" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{fa(p.age)} • {p.city} • {p.channel}</div>
                <div className="text-xs text-3 mono mt-4">بودجه: {faMoney(p.budget / 1_000_000)}M</div>
              </div>
            </div>
          ))}
        </div>
        {visible.length > 60 && (
          <div className="text-xs text-3 mt-12" style={{ textAlign: 'center' }}>{fa(visible.length - 60)} نفر دیگه — برای دیدن همه از خروجی CSV استفاده کن</div>
        )}
      </div>

      <div className="card">
        {/* Mode selector */}
        <div className="row gap-8 mb-16" style={{ alignItems: 'center' }}>
          <span className="label" style={{ margin: 0, flexShrink: 0 }}>اجرا با:</span>
          <button className={`pill ${testMode === 'script' ? 'active' : ''}`} onClick={() => setTestMode('script')}>📄 اسکریپت</button>
          <button className={`pill ${testMode === 'campaign' ? 'active' : ''}`} onClick={() => { setTestMode('campaign'); if (!activeCampaigns.length) onLoadCampaigns(); }}>📢 کمپین</button>
        </div>

        {testMode === 'script' ? (
          <div className="mb-16">
            <div className="label">اسکریپت</div>
            {realScripts.length > 0 ? (
              <select className="select" value={selectedScript?.id || ''} onChange={e => {
                const s = realScripts.find(x => x.id === e.target.value);
                if (s) onScriptChange(s);
              }}>
                {realScripts.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
              </select>
            ) : (
              <select className="select" value={script} onChange={e => setScript(e.target.value)}>
                {SCRIPTS.map(s => <option key={s.id}>{s.name}</option>)}
              </select>
            )}
            {selectedScript && (
              <div className="text-xs text-3 mt-6" style={{ padding: '6px 10px', background: 'rgba(108,99,255,0.08)', borderRadius: 6, border: '1px solid rgba(108,99,255,0.2)' }}>
                📋 {(selectedScript.questions || []).length > 0
                  ? `${selectedScript.questions.length} سوال لود شد از اسکریپت`
                  : 'اسکریپت بدون سوال تعریف‌شده'}
              </div>
            )}
          </div>
        ) : (
          <div className="mb-16">
            <div className="label">کمپین فعال</div>
            {campaignsLoading ? (
              <div className="row gap-8" style={{ padding: 12, color: 'var(--text-3)', fontSize: 13 }}>
                <Icon name="loader" size={14} color="var(--primary)" /> در حال بارگذاری کمپین‌ها...
              </div>
            ) : campaignsError ? (
              <div className="col gap-8" style={{ padding: 12, border: '1px solid rgba(248,113,113,0.3)', borderRadius: 8, background: 'rgba(248,113,113,0.06)' }}>
                <span className="text-xs" style={{ color: '#F87171' }}>⚠ {campaignsError}</span>
                <Button kind="ghost" size="sm" icon="refresh-cw" onClick={onLoadCampaigns}>تلاش دوباره</Button>
              </div>
            ) : activeCampaigns.length === 0 ? (
              <div className="col gap-8" style={{ padding: 12, border: '1px solid var(--border-soft)', borderRadius: 8 }}>
                <span className="text-xs text-3">هنوز کمپینی بارگذاری نشده</span>
                <Button kind="ghost" size="sm" icon="refresh-cw" onClick={onLoadCampaigns}>بارگذاری کمپین‌ها</Button>
              </div>
            ) : (
              <div className="col gap-6">
                {activeCampaigns.map(c => {
                  const isSelected = selectedCampaign?.id === c.id;
                  return (
                    <button key={c.id} onClick={() => setSelectedCampaign(c)}
                      style={{ padding: '12px 14px', borderRadius: 10, cursor: 'pointer', textAlign: 'right', border: `1px solid ${isSelected ? '#6C63FF' : 'var(--border-soft)'}`, background: isSelected ? 'rgba(108,99,255,0.18)' : 'rgba(255,255,255,0.04)', display: 'flex', alignItems: 'center', gap: 12, color: 'var(--text)', width: '100%' }}>
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 13, fontWeight: 600, color: isSelected ? '#a5b4fc' : 'var(--text)' }}>{c.name}</div>
                        {c.goal && <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 4, lineHeight: 1.5 }}>{c.goal}</div>}
                        <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 4, fontFamily: 'monospace' }}>
                          {c.lead_count != null && <span>{fa(c.lead_count)} لید</span>}
                          {c.start_date && <span style={{ marginRight: 6 }}>• از {c.start_date}</span>}
                          {c.end_date && <span style={{ marginRight: 6 }}>تا {c.end_date}</span>}
                        </div>
                      </div>
                      <div style={{ width: 18, height: 18, borderRadius: '50%', border: `2px solid ${isSelected ? '#6C63FF' : 'var(--border-soft)'}`, background: isSelected ? '#6C63FF' : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                        {isSelected && <Icon name="check" size={10} color="#fff" strokeWidth={3} />}
                      </div>
                    </button>
                  );
                })}
              </div>
            )}
          </div>
        )}

        <div className="divider"></div>

        {/* Pace mode */}
        <div className="row gap-8 mb-12" style={{ alignItems: 'center' }}>
          <span className="label" style={{ margin: 0, flexShrink: 0 }}>حالت اجرا:</span>
          <button className={`pill ${paceMode === 'instant' ? 'active' : ''}`} onClick={() => setPaceMode('instant')}>⚡ فوری</button>
          <button className={`pill ${paceMode === 'paced' ? 'active' : ''}`} onClick={() => setPaceMode('paced')}>⏱ زمان‌بندی‌شده</button>
        </div>

        {paceMode === 'paced' && (
          <div className="grid grid-2 gap-16 mb-16" style={{ padding: '14px 0' }}>
            <div>
              <div className="label">هر دفعه: <span className="mono bold" style={{ color: 'var(--primary-2)' }}>{fa(batchSize)}</span> نفر</div>
              <input type="range" min={1} max={50} step={1} value={batchSize} onChange={e => setBatchSize(Number(e.target.value))} style={{ width: '100%', accentColor: '#6C63FF', marginTop: 6 }} />
              <div className="row between text-xs text-3 mono mt-2"><span>{fa(1)}</span><span>{fa(10)}</span><span>{fa(25)}</span><span>{fa(50)}</span></div>
            </div>
            <div>
              <div className="label">فاصله زمانی: <span className="mono bold" style={{ color: 'var(--primary-2)' }}>{fa(paceInterval)}</span> ثانیه</div>
              <input type="range" min={5} max={300} step={5} value={paceInterval} onChange={e => setPaceInterval(Number(e.target.value))} style={{ width: '100%', accentColor: '#6C63FF', marginTop: 6 }} />
              <div className="row between text-xs text-3 mono mt-2"><span>{fa(5)}s</span><span>{fa(60)}s</span><span>{fa(120)}s</span><span>{fa(300)}s</span></div>
            </div>
            <div className="col" style={{ gridColumn: '1 / -1', padding: '8px 12px', background: 'rgba(108,99,255,0.08)', borderRadius: 8, border: '1px solid rgba(108,99,255,0.2)' }}>
              <span className="text-xs" style={{ color: 'var(--primary-2)' }}>
                📊 هر {fa(paceInterval)} ثانیه، {fa(batchSize)} نفر پردازش می‌شن — نتایج به‌صورت زنده آپدیت می‌شه
              </span>
              <span className="text-xs text-3 mt-4">
                برای {fa(population.length)} نفر: حدود {fa(Math.ceil(population.length / batchSize))} دفعه • زمان کل: ~{fa(Math.ceil((population.length / batchSize) * paceInterval))} ثانیه
              </span>
            </div>
          </div>
        )}

        <div className="row gap-8" style={{ justifyContent: 'flex-end' }}>
          <Button kind="ghost" icon="save" loading={savingPop} onClick={onSave}>ذخیره جامعه</Button>
          <Button kind="ghost" icon="download">خروجی CSV</Button>
          <Button kind="primary" icon="play" loading={running} onClick={runTest}>{running ? 'در حال آماده‌سازی...' : `اجرای تست (${fa(population.length)} نفر)`}</Button>
        </div>
      </div>
    </>
  );
};

const CAT_COLOR = { ready: '#10B981', warm: '#F59E0B', cold: '#3B82F6', unfit: '#6B7280' };
const CAT_LABEL = { ready: 'آماده', warm: 'گرم', cold: 'سرد', unfit: 'نامناسب' };

const ConversationModal = ({ person, open, onClose }) => {
  const { Modal, CategoryBadge } = window.SB_UI;
  const { fa, faMoney } = window.SB_DATA;
  const ref = useRef(null);

  const msgs = React.useMemo(() => {
    if (!person) return [];
    if (Array.isArray(person.conversation) && person.conversation.length > 0) return person.conversation;
    // اگر مکالمه ذخیره نشده بود، on-the-fly تولید کن
    try { return generateConversation(person, person.cat || 'cold', null, null); } catch { return []; }
  }, [person, open]);

  useEffect(() => { if (open && ref.current) setTimeout(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, 80); }, [open, msgs]);
  if (!person) return null;
  const gT = { male: 'آقا', female: 'خانم', any: '' }[person.persona.gender] || '';
  return (
    <Modal open={open} onClose={onClose} title={`${person.name} — مکالمه شبیه‌سازی‌شده`} width={620}>
      <div style={{ padding: '10px 14px', background: 'rgba(15,15,26,0.6)', border: `1px solid ${person.persona.color}44`, borderRadius: 12, marginBottom: 14, display: 'flex', gap: 12, alignItems: 'center' }}>
        <div style={{ width: 44, height: 44, borderRadius: 50, background: `linear-gradient(135deg, ${person.persona.color}, ${person.persona.color}66)`, display: 'grid', placeItems: 'center', fontSize: 20, flexShrink: 0 }}>{person.persona.emoji}</div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="row gap-8" style={{ alignItems: 'center' }}>
            <span className="bold text-sm">{person.name}</span>
            <span style={{ padding: '2px 8px', borderRadius: 6, background: `${CAT_COLOR[person.cat]}22`, color: CAT_COLOR[person.cat], fontSize: 11, border: `1px solid ${CAT_COLOR[person.cat]}44` }}>{CAT_LABEL[person.cat]}</span>
          </div>
          <div className="text-xs text-3 mt-4">
            {gT && <span>{gT} • </span>}{fa(person.age)} سال
            {person.persona.occupation && <span> • {person.persona.occupation}</span>}
            {' • '}{person.city} • {person.channel}
          </div>
          <div className="text-xs text-3 mt-2">
            بودجه: {faMoney(Math.round(person.budget / 1_000_000))}M •
            پرسونا: {person.persona.name} •
            پیام‌ها: {fa(msgs.length)}
          </div>
        </div>
      </div>
      <div ref={ref} style={{ maxHeight: 420, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 8, paddingLeft: 4, paddingRight: 4 }}>
        {msgs.length === 0 && (
          <div style={{ textAlign: 'center', padding: '32px 16px', color: 'var(--text-3)' }}>
            <div style={{ fontSize: 28, marginBottom: 8 }}>💬</div>
            <div className="text-sm">مکالمه‌ای موجود نیست</div>
          </div>
        )}
        {msgs.map((msg, i) => (
          <div key={i} style={{ display: 'flex', justifyContent: msg.from === 'bot' ? 'flex-end' : 'flex-start' }}>
            <div style={{ maxWidth: '78%', padding: '9px 13px', borderRadius: msg.from === 'bot' ? '14px 14px 0 14px' : '14px 14px 14px 0', background: msg.from === 'bot' ? 'rgba(108,99,255,0.22)' : 'rgba(255,255,255,0.07)', border: `1px solid ${msg.from === 'bot' ? 'rgba(108,99,255,0.35)' : 'var(--border-soft)'}`, fontSize: 13, lineHeight: 1.65, whiteSpace: 'pre-wrap', color: 'var(--text-2)' }}>
              {msg.text}
              <div style={{ fontSize: 10, color: 'var(--text-3)', textAlign: msg.from === 'bot' ? 'left' : 'right', marginTop: 4 }}>{msg.from === 'bot' ? '🤖 ربات' : '👤 مشتری'} • {msg.time}</div>
            </div>
          </div>
        ))}
      </div>
    </Modal>
  );
};

const PeopleList = ({ people, popName }) => {
  const { Icon, CategoryBadge } = window.SB_UI;
  const { fa, faMoney } = window.SB_DATA;
  const [search, setSearch] = useState('');
  const [catFilter, setCatFilter] = useState('all');
  const [selected, setSelected] = useState(null);

  const filtered = people.filter(p => {
    const matchCat = catFilter === 'all' || p.cat === catFilter;
    const matchSearch = !search.trim() || p.name.includes(search) || (p.persona.occupation || '').includes(search) || p.city.includes(search);
    return matchCat && matchSearch;
  });

  const counts = { all: people.length, ready: people.filter(p => p.cat === 'ready').length, warm: people.filter(p => p.cat === 'warm').length, cold: people.filter(p => p.cat === 'cold').length, unfit: people.filter(p => p.cat === 'unfit').length };

  return (
    <div className="card">
      <div className="card-head">
        <div>
          <div className="card-title"><Icon name="messages-square" size={15} color="var(--primary-2)" />لیست کامل مکالمات{popName ? ` — ${popName}` : ''}</div>
          <div className="card-sub mt-4">روی هر نفر کلیک کن تا مکالمه شبیه‌سازی‌شده‌اش رو ببینی</div>
        </div>
        <span className="mono text-xs text-3">{fa(filtered.length)} از {fa(people.length)}</span>
      </div>

      <div className="row gap-8 mb-12" style={{ flexWrap: 'wrap' }}>
        <input className="input" placeholder="جستجو بر اساس نام، شغل، شهر..." value={search} onChange={e => setSearch(e.target.value)} style={{ flex: 1, minWidth: 180 }} />
        {['all', 'ready', 'warm', 'cold', 'unfit'].map(cat => (
          <button key={cat} className={`pill ${catFilter === cat ? 'active' : ''}`} onClick={() => setCatFilter(cat)} style={{ borderColor: cat !== 'all' && catFilter === cat ? CAT_COLOR[cat] : undefined }}>
            {cat === 'all' ? 'همه' : CAT_LABEL[cat]}
            <span className="count mono">{fa(counts[cat])}</span>
          </button>
        ))}
      </div>

      <div style={{ maxHeight: 480, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 6 }}>
        {filtered.slice(0, 300).map(p => (
          <div key={p.id} onClick={() => setSelected(p)} style={{ padding: '10px 12px', borderRadius: 10, cursor: 'pointer', border: '1px solid var(--border-soft)', background: 'rgba(15,15,26,0.4)', display: 'flex', gap: 12, alignItems: 'center', transition: 'border-color 0.15s' }}
            onMouseEnter={e => e.currentTarget.style.borderColor = p.persona.color + '66'}
            onMouseLeave={e => e.currentTarget.style.borderColor = 'var(--border-soft)'}>
            <div style={{ width: 34, height: 34, borderRadius: 50, background: `linear-gradient(135deg, ${p.persona.color}, ${p.persona.color}66)`, display: 'grid', placeItems: 'center', fontSize: 16, flexShrink: 0 }}>{p.persona.emoji}</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div className="row between" style={{ alignItems: 'center' }}>
                <span className="text-sm semi">{p.name}</span>
                <div className="row gap-6" style={{ alignItems: 'center' }}>
                  <span className="mono text-xs text-3">{fa(p.conversation ? p.conversation.length : p.msgCount)} پیام</span>
                  <span style={{ padding: '2px 7px', borderRadius: 5, background: `${CAT_COLOR[p.cat]}18`, color: CAT_COLOR[p.cat], fontSize: 10, border: `1px solid ${CAT_COLOR[p.cat]}33` }}>{CAT_LABEL[p.cat]}</span>
                </div>
              </div>
              <div className="text-xs text-3 mono mt-3">
                {fa(p.age)} سال
                {p.persona.occupation && <span> • {p.persona.occupation}</span>}
                {' • '}{p.city} • {p.channel}
                {' • '}{faMoney(Math.round(p.budget / 1_000_000))}M
              </div>
            </div>
            <Icon name="chevron-left" size={14} color="var(--text-3)" />
          </div>
        ))}
        {filtered.length > 300 && <div className="text-xs text-3" style={{ textAlign: 'center', padding: 8 }}>{fa(filtered.length - 300)} نفر دیگه — از فیلتر برای محدود کردن استفاده کن</div>}
        {filtered.length === 0 && <div className="text-xs text-3" style={{ textAlign: 'center', padding: 24 }}>نتیجه‌ای پیدا نشد</div>}
      </div>

      <ConversationModal person={selected} open={!!selected} onClose={() => setSelected(null)} />
    </div>
  );
};

const downloadCSV = (rows, filename) => {
  const bom = '﻿';
  const content = bom + rows.map(r => r.map(c => `"${String(c ?? '').replace(/"/g, '""')}"`).join(',')).join('\n');
  const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url; a.download = filename; a.click();
  URL.revokeObjectURL(url);
};

const Results = ({ results, total, back, rerun, personas, popName, progress, onPause, onResume, onStop, autoSavedId }) => {
  const { Icon, Button, CategoryBadge, Donut } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const segs = [
    { value: results.stats.ready, color: '#10B981', label: 'آماده' },
    { value: results.stats.warm, color: '#F59E0B', label: 'گرم' },
    { value: results.stats.cold, color: '#3B82F6', label: 'سرد' },
    { value: results.stats.unfit, color: '#6B7280', label: 'نامناسب' },
  ];

  // Per-persona breakdown
  const byPersona = personas.map(p => {
    const subset = results.people.filter(x => x.persona.id === p.id);
    const n = subset.length;
    return {
      p,
      n,
      ready: subset.filter(x => x.cat === 'ready').length,
      warm: subset.filter(x => x.cat === 'warm').length,
      cold: subset.filter(x => x.cat === 'cold').length,
      unfit: subset.filter(x => x.cat === 'unfit').length,
      readyPct: n === 0 ? 0 : Math.round((subset.filter(x => x.cat === 'ready').length / n) * 100),
    };
  });

  const CAT_FA = { ready: 'آماده', warm: 'گرم', cold: 'سرد', unfit: 'نامناسب' };

  const downloadFullReport = () => {
    const header = ['نام', 'سن', 'جنسیت', 'شهر', 'کانال', 'پرسونا', 'شغل', 'درآمد', 'منطقه', 'بودجه (M)', 'وضعیت', 'تعداد پیام'];
    const rows = results.people.map(p => [
      p.name, p.age,
      { male: 'آقا', female: 'خانم', any: 'نامشخص' }[p.persona.gender] || '',
      p.city, p.channel, p.persona.name,
      p.persona.occupation || '',
      { low: 'کم', medium: 'متوسط', high: 'بالا', very_high: 'مرفه' }[p.persona.income] || '',
      { tehran: 'تهران', big_city: 'شهر بزرگ', small_city: 'شهر کوچک', rural: 'روستا' }[p.persona.region] || '',
      Math.round((p.budget || 0) / 1_000_000),
      CAT_FA[p.cat] || p.cat,
      p.msgCount || 0,
    ]);
    const name = (popName || 'گزارش').replace(/[^\w؀-ۿ]/g, '_');
    downloadCSV([header, ...rows], `${name}.csv`);
  };

  const downloadPersonaCSV = () => {
    const header = ['پرسونا', 'تعداد', 'آماده', 'گرم', 'سرد', 'نامناسب', 'نرخ آماده (%)'];
    const rows = byPersona.filter(r => r.n > 0).map(r => [r.p.name, r.n, r.ready, r.warm, r.cold, r.unfit, r.readyPct]);
    downloadCSV([header, ...rows], 'تفکیک_پرسونا.csv');
  };

  return (
    <>
      {/* Progress bar (paced mode) */}
      {progress && !progress.done && (
        <div className="card" style={{ border: '1px solid rgba(108,99,255,0.4)', background: 'rgba(108,99,255,0.06)' }}>
          <div className="row between" style={{ alignItems: 'center' }}>
            <div>
              <div className="row gap-8" style={{ alignItems: 'center' }}>
                {!progress.paused ? <span style={{ width:8, height:8, borderRadius:'50%', background:'#6C63FF', boxShadow:'0 0 6px #6C63FF', animation:'pulse 1s infinite' }} /> : <Icon name="pause-circle" size={16} color="#F59E0B" />}
                <span className="bold text-sm">{progress.paused ? 'تست متوقف شد موقتاً' : 'در حال اجرا...'}</span>
              </div>
              <div className="text-xs text-3 mt-4 mono">
                {fa(progress.processed)} از {fa(progress.total)} نفر پردازش شدن
                {' — '}{fa(Math.round((progress.processed / progress.total) * 100))}%
              </div>
            </div>
            <div className="row gap-8">
              {!progress.paused
                ? <Button kind="secondary" size="sm" icon="pause" onClick={onPause}>توقف موقت</Button>
                : <Button kind="primary" size="sm" icon="play" onClick={onResume}>ادامه</Button>
              }
              <Button kind="ghost" size="sm" icon="square" onClick={onStop}>متوقف کن</Button>
            </div>
          </div>
          <div style={{ height: 6, background: 'rgba(255,255,255,0.08)', borderRadius: 3, marginTop: 12, overflow: 'hidden' }}>
            <div style={{ height: '100%', width: `${(progress.processed / progress.total) * 100}%`, background: 'linear-gradient(90deg, #6C63FF, #10B981)', borderRadius: 3, transition: 'width 0.4s ease' }} />
          </div>
        </div>
      )}

      <div className="card" style={{ background: 'linear-gradient(135deg, rgba(108,99,255,0.12), rgba(16,185,129,0.08))', border: '1px solid rgba(108,99,255,0.3)' }}>
        <div className="row between">
          <div>
            <div className="row gap-8">
              <Icon name={progress && !progress.done ? 'loader' : 'check-circle-2'} size={18} color={progress && !progress.done ? '#6C63FF' : '#34D399'} />
              <span className="bold" style={{ fontSize: 15 }}>
                {progress && !progress.done ? 'نتایج زنده (در حال به‌روزرسانی)' : `تست کامل شد${popName ? ` — ${popName}` : ''}`}
              </span>
            </div>
            <div className="text-xs text-3 mt-4">
              {results.campaignName ? `کمپین: ${results.campaignName}` : results.scriptName ? `اسکریپت: ${results.scriptName}` : ''}
              {' • '}{fa(results.people.length)} نفر پردازش شدن از {fa(total)}
            </div>
          </div>
          <div className="row gap-8">
            <Button kind="ghost" icon="arrow-right" onClick={back}>برگشت</Button>
            {(!progress || progress.done) && <Button kind="secondary" icon="rotate-ccw" onClick={rerun}>اجرای مجدد</Button>}
            {autoSavedId && <span style={{ padding: '6px 12px', borderRadius: 8, background: 'rgba(16,185,129,0.15)', border: '1px solid rgba(16,185,129,0.3)', fontSize: 12, color: '#34D399' }}>✓ ذخیره شد</span>}
            <Button kind="primary" icon="download" onClick={downloadFullReport}>دانلود گزارش</Button>
          </div>
        </div>
      </div>

      <div className="grid" style={{ gridTemplateColumns: '1fr 2fr', gap: 16 }}>
        <div className="card">
          <div className="card-title"><Icon name="pie-chart" size={15} color="var(--primary-2)" />نتیجه کلی</div>
          <div style={{ position: 'relative', margin: '16px auto', width: 'fit-content' }}>
            <Donut segments={segs} size={160} stroke={22} />
            <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', textAlign: 'center' }}>
              <div>
                <div className="text-xs text-3">نرخ تبدیل</div>
                <div className="bold" style={{ fontSize: 22, color: '#34D399' }}>{fa(results.conv)}%</div>
              </div>
            </div>
          </div>
          <div className="col gap-8 mt-8">
            {segs.map(s => (
              <div key={s.label} className="row between">
                <div className="row gap-8"><span style={{ width: 10, height: 10, background: s.color, borderRadius: 3 }} /><span className="text-sm">{s.label}</span></div>
                <span className="mono semi">{fa(s.value)}</span>
              </div>
            ))}
            <div className="divider" style={{ margin: '4px 0' }}></div>
            <div className="row between"><span className="text-xs text-3">میانگین تعداد پیام</span><span className="mono semi">{fa(results.avgMsg)}</span></div>
          </div>
        </div>

        <div className="card">
          <div className="card-head">
            <div className="card-title"><Icon name="bar-chart-3" size={15} color="var(--primary-2)" />تفکیک بر اساس پرسونا</div>
            <Button kind="ghost" size="sm" icon="download" onClick={downloadPersonaCSV}>CSV</Button>
          </div>
          <table className="table">
            <thead><tr><th>پرسونا</th><th>تعداد</th><th>آماده</th><th>گرم</th><th>سرد</th><th>نامناسب</th><th>نرخ آماده</th></tr></thead>
            <tbody>
              {byPersona.filter(r => r.n > 0).map(r => (
                <tr key={r.p.id}>
                  <td>
                    <div className="row gap-10">
                      <div style={{ width: 26, height: 26, borderRadius: 50, background: `linear-gradient(135deg, ${r.p.color}, ${r.p.color}66)`, display: 'grid', placeItems: 'center', fontSize: 12 }}>{r.p.emoji}</div>
                      <span className="semi text-sm">{r.p.name}</span>
                    </div>
                  </td>
                  <td className="mono">{fa(r.n)}</td>
                  <td><span className="mono" style={{ color: '#34D399' }}>{fa(r.ready)}</span></td>
                  <td><span className="mono" style={{ color: '#FBBF24' }}>{fa(r.warm)}</span></td>
                  <td><span className="mono" style={{ color: '#60A5FA' }}>{fa(r.cold)}</span></td>
                  <td><span className="mono text-3">{fa(r.unfit)}</span></td>
                  <td>
                    <div className="col gap-4" style={{ minWidth: 100 }}>
                      <span className="mono text-xs semi" style={{ color: '#34D399' }}>{fa(r.readyPct)}%</span>
                      <div className="bar"><div className="bar-fill green" style={{ width: r.readyPct + '%' }} /></div>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      <PeopleList people={results.people} popName={popName} />
    </>
  );
};

// ── تب مدیریت پرسوناها ──────────────────────────────────
const PersonaMgmtTab = () => {
  const { Icon, Button, useToast } = window.SB_UI;
  const { PERSONAS } = window.SB_DATA;
  const toast = useToast();
  const [personas, setPersonas] = useState(PERSONAS);
  const [addOpen, setAddOpen] = useState(false);
  const [editIdx, setEditIdx] = useState(null);

  const PALETTE = ['#6C63FF', '#FF6B35', '#10B981', '#F59E0B', '#3B82F6', '#8B5CF6', '#EC4899', '#06B6D4', '#84CC16', '#F97316'];
  const EMOJIS = ['👔', '🎨', '🚀', '🎓', '💼', '🧑‍💻', '🛍️', '📊', '🏢', '🎯', '🧠', '🦄', '🛠️', '📱', '💎', '🌟', '🏡', '👴', '👩', '📚', '🏛️', '🩺', '⚡', '🎭', '👨‍🌾', '🧑‍🍳', '👷', '🧑‍🎓', '🎪', '🌾', '🏥', '✂️', '🛒', '🧕', '👩‍💼', '🧓'];

  const upsertPersona = (data) => {
    if (editIdx !== null) {
      const nextP = [...personas]; nextP[editIdx] = { ...nextP[editIdx], ...data };
      setPersonas(nextP);
      toast('پرسونا ویرایش شد', 'success');
    } else {
      setPersonas([...personas, { id: Date.now(), custom: true, ...data }]);
      toast('پرسونای جدید اضافه شد', 'success');
    }
    setAddOpen(false);
    setEditIdx(null);
  };

  const deletePersona = (i) => {
    if (personas.length <= 2) return toast('حداقل باید ۲ پرسونا داشته باشی', 'error');
    setPersonas(personas.filter((_, idx) => idx !== i));
    toast('پرسونا حذف شد', 'info');
  };

  const INCOME_LABEL = { low: 'درآمد کم', medium: 'درآمد متوسط', high: 'درآمد بالا', very_high: 'درآمد مرفه' };
  const REGION_LABEL = { tehran: 'تهران', big_city: 'شهر بزرگ', small_city: 'شهر کوچک', rural: 'روستا' };

  return (
    <div className="col gap-16">
      <div className="card">
        <div className="row between">
          <div>
            <div className="bold" style={{ fontSize: 15 }}>پرسوناها</div>
            <div className="text-xs text-3 mt-4">{personas.length} پرسونا تعریف شده</div>
          </div>
          <Button kind="primary" size="sm" icon="plus" onClick={() => { setEditIdx(null); setAddOpen(true); }}>پرسونای جدید</Button>
        </div>
        <div className="col gap-10 mt-16">
          {personas.map((p, i) => (
            <div key={p.id} className="row gap-16" style={{ padding: 14, background: 'rgba(15,15,26,0.4)', border: `1px solid ${p.color}33`, borderRadius: 12 }}>
              <div style={{ width: 44, height: 44, borderRadius: 50, background: `linear-gradient(135deg, ${p.color}, ${p.color}66)`, display: 'grid', placeItems: 'center', fontSize: 22, flexShrink: 0, boxShadow: `0 4px 14px ${p.color}44` }}>{p.emoji}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="row gap-8" style={{ alignItems: 'center' }}>
                  <span className="semi text-sm">{p.name}</span>
                  {p.custom && <span style={{ fontSize: 10, padding: '1px 6px', borderRadius: 6, background: 'rgba(255,107,53,0.16)', color: '#FB923C', border: '1px solid rgba(255,107,53,0.3)' }}>سفارشی</span>}
                </div>
                <div className="text-xs text-3 mt-4">
                  {p.age && <span>{p.age} ساله • </span>}
                  {p.occupation && <span>{p.occupation} • </span>}
                  {INCOME_LABEL[p.income] || ''}
                  {p.region && <span> • {REGION_LABEL[p.region] || p.region}</span>}
                </div>
                {p.traits && <div className="text-xs text-3 mt-3" style={{ lineHeight: 1.5 }}>{p.traits}</div>}
                {Array.isArray(p.concerns) && p.concerns.length > 0 && (
                  <div className="row gap-4 mt-6" style={{ flexWrap: 'wrap' }}>
                    {p.concerns.map((c, ci) => (
                      <span key={ci} style={{ padding: '2px 7px', borderRadius: 6, background: `${p.color}18`, color: p.color, fontSize: 10, border: `1px solid ${p.color}33` }}>{c}</span>
                    ))}
                  </div>
                )}
              </div>
              <div className="col gap-4">
                <button className="icon-btn" style={{ width: 30, height: 30 }} onClick={() => { setEditIdx(i); setAddOpen(true); }}><Icon name="edit-3" size={13} /></button>
                <button className="icon-btn" style={{ width: 30, height: 30 }} onClick={() => deletePersona(i)}><Icon name="trash-2" size={13} color="#F87171" /></button>
              </div>
            </div>
          ))}
        </div>
      </div>
      <PersonaModal open={addOpen} onClose={() => { setAddOpen(false); setEditIdx(null); }} initial={editIdx !== null ? personas[editIdx] : null} palette={PALETTE} emojis={EMOJIS} onSave={upsertPersona} />
    </div>
  );
};

// ── تب بایگانی تست‌ها ────────────────────────────────────
const ArchiveTab = ({ initialId = null }) => {
  const { Button } = window.SB_UI;
  const { PERSONAS, fa } = window.SB_DATA;
  const { useToast } = window.SB_UI;
  const toast = useToast();
  const [savedPops, setSavedPops] = useState([]);
  const [viewResult, setViewResult] = useState(null);
  const [viewPersonas, setViewPersonas] = useState(PERSONAS);

  const refreshSavedPops = () => {
    window.api('/lab/populations').then(data => {
      if (Array.isArray(data)) setSavedPops(data);
    }).catch(() => {});
  };

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

  const loadSavedPop = async (id) => {
    try {
      const data = await window.api('/lab/populations/' + id);
      if (!data || !Array.isArray(data.people)) return toast('خطا در بارگذاری', 'error');
      if (data.stats && data.conv && data.conv !== '0') {
        setViewPersonas(Array.isArray(data.personas) && data.personas.length ? data.personas : PERSONAS);
        setViewResult({
          people: data.people,
          stats: data.stats,
          conv: data.conv,
          avgMsg: data.avg_msg || '0',
          popName: data.name,
          testMode: data.test_mode,
          campaignName: data.campaign_name,
          scriptName: data.script_name,
        });
      } else {
        toast('این مورد نتیجه‌ای ندارد — جامعه بدون تست', 'info');
      }
    } catch { toast('خطا در بارگذاری', 'error'); }
  };

  useEffect(() => {
    if (initialId) loadSavedPop(initialId);
  }, [initialId]);

  const deleteSavedPop = async (id, e) => {
    e.stopPropagation();
    if (!window.confirm('این تست حذف بشه؟')) return;
    await window.api('/lab/populations/' + id, { method: 'DELETE' }).catch(() => {});
    if (viewResult) setViewResult(null);
    refreshSavedPops();
    toast('حذف شد', 'info');
  };

  if (viewResult) {
    return (
      <div>
        <div className="mb-16">
          <Button kind="ghost" icon="arrow-right" onClick={() => setViewResult(null)}>بازگشت به بایگانی</Button>
        </div>
        <Results
          results={viewResult}
          total={viewResult.people.length}
          back={() => setViewResult(null)}
          rerun={() => {}}
          personas={viewPersonas}
          popName={viewResult.popName}
          progress={null}
          onPause={() => {}} onResume={() => {}} onStop={() => {}}
          autoSavedId={null}
        />
      </div>
    );
  }

  return (
    <TestHistory
      savedPops={savedPops}
      onLoad={loadSavedPop}
      onDelete={deleteSavedPop}
      onRefresh={refreshSavedPops}
      fa={fa}
    />
  );
};

// ── ماژول آزمایشگاه برای داشبورد ────────────────────────
const LabModule = () => {
  const { Icon } = window.SB_UI;
  const [tab, setTab] = window.useStickyState('tab_lab_module', 'run-test');
  const [savedPops, setSavedPops] = useState([]);

  const refreshSavedPops = () => {
    window.api('/lab/populations').then(data => {
      if (Array.isArray(data)) setSavedPops(data);
    }).catch(() => {});
  };

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

  const tabs = [
    { id: 'run-test', name: 'اجرای تست', icon: 'play' },
    { id: 'archive', name: 'بایگانی', icon: 'archive' },
  ];

  return (
    <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
      <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border-soft)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div className="row gap-8">
          <Icon name="flask" size={15} color="var(--primary-2)" />
          <span className="bold text-sm">آزمایشگاه</span>
        </div>
        <div className="row gap-6">
          {tabs.map(t => (
            <button key={t.id} onClick={() => setTab(t.id)}
              style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '5px 12px', borderRadius: 8, fontSize: 12, cursor: 'pointer', border: `1px solid ${tab === t.id ? 'rgba(108,99,255,0.5)' : 'var(--border-soft)'}`, background: tab === t.id ? 'rgba(108,99,255,0.12)' : 'transparent', color: tab === t.id ? '#a5b4fc' : 'var(--text-3)' }}>
              <Icon name={t.icon} size={12} />{t.name}
            </button>
          ))}
        </div>
      </div>
      <div style={{ padding: 18 }}>
        {tab === 'run-test' && <RunTestTab savedPops={savedPops} onRefresh={refreshSavedPops} />}
        {tab === 'archive' && <ArchiveTab />}
      </div>
    </div>
  );
};

window.Lab = Lab;
window.LabModule = LabModule;
