// ─── از leads.jsx ─────────────────────────────────────────
// ─── تبدیل تاریخ میلادی به شمسی ────────────────────────────
function gregorianToJalali(gy, gm, gd) {
  const g_d = [31,28,31,30,31,30,31,31,30,31,30,31];
  const j_d = [31,31,31,31,31,31,30,30,30,30,30,29];
  let gy2 = gm > 2 ? gy + 1 : gy;
  let days = 355666 + (365*gy) + Math.floor((gy2+3)/4) - Math.floor((gy2+99)/100) + Math.floor((gy2+399)/400) + gd;
  for (let i = 0; i < gm-1; i++) days += g_d[i];
  let jy = -1595 + 33*Math.floor(days/12053); days %= 12053;
  jy += 4*Math.floor(days/1461); days %= 1461;
  if (days > 365) { jy += Math.floor((days-1)/365); days = (days-1)%365; }
  let jm, jd;
  if (days < 186) { jm = 1 + Math.floor(days/31); jd = 1 + (days%31); }
  else { days -= 186; jm = 7 + Math.floor(days/30); jd = 1 + (days%30); }
  return [jy, jm, jd];
}
// یه رشته‌ی تاریخِ فقط-تاریخ («2026-07-24») طبقِ استانداردِ جاوااسکریپت با new Date()
// به‌صورتِ UTC پارس می‌شه، نه محلی — اگه تایم‌زونِ سیستم عقب‌تر از UTC باشه، یک روز
// عقب می‌افته. برایِ جلوگیری از این ناهماهنگی با بقیه‌ی جاهایی که همین رشته رو محلی
// پارس می‌کنن (مثلِ JalaliGridPopup)، اجزایِ سال/ماه/روز مستقیم از رشته خونده می‌شه.
function parseYMD(dateStr) {
  const m = String(dateStr||'').match(/^(\d{4})-(\d{2})-(\d{2})/);
  if (m) return { gy: +m[1], gm: +m[2], gd: +m[3] };
  const d = new Date(dateStr);
  if (isNaN(d.getTime())) return null;
  return { gy: d.getFullYear(), gm: d.getMonth()+1, gd: d.getDate() };
}
function toShamsi(dateStr) {
  if (!dateStr) return '—';
  const ymd = parseYMD(dateStr);
  if (!ymd) return (dateStr||'').slice(0,10);
  const [jy, jm, jd] = gregorianToJalali(ymd.gy, ymd.gm, ymd.gd);
  return `${jy}/${String(jm).padStart(2,'0')}/${String(jd).padStart(2,'0')}`;
}
// ⚠️ این تابع new Date(dateStr).getHours() رو با تایم‌زونِ خودِ مرورگر/سیستم‌عامل
// می‌خونه — فقط برایِ فیلدهایی درسته که از قبل به‌وقتِ محلی ذخیره شدن (مثلِ follow_up_at
// که از input[type=datetime-local] خامِ همون لحظه‌ی وارد‌کردنِ کاربر میاد، نه UTC).
// برایِ ستون‌هایی مثلِ created_at که با datetime('now') = UTC ذخیره می‌شن، از
// toShamsiTimeUTC (پایین) استفاده کن.
function toShamsiTime(dateStr) {
  if (!dateStr) return '—';
  const ymd = parseYMD(dateStr);
  if (!ymd) return (dateStr||'').slice(0,16);
  const [jy, jm, jd] = gregorianToJalali(ymd.gy, ymd.gm, ymd.gd);
  const d = new Date(dateStr);
  const hh = String(d.getHours()).padStart(2,'0');
  const mm = String(d.getMinutes()).padStart(2,'0');
  return `${jy}/${String(jm).padStart(2,'0')}/${String(jd).padStart(2,'0')} — ${hh}:${mm}`;
}
// قانونِ کاربر (۲۰۲۶-۰۸-۰۱): «تاریخ ثبت» تویِ جزئیاتِ لید یه ساعتِ عجیب (مثلاً ۰۸:۱۵ به‌جایِ
// ۱۵:۱۵) نشون می‌داد — چون toShamsiTime رویِ رشته‌ی خامِ UTC (بدونِ Z) از new Date().getHours()
// استفاده می‌کرد که به تایم‌زونِ مرورگر/سیستم‌عاملِ خودِ ادمین وابسته‌ست، نه لزوماً +۳:۳۰ِ ایران —
// این تابع صریح UTC رو پارس می‌کنه و ۲۱۰ دقیقه (وقتِ ایران) اضافه می‌کنه، مستقل از تنظیماتِ سیستم.
function toShamsiTimeUTC(dateStr) {
  if (!dateStr) return '—';
  // قانونِ کاربر (۲۰۲۶-۰۸-۱۱): وقتی created_at فقط تاریخه (بدونِ ساعت — مثلِ چیزی که پنلِ
  // «ویرایشِ معامله» با dealDate می‌فرسته)، Regexِ قبلی که ساعت رو الزامی می‌دونست match
  // نمی‌شد و کل رشته‌ی خام (میلادی، بدونِ تبدیل) نشون داده می‌شد. حالا بخشِ ساعت اختیاریه.
  const m = String(dateStr).match(/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?/);
  if (!m) return (dateStr||'').slice(0,16);
  if (m[4] === undefined) {
    // فقط تاریخ — این یه تاریخِ تقویمیِ خام (نه یه لحظه‌ی UTC)، پس آفستِ +۲۱۰دقیقه‌ای
    // (تبدیلِ UTC→ایران) اینجا معنی نداره، مستقیم تبدیل می‌شه.
    const [jy, jm, jd] = gregorianToJalali(+m[1], +m[2], +m[3]);
    return `${jy}/${String(jm).padStart(2,'0')}/${String(jd).padStart(2,'0')}`;
  }
  const d = new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], +(m[6]||0)) + 210*60000);
  const [jy, jm, jd] = gregorianToJalali(d.getUTCFullYear(), d.getUTCMonth()+1, d.getUTCDate());
  const hh = String(d.getUTCHours()).padStart(2,'0');
  const mm = String(d.getUTCMinutes()).padStart(2,'0');
  return `${jy}/${String(jm).padStart(2,'0')}/${String(jd).padStart(2,'0')} — ${hh}:${mm}`;
}
// معکوسِ gregorianToJalali — برایِ فیلترِ تاریخِ شمسی (ورودیِ کاربر → فرمتِ API میلادی)
function jalaliToGregorian(jy, jm, jd) {
  jy += 1595;
  let days = -355668 + (365*jy) + (Math.floor(jy/33)*8) + Math.floor(((jy%33)+3)/4) + jd +
    ((jm < 7) ? (jm-1)*31 : ((jm-7)*30)+186);
  let gy = 400*Math.floor(days/146097); days %= 146097;
  if (days > 36524) { gy += 100*Math.floor(--days/36524); days %= 36524; if (days >= 365) days++; }
  gy += 4*Math.floor(days/1461); days %= 1461;
  if (days > 365) { gy += Math.floor((days-1)/365); days = (days-1)%365; }
  let gd = days + 1;
  const isLeap = (gy%4===0 && gy%100!==0) || (gy%400===0);
  const sal_a = [0,31,isLeap?29:28,31,30,31,30,31,31,30,31,30,31];
  let gm; for (gm=1; gm<=12; gm++) { if (gd <= sal_a[gm]) break; gd -= sal_a[gm]; }
  return [gy, gm, gd];
}
// «۱۴۰۵/۰۴/۲۷» → «2026-07-18» — null اگه نامعتبر باشه
function jalaliStrToGregorianStr(jalaliStr) {
  const m = String(jalaliStr||'').trim().match(/^(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})$/);
  if (!m) return null;
  const jy = +m[1], jm = +m[2], jd = +m[3];
  if (jm < 1 || jm > 12 || jd < 1 || jd > 31) return null;
  const [gy, gm, gd] = jalaliToGregorian(jy, jm, jd);
  return `${gy}-${String(gm).padStart(2,'0')}-${String(gd).padStart(2,'0')}`;
}

// «امروز» به‌صورتِ YYYY-MM-DD طبقِ ساعتِ محلیِ سیستم — new Date().toISOString() همیشه UTC
// می‌ده؛ بینِ ساعتِ ۰۰:۰۰ تا ۰۳:۳۰ به‌وقتِ ایران، اون روش «دیروز» رو به‌جایِ «امروز» می‌داد.
function todayLocalStr() {
  const d = new Date();
  return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
}

// آفستِ n روزِ محلی از امروز — برایِ پریست‌هایِ سریعِ «زمانِ ثبت» (امروز/این هفته/این ماه)
function localDateStrOffset(days) {
  const d = new Date();
  d.setDate(d.getDate() + days);
  return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
}

// اولِ ماهِ شمسیِ جاری، به فرمتِ میلادیِ YYYY-MM-DD (برایِ پریستِ «این ماه»)
function jalaliMonthStartStr() {
  const d = new Date();
  const [jy, jm] = gregorianToJalali(d.getFullYear(), d.getMonth() + 1, d.getDate());
  const [gy, gm, gd] = jalaliToGregorian(jy, jm, 1);
  return gy + '-' + String(gm).padStart(2, '0') + '-' + String(gd).padStart(2, '0');
}

// ─── تقویمِ جدولیِ شمسی (grid) — برایِ فیلترِ تاریخ ─────────────
const FA_MONTHS = ['فروردین','اردیبهشت','خرداد','تیر','مرداد','شهریور','مهر','آبان','آذر','دی','بهمن','اسفند'];
const FA_WEEK   = ['ش','ی','د','س','چ','پ','ج'];

function jalaliDaysInMonth(jy, jm) {
  if (jm <= 6) return 31;
  if (jm <= 11) return 30;
  const [gy, gm, gd] = jalaliToGregorian(jy, 12, 30);
  const [jy2, jm2, jd2] = gregorianToJalali(gy, gm, gd);
  return (jy2 === jy && jm2 === 12 && jd2 === 30) ? 30 : 29;
}

function JalaliGridPopup({ value, onSelect, onClose, pos }) {
  const todayD = new Date();
  const [ty, tm, td] = gregorianToJalali(todayD.getFullYear(), todayD.getMonth() + 1, todayD.getDate());
  const base = value ? new Date(value + 'T00:00:00') : todayD;
  const [by, bm, bd] = gregorianToJalali(base.getFullYear(), base.getMonth() + 1, base.getDate());
  const [viewY, setViewY] = React.useState(by);
  const [viewM, setViewM] = React.useState(bm);

  const daysInMonth = jalaliDaysInMonth(viewY, viewM);
  const [firstGy, firstGm, firstGd] = jalaliToGregorian(viewY, viewM, 1);
  // getDay(): ۰=یکشنبه...۶=شنبه — ولی FA_WEEK از شنبه شروع می‌شه، پس باید یک روز بچرخه
  const startWeekday = (new Date(firstGy, firstGm - 1, firstGd).getDay() + 1) % 7;

  const cells = [];
  for (let i = 0; i < startWeekday; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(d);

  const pick = (d) => {
    const [gy, gm, gd] = jalaliToGregorian(viewY, viewM, d);
    onSelect(`${gy}-${String(gm).padStart(2, '0')}-${String(gd).padStart(2, '0')}`);
    onClose();
  };
  const prevMonth = () => { if (viewM === 1) { setViewY(y => y - 1); setViewM(12); } else setViewM(m => m - 1); };
  const nextMonth = () => { if (viewM === 12) { setViewY(y => y + 1); setViewM(1); } else setViewM(m => m + 1); };

  // پاپ‌آپ با پورتال به body رندر می‌شه تا سایدبارِ باریک (overflow) اون رو نبره
  return ReactDOM.createPortal(
    <div onClick={e => e.stopPropagation()} style={{
      position:'fixed', top: pos.top, left: pos.left, zIndex:9999, background:'#161c2c',
      border:'1px solid var(--border)', borderRadius:10, boxShadow:'0 8px 24px rgba(0,0,0,0.4)', padding:10, width:240,
      // لایه‌ی امنِ دوم: حتی اگه محاسبه‌ی موقعیت (doOpen) به هر دلیلی جا نداشت (مثلاً
      // پنجره‌ی مرورگر خیلی کوتاهه)، پاپ‌آپ به‌جایِ زدن‌بیرونِ بی‌اسکرول، خودش اسکرول می‌گیره.
      maxHeight:'min(310px, calc(100vh - 16px))', overflowY:'auto',
    }}>
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:8}}>
        <button onClick={prevMonth} style={{background:'transparent',border:'1px solid var(--border)',borderRadius:6,color:'var(--text-muted)',width:24,height:24,cursor:'pointer'}}>‹</button>
        <span style={{fontWeight:700,fontSize:12,color:'#e5e7eb'}}>{FA_MONTHS[viewM-1]} {viewY}</span>
        <button onClick={nextMonth} style={{background:'transparent',border:'1px solid var(--border)',borderRadius:6,color:'var(--text-muted)',width:24,height:24,cursor:'pointer'}}>›</button>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'repeat(7,1fr)',gap:2,marginBottom:4}}>
        {FA_WEEK.map((w,i) => <div key={i} style={{fontSize:9,color:'var(--text-muted)',textAlign:'center'}}>{w}</div>)}
      </div>
      <div style={{display:'grid',gridTemplateColumns:'repeat(7,1fr)',gap:2}}>
        {cells.map((d, i) => {
          const isSelected = d && value && viewY === by && viewM === bm && d === bd;
          const isToday = d && viewY === ty && viewM === tm && d === td;
          return (
            <button key={i} type="button" disabled={!d} onClick={() => d && pick(d)}
              style={{
                height:26, borderRadius:6, cursor: d ? 'pointer' : 'default', fontSize:11,
                border: isToday ? '1px solid #818CF8' : '1px solid transparent',
                background: isSelected ? '#818CF8' : 'transparent',
                color: !d ? 'transparent' : (isSelected ? '#fff' : '#e5e7eb'),
              }}>
              {d || ''}
            </button>
          );
        })}
      </div>
      <div style={{display:'flex',justifyContent:'space-between',marginTop:8,gap:6}}>
        <button onClick={() => { setViewY(ty); setViewM(tm); }} style={{fontSize:10,padding:'4px 8px',borderRadius:6,border:'1px solid var(--border)',background:'transparent',color:'var(--text-muted)',cursor:'pointer'}}>امروز</button>
        <button onClick={onClose} style={{fontSize:10,padding:'4px 8px',borderRadius:6,border:'1px solid var(--border)',background:'transparent',color:'var(--text-muted)',cursor:'pointer'}}>بستن</button>
      </div>
    </div>,
    document.body
  );
}

// ─── فیلترِ تاریخِ شمسی — دکمه‌ای که تقویمِ جدولی باز می‌کنه ─────────────
function ShamsiDateFilterMini({ value, onChange, placeholder }) {
  const { useState, useRef } = React;
  const [open, setOpen] = useState(false);
  const [pos, setPos] = useState(null);
  const btnRef = useRef(null);

  const doOpen = () => {
    const r = btnRef.current?.getBoundingClientRect();
    // کشفِ زنده ۲۰۲۶-۰۷-۲۳: تقویم position:fixed با top ثابت باز می‌شد — اگه دکمه نزدیکِ
    // پایینِ صفحه بود، پاپ‌آپ (~۳۱۰ پیکسل ارتفاع) از پایینِ صفحه می‌زد بیرون بدونِ هیچ
    // اسکرولی. حالا اگه جا نبود پایین، بالایِ دکمه باز می‌شه؛ در نهایت هم به سقفِ صفحه clamp می‌شه.
    const POPUP_H = 310;
    if (r) {
      const top = (r.bottom + 6 + POPUP_H > window.innerHeight)
        ? Math.max(8, r.top - 6 - POPUP_H)
        : r.bottom + 6;
      setPos({ top, left: Math.min(r.left, window.innerWidth - 250) });
    }
    setOpen(true);
  };

  return (
    <div style={{ position:'relative', width:'100%' }}>
      <button ref={btnRef} onClick={doOpen} style={{ ...selStyle, width:'100%', textAlign:'right', cursor:'pointer', boxSizing:'border-box' }}>
        {value ? toShamsi(value) : placeholder}
      </button>
      {open && pos && (
        <>
          {ReactDOM.createPortal(
            <div onClick={() => setOpen(false)} style={{ position:'fixed', inset:0, zIndex:9998 }} />,
            document.body
          )}
          <JalaliGridPopup value={value} onSelect={onChange} onClose={() => setOpen(false)} pos={pos} />
        </>
      )}
    </div>
  );
}

// ─── Pipeline فروش ───────────────────────────────────────────
const STATUS = [
  { id: 'new',          label: '✨ جدید',           color: '#60A5FA' },
  { id: 'follow_up',    label: '🔄 پیگیری',         color: '#818CF8' },
  { id: 'buyer',        label: '💰 خریدار',          color: '#34D399' },
  { id: 'lost',         label: '❌ از دست رفته',     color: '#6B7280' },
  { id: 'cancelled',    label: '🚫 کنسل شده',        color: '#EF4444' },
  { id: 'bad_number',   label: '📵 شماره اشتباه',    color: '#DC2626' },
];
const statusColor = Object.fromEntries(STATUS.map(s => [s.id, s.color]));
const statusLabel = Object.fromEntries(STATUS.map(s => [s.id, s.label.replace(/^\S+ /, '')]));

// ─── نگاشت نتیجه تماس → وضعیت ──────────────────────────────
const OUTCOME_STATUS = {
  answered:       'follow_up',
  no_answer:      'follow_up',
  call_later:     'follow_up',
  follow_up:      'follow_up',
  scheduled:      'follow_up',
  sold:           'buyer',
  not_interested: 'lost',
  cancelled:      'cancelled',
  bad_number:     'bad_number',
  re_request:     'new',
};

// ─── برچسب و رنگ نتایج تماس ──────────────────────────────
const OUTCOME_LABEL = {
  answered:       { label: 'جواب داد',      color: '#34D399', icon: '✅' },
  no_answer:      { label: 'بی‌پاسخ',        color: '#F87171', icon: '📵' },
  call_later:     { label: 'بعداً زنگ بزنه', color: '#818CF8', icon: '⏰' },
  follow_up:      { label: 'پیگیری',        color: '#818CF8', icon: '🔄' },
  scheduled:      { label: 'زمان خرید داد', color: '#A78BFA', icon: '📅' },
  sold:           { label: 'فروش شد',       color: '#34D399', icon: '💰' },
  not_interested: { label: 'علاقه نداشت',   color: '#6B7280', icon: '❌' },
  cancelled:      { label: 'کنسل کرد',      color: '#EF4444', icon: '🚫' },
  bad_number:     { label: 'شماره اشتباه',   color: '#DC2626', icon: '☎️' },
  re_request:     { label: 'درخواست مجدد',   color: '#60A5FA', icon: '🔁' },
};

// کامپوننت مشترک انتخاب وضعیت
const StatusPicker = ({ value, onChange, size = 'md' }) => (
  <div style={{ display: 'flex', flexWrap: 'wrap', gap: size === 'sm' ? 5 : 8 }}>
    {STATUS.map(s => (
      <button key={s.id} onClick={() => onChange(s.id)} style={{
        padding: size === 'sm' ? '4px 9px' : '5px 13px',
        borderRadius: 8, fontSize: size === 'sm' ? 11 : 12,
        cursor: 'pointer', border: 'none',
        background: value === s.id ? s.color + '30' : 'rgba(255,255,255,0.06)',
        color: value === s.id ? s.color : '#94a3b8',
        fontWeight: value === s.id ? 600 : 400,
        transition: 'all 0.12s',
      }}>{s.label}</button>
    ))}
  </div>
);

// Leads page
const Leads = () => {
  const { Icon, CategoryBadge, Button, SlidePanel } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const [leads, setLeads] = useState([]);
  const [stats, setStats] = useState({});
  const [filter, setFilter] = useState('all');
  const [callFilter, setCallFilter] = useState('');  // '' | 'called' | 'not_called'
  const [tagSearch, setTagSearch] = useState('');
  const [search, setSearch] = useState('');
  const [selected, setSelected] = useState(null);
  const [quickCallLead, setQuickCallLead] = useState(null);
  const [loading, setLoading] = useState(true);

  const token = localStorage.getItem(window.TOKEN_KEY);
  const headers = { Authorization: `Bearer ${token}` };

  const load = (statusFilter, cf) => {
    setLoading(true);
    const cFilter = cf !== undefined ? cf : callFilter;
    const params = new URLSearchParams({ limit: 100 });
    if (statusFilter && statusFilter !== 'all') params.set('status', statusFilter);
    if (search) params.set('search', search);
    if (cFilter) params.set('call_filter', cFilter);

    Promise.all([
      fetch(`/api/leads?${params}`, { headers }).then(r => r.json()),
      fetch('/api/leads/stats/overview', { headers }).then(r => r.json()),
    ]).then(([leadsData, statsData]) => {
      if (leadsData.success) setLeads(leadsData.data?.leads || []);
      if (statsData.success) setStats(statsData.data?.stats || {});
    }).finally(() => setLoading(false));
  };

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

  const statusFilters = [
    { id: 'all',       label: 'همه',           count: stats.total     || 0 },
    { id: 'new',        label: '✨ جدید',        count: stats.new        || 0 },
    { id: 'follow_up',  label: '🔄 پیگیری',      count: stats.follow_up  || 0 },
    { id: 'buyer',      label: '💰 خریدار',       count: stats.buyer      || 0 },
    { id: 'lost',      label: '❌ از دست رفته',  count: stats.lost      || 0 },
  ];

  const callFilters = [
    { id: '',           label: 'همه تماس‌ها',       icon: '📋' },
    { id: 'called',     label: 'تماس گرفته شده',    icon: '📞', count: stats.called     || 0, color: '#34D399' },
    { id: 'not_called', label: 'تماس نگرفته',        icon: '📵', count: stats.not_called || 0, color: '#F87171' },
  ];

  const filtered = tagSearch.trim()
    ? leads.filter(l => (l.tags || '').toLowerCase().includes(tagSearch.replace(/^#/, '').toLowerCase()))
    : leads;

  const selectedIndex = selected ? filtered.findIndex(l => l.id === selected.id) : -1;

  return (
    <div>
      <div className="col gap-8">
        {/* ردیف ۱: وضعیت */}
        <div className="pills" style={{ overflowX: 'auto', flexWrap: 'nowrap', paddingBottom: 2 }}>
          {statusFilters.map(f => (
            <button key={f.id} className={`pill ${filter === f.id ? 'active' : ''}`} onClick={() => setFilter(f.id)} style={{ whiteSpace: 'nowrap' }}>
              {f.label}<span className="count mono">{fa(f.count)}</span>
            </button>
          ))}
        </div>

        {/* ردیف ۲: فیلتر تماس + جستجو + ابزارها */}
        <div className="row between gap-8" style={{ flexWrap: 'wrap' }}>
          <div className="row gap-6">
            {callFilters.map(f => (
              <button key={f.id} onClick={() => setCallFilter(f.id)} style={{
                display: 'flex', alignItems: 'center', gap: 5,
                padding: '4px 12px', borderRadius: 7, fontSize: 12, cursor: 'pointer',
                border: `1px solid ${callFilter === f.id ? (f.color || 'var(--primary)') : 'rgba(255,255,255,0.07)'}`,
                background: callFilter === f.id ? (f.color || 'var(--primary)') + '15' : 'transparent',
                color: callFilter === f.id ? (f.color || 'var(--primary)') : 'var(--text-3)',
                transition: 'all 0.12s',
              }}>
                <span>{f.icon}</span><span>{f.label}</span>
                {f.count !== undefined && <span style={{ fontSize: 10, fontFamily: 'JetBrains Mono', opacity: 0.8 }}>{fa(f.count)}</span>}
              </button>
            ))}
          </div>
          <div className="row gap-6">
            <div style={{ position: 'relative' }}>
              <Icon name="search" size={13} style={{ position: 'absolute', right: 9, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-3)', pointerEvents: 'none' }} />
              <input value={search} onChange={e => setSearch(e.target.value)} onKeyDown={e => e.key === 'Enter' && load(filter)}
                placeholder="جستجو..." style={{ background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.07)', borderRadius: 7, padding: '5px 28px 5px 10px', color: 'var(--text-1)', fontSize: 12, outline: 'none', width: 150, direction: 'rtl' }} />
            </div>
            <Button kind="ghost" icon="download">خروجی</Button>
          </div>
        </div>
      </div>

      <div className="card mt-16" style={{ padding: 0, overflow: 'hidden' }}>
        {loading ? (
          <div style={{ padding: 40, textAlign: 'center', color: 'var(--text-3)' }}>در حال بارگذاری...</div>
        ) : filtered.length === 0 ? (
          <div style={{ padding: 40, textAlign: 'center', color: 'var(--text-3)' }}>لیدی یافت نشد</div>
        ) : (
          <table className="table">
            <thead>
              <tr>
                <th>اسم</th>
                <th>شماره</th>
                <th>پلتفرم</th>
                <th>هشتک‌ها</th>
                <th>امتیاز</th>
                <th>تماس</th>
                <th>آخرین نتیجه</th>
                <th>وضعیت</th>
                <th style={{ width: 40 }}></th>
              </tr>
            </thead>
            <tbody>
              {filtered.map(l => (
                <tr key={l.id} onClick={() => setSelected(l)} style={{ cursor: 'pointer' }}>
                  <td>
                    <div className="row gap-10">
                      <div className="avatar" style={{ width: 30, height: 30, fontSize: 11 }}>
                        {(l.full_name || l.username || '؟').slice(0, 2)}
                      </div>
                      <div>
                        <div className="semi text-sm">{l.full_name || l.username || 'ناشناس'}</div>
                        {l.username && l.full_name && <div className="text-xs text-3">@{l.username}</div>}
                      </div>
                    </div>
                  </td>
                  <td className="mono text-sm text-2">{l.phone || '—'}</td>
                  <td>
                    <span style={{ fontSize: 12, padding: '2px 8px', borderRadius: 6, background: l.platform === 'telegram' ? 'rgba(41,182,246,0.15)' : 'rgba(99,102,241,0.15)', color: l.platform === 'telegram' ? '#29B6F6' : '#818CF8' }}>
                      {l.platform === 'telegram' ? 'تلگرام' : 'بله'}
                    </span>
                  </td>
                  <td>
                    <div className="row gap-4" style={{ flexWrap: 'wrap' }}>
                      {(l.tags || '').split(',').filter(Boolean).slice(0, 3).map(tag => (
                        <span key={tag} onClick={e => { e.stopPropagation(); setTagSearch(tag); }}
                          style={{ fontSize: 10, padding: '2px 6px', borderRadius: 20, background: 'rgba(99,102,241,0.18)', color: '#818CF8', cursor: 'pointer', whiteSpace: 'nowrap' }}>
                          #{tag}
                        </span>
                      ))}
                    </div>
                  </td>
                  <td>
                    <span className="mono text-xs" style={{ color: (l.score || 0) >= 7 ? '#F87171' : (l.score || 0) >= 4 ? '#FB923C' : '#475569' }}>
                      {l.score || 0}
                    </span>
                  </td>
                  <td onClick={e => { e.stopPropagation(); setQuickCallLead(l); }}
                    title="کلیک برای ثبت تماس">
                    {l.call_count > 0 ? (
                      <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11, padding: '3px 9px', borderRadius: 6, background: 'rgba(52,211,153,0.15)', color: '#34D399', cursor: 'pointer' }}>
                        📞 {fa(l.call_count)}
                      </span>
                    ) : (
                      <span style={{ fontSize: 11, padding: '3px 9px', borderRadius: 6, background: 'rgba(99,102,241,0.12)', color: '#818CF8', cursor: 'pointer', border: '1px dashed rgba(99,102,241,0.3)' }}>
                        + ثبت
                      </span>
                    )}
                  </td>
                  <td>
                    {(() => {
                      if (!l.last_call_json) return <span style={{ color: '#374151', fontSize: 11 }}>—</span>;
                      try {
                        const d = JSON.parse(l.last_call_json);
                        const o = OUTCOME_LABEL[d.outcome];
                        if (!o) return <span style={{ color: '#374151', fontSize: 11 }}>—</span>;
                        return <span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 6, background: o.color + '18', color: o.color }}>{o.icon} {o.label}</span>;
                      } catch { return null; }
                    })()}
                  </td>
                  <td>
                    <span style={{ fontSize: 11, padding: '3px 8px', borderRadius: 6, background: (statusColor[l.status] || '#6B7280') + '20', color: statusColor[l.status] || '#6B7280' }}>
                      {statusLabel[l.status] || l.status}
                    </span>
                  </td>
                  <td>
                    <button className="icon-btn" style={{ width: 28, height: 28 }}><Icon name="chevron-left" size={13} /></button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      <SlidePanel open={!!selected} onClose={() => setSelected(null)}>
        {selected && (
          <LeadPoolDetail
            lead={selected}
            onClose={() => setSelected(null)}
            onUpdate={() => load(filter)}
            onNext={selectedIndex < filtered.length - 1 ? () => setSelected(filtered[selectedIndex + 1]) : null}
            onPrev={selectedIndex > 0 ? () => setSelected(filtered[selectedIndex - 1]) : null}
            currentIndex={selectedIndex + 1}
            totalCount={filtered.length}
          />
        )}
      </SlidePanel>

      {quickCallLead && (
        <CallModal
          lead={quickCallLead}
          token={token}
          onClose={() => setQuickCallLead(null)}
          onDone={() => { setQuickCallLead(null); load(filter, callFilter); }}
        />
      )}
    </div>
  );
};

// ─── کامپوننت مسئول معامله + ارجاع ─────────────────────────
const SellerAssignSection = ({ lead, headers, onUpdate }) => {
  const { Icon } = window.SB_UI;
  const [sellers, setSellers] = useState([]);
  const [showRefer, setShowRefer] = useState(false);
  const [referTo, setReferTo] = useState('');
  const [referReason, setReferReason] = useState('');
  const [saving, setSaving] = useState(false);
  const [sellerName, setSellerName] = useState(lead.seller_name || '');

  useEffect(() => {
    // فقط یک‌بار لیست فروشندگان رو بگیر
    fetch('/api/leads/sellers/list', { headers })
      .then(r => r.json())
      .then(d => {
        if (d.success) {
          setSellers(d.data.sellers || []);
          if (lead.seller_id && !lead.seller_name) {
            const s = (d.data.sellers || []).find(s => s.id === lead.seller_id);
            if (s) setSellerName(s.name);
          }
        }
      });
  }, [lead.id]);

  const doRefer = () => {
    if (!referTo) return;
    setSaving(true);
    fetch(`/api/leads/${lead.id}/refer`, {
      method: 'POST', headers,
      body: JSON.stringify({ to_seller_id: referTo, reason: referReason }),
    }).then(r => r.json()).then(d => {
      if (d.success) {
        const s = sellers.find(s => s.id === referTo);
        setSellerName(s ? s.name : referTo);
        onUpdate && onUpdate(referTo, s ? s.name : '');
        setShowRefer(false);
        setReferTo('');
        setReferReason('');
      }
    }).finally(() => setSaving(false));
  };

  return (
    <section>
      <div className="text-xs text-3 semi" style={{ marginBottom: 8 }}>👤 مسئول معامله</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderRadius: 8, background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.07)' }}>
        <div style={{ width: 30, height: 30, borderRadius: '50%', background: 'rgba(99,102,241,0.2)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, color: '#818CF8', flexShrink: 0 }}>
          {lead.seller_id ? '👤' : '🤖'}
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 600, color: '#e2e8f0' }}>
            {sellerName || (lead.seller_id ? lead.seller_id : 'هنوز assign نشده')}
          </div>
          {lead.assigned_at && (
            <div style={{ fontSize: 10, color: '#475569', marginTop: 2 }}>
              از {lead.assigned_at ? toShamsi(lead.assigned_at) : ''}
            </div>
          )}
        </div>
        <button onClick={() => setShowRefer(p => !p)} style={{
          padding: '5px 11px', borderRadius: 7, fontSize: 11, cursor: 'pointer',
          border: '1px solid rgba(99,102,241,0.3)', background: 'rgba(99,102,241,0.1)',
          color: '#818CF8', fontWeight: 600,
        }}>
          {showRefer ? '✕ بستن' : '🔀 ارجاع'}
        </button>
      </div>

      {/* فرم ارجاع */}
      {showRefer && (
        <div style={{ marginTop: 8, padding: '12px 14px', borderRadius: 8, background: 'rgba(99,102,241,0.06)', border: '1px solid rgba(99,102,241,0.2)' }}>
          <div className="col gap-10">
            <div>
              <div style={{ fontSize: 11, color: '#64748b', marginBottom: 5 }}>فروشنده مقصد</div>
              <select value={referTo} onChange={e => setReferTo(e.target.value)} style={{
                width: '100%', background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)',
                borderRadius: 7, padding: '7px 10px', color: referTo ? '#e2e8f0' : '#64748b',
                fontSize: 12, outline: 'none', direction: 'rtl',
              }}>
                <option value="">انتخاب فروشنده...</option>
                {sellers.filter(s => s.id !== lead.seller_id).map(s => (
                  <option key={s.id} value={s.id}>
                    {s.name}{s.on_leave ? ' (مرخصی)' : ''}
                  </option>
                ))}
              </select>
            </div>
            <div>
              <div style={{ fontSize: 11, color: '#64748b', marginBottom: 5 }}>دلیل ارجاع (اختیاری)</div>
              <input value={referReason} onChange={e => setReferReason(e.target.value)}
                placeholder="مثلا: تخصص بیشتر، ظرفیت..."
                style={{ width: '100%', boxSizing: 'border-box', background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 7, padding: '7px 10px', color: '#e2e8f0', fontSize: 12, outline: 'none', direction: 'rtl' }} />
            </div>
            <button onClick={doRefer} disabled={saving || !referTo} style={{
              padding: '8px', borderRadius: 8, fontSize: 12, cursor: referTo ? 'pointer' : 'not-allowed',
              background: referTo ? 'rgba(99,102,241,0.2)' : 'rgba(255,255,255,0.04)',
              border: `1px solid ${referTo ? 'rgba(99,102,241,0.4)' : 'rgba(255,255,255,0.07)'}`,
              color: referTo ? '#818CF8' : '#475569', fontWeight: 600,
              opacity: referTo ? 1 : 0.5,
            }}>
              {saving ? 'در حال ارجاع...' : '🔀 تأیید ارجاع'}
            </button>
          </div>
        </div>
      )}
    </section>
  );
};

// ─── پاپ‌آپ مکالمه داخل استخر ─────────────────────────────
const ConvPopup = ({ lead, token, onClose }) => {
  const { Button } = window.SB_UI;
  const { useState: useStateC, useEffect: useEffectC, useRef: useRefC } = React;
  const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };
  const [conv, setConv] = useStateC(null);
  const [messages, setMessages] = useStateC([]);
  const [input, setInput] = useStateC('');
  const [loading, setLoading] = useStateC(true);
  const [sending, setSending] = useStateC(false);
  const scrollRef = useRefC(null);

  useEffectC(() => {
    fetch(`/api/conversations?lead_id=${lead.id}&limit=1`, { headers })
      .then(r => r.json())
      .then(d => {
        const found = d.success && d.data?.conversations?.[0];
        if (!found) { setLoading(false); return; }
        setConv(found);
        fetch(`/api/conversations/${found.id}/messages`, { headers })
          .then(r => r.json())
          .then(d2 => {
            if (d2.success) setMessages(d2.data.messages || []);
            setLoading(false);
            setTimeout(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, 60);
          });
      });
  }, []);

  const sendMessage = () => {
    if (!input.trim() || !conv || sending) return;
    const text = input.trim();
    setInput('');
    setSending(true);
    const optimistic = { id: Date.now(), role: 'assistant', content: text, created_at: new Date().toISOString() };
    setMessages(prev => [...prev, optimistic]);
    setTimeout(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, 30);
    fetch(`/api/conversations/${conv.id}/send`, { method: 'POST', headers, body: JSON.stringify({ text }) })
      .then(r => r.json())
      .then(d => { if (d.success) setMessages(prev => prev.map(m => m.id === optimistic.id ? d.data.message : m)); })
      .finally(() => setSending(false));
  };

  // کشفِ زنده ۲۰۲۶-۰۸-۳۰: created_at تویِ دیتابیس UTCه (بدونِ Z)؛ بدونِ اضافه‌کردنِ Z، مرورگر
  // این رشته رو ساعتِ محلی فرض می‌کنه و رقم‌هایِ خامِ UTC رو عیناً نشون می‌ده — همیشه ۳:۳۰
  // ساعت عقب‌تر از ساعتِ واقعیِ ایران.
  const fmt = (t) => { try { return new Date(t.replace(' ', 'T') + 'Z').toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' }); } catch { return ''; } };


  // قانونِ کاربر (۲۰۲۶-۰۸-۲۷): پیامِ فایل‌هایِ ارسالی (کمپین/کیوسک) الان لینکِ عمومیِ واقعی
  // رو هم تويِ متن داره (logOutgoing تويِ campaignFlowEngine.js) — قبلاً همیشه به‌صورتِ متنِ
  // خام نشون داده می‌شد، حتی اگه ویدیو/عکس بود. این تابع خط‌به‌خطِ متن رو چک می‌کنه: اگه یه
  // خط لینکِ /api/public/library/ بود و بقیه‌ی پیام یه پسوندِ ویدیو/عکس داشت، به‌جایِ متنِ
  // خام، پلیرِ واقعی رندر می‌کنه.
  const renderMessageContent = (content) => {
    const lines = (content || '').split('\n');
    const isVideo = /\.(mp4|mov|webm|mkv|avi)\b/i.test(content || '');
    const isImage = /\.(jpg|jpeg|png|gif|webp)\b/i.test(content || '');
    return lines.map((l, k) => {
      const isPublicLink = /^https?:\/\/\S*\/api\/public\/library\/\S+$/.test(l.trim());
      if (isPublicLink && isVideo) {
        return <video key={k} controls src={l.trim()} style={{ maxWidth: '100%', borderRadius: 8, marginTop: 4 }} />;
      }
      if (isPublicLink && isImage) {
        return <img key={k} src={l.trim()} alt="" style={{ maxWidth: '100%', borderRadius: 8, marginTop: 4 }} />;
      }
      if (isPublicLink) {
        return <a key={k} href={l.trim()} target="_blank" rel="noreferrer" style={{ color: '#A5B4FC' }}>{l.trim()}</a>;
      }
      return <div key={k}>{l || ' '}</div>;
    });
  };

  return ReactDOM.createPortal(
    <div style={{ position: 'fixed', inset: 0, zIndex: 10000, background: 'rgba(0,0,0,0.65)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
      onClick={onClose}>
      <div style={{ width: 480, maxWidth: '95vw', height: 580, maxHeight: '90vh', background: '#111118', borderRadius: 16, border: '1px solid rgba(255,255,255,0.1)', display: 'flex', flexDirection: 'column', boxShadow: '0 24px 80px rgba(0,0,0,0.8)' }}
        onClick={e => e.stopPropagation()}>
        {/* هدر */}
        <div style={{ padding: '12px 16px', borderBottom: '1px solid rgba(255,255,255,0.08)', display: 'flex', alignItems: 'center', gap: 10, flexShrink: 0 }}>
          <span style={{ fontSize: 18 }}>💬</span>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 13, color: '#e2e8f0' }}>{lead.full_name || lead.username || 'ناشناس'}</div>
            {conv && <div style={{ fontSize: 11, color: '#475569' }}>{conv.platform} • {conv.status === 'active' ? 'فعال' : 'بسته'}</div>}
          </div>
          <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#64748b', fontSize: 18, lineHeight: 1, padding: '4px 8px', borderRadius: 6 }}>✕</button>
        </div>
        {/* پیام‌ها */}
        <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', padding: '12px', display: 'flex', flexDirection: 'column', gap: 8 }}>
          {loading ? (
            <div style={{ textAlign: 'center', color: '#475569', paddingTop: 60 }}>در حال بارگذاری...</div>
          ) : !conv ? (
            <div style={{ textAlign: 'center', color: '#475569', paddingTop: 60 }}>
              <div style={{ fontSize: 36, marginBottom: 12 }}>💬</div>
              <div>هنوز مکالمه‌ای با ربات وجود ندارد</div>
            </div>
          ) : messages.length === 0 ? (
            <div style={{ textAlign: 'center', color: '#475569', paddingTop: 60 }}>پیامی وجود ندارد</div>
          ) : (
            messages.map((m, i) => (
              <div key={i} style={{ maxWidth: '80%', alignSelf: m.role === 'user' ? 'flex-start' : 'flex-end', background: m.role === 'user' ? 'rgba(255,255,255,0.07)' : 'rgba(99,102,241,0.2)', borderRadius: m.role === 'user' ? '4px 12px 12px 12px' : '12px 4px 12px 12px', padding: '8px 12px', fontSize: 13, lineHeight: 1.6, color: '#e2e8f0', wordBreak: 'break-word' }}>
                {renderMessageContent(m.content)}
                <div style={{ fontSize: 10, color: '#475569', marginTop: 3, textAlign: m.role === 'user' ? 'right' : 'left' }}>{fmt(m.created_at)}</div>
              </div>
            ))
          )}
        </div>
        {/* ارسال پیام */}
        {conv && conv.status === 'active' && (
          <div style={{ padding: '10px 12px', borderTop: '1px solid rgba(255,255,255,0.08)', display: 'flex', gap: 8, flexShrink: 0 }}>
            <input value={input} onChange={e => setInput(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); } }}
              placeholder="پیام ارسال کن... (Enter)"
              style={{ flex: 1, background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 8, padding: '8px 12px', color: '#e2e8f0', fontSize: 13, outline: 'none', direction: 'rtl' }}
              disabled={sending} />
            <Button kind="primary" icon="send" onClick={sendMessage} disabled={!input.trim() || sending}>{sending ? '...' : 'ارسال'}</Button>
          </div>
        )}
      </div>
    </div>,
    document.body
  );
};

const LeadPoolDetail = ({ lead: initialLead, onClose, onUpdate, onNext, onPrev, currentIndex, totalCount }) => {
  const { Icon, Button } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const [lead, setLead] = useState(initialLead);
  const [callLogs, setCallLogs] = useState([]);
  const [nextReminder, setNextReminder] = useState(null);
  const [scriptState, setScriptState] = useState(null);
  const [collectedData, setCollectedData] = useState([]);
  const [campaignMemberships, setCampaignMemberships] = useState([]);
  const [status, setStatus] = useState(initialLead.status);
  const [showInlineLog, setShowInlineLog] = useState(false);
  const [showAI, setShowAI] = useState(false);
  const [showConvPopup, setShowConvPopup] = useState(false);
  const [detailLoading, setDetailLoading] = useState(true);
  const [tagInput, setTagInput] = useState('');
  const [tagSaving, setTagSaving] = useState(false);

  // ─── فرم ثبت فعالیت inline ───
  const [note, setNote] = useState('');
  const [outcome, setOutcome] = useState('');
  const [newStatus, setNewStatus] = useState(initialLead.status);
  const [followUpAt, setFollowUpAt] = useState('');
  const [saleAmountInline, setSaleAmountInline] = useState('');
  const [lostReasonInline, setLostReasonInline] = useState('');
  const [saving, setSaving] = useState(false);

  const token = localStorage.getItem(window.TOKEN_KEY);
  const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };

  const loadDetail = () => {
    setDetailLoading(true);
    fetch(`/api/leads/${initialLead.id}`, { headers })
      .then(r => r.json())
      .then(d => {
        if (d.success) {
          const l = d.data.lead;
          if (l) { setLead(l); setStatus(l.status); }
          setCallLogs(d.data.callLogs || []);
          setNextReminder(d.data.nextReminder || null);
          setScriptState(d.data.scriptState || null);
          setCollectedData(d.data.collectedData || []);
          setCampaignMemberships(d.data.campaignMemberships || []);
        }
      }).finally(() => setDetailLoading(false));
  };

  useEffect(() => { loadDetail(); }, [initialLead.id]);

  useEffect(() => {
    if (outcome && OUTCOME_STATUS[outcome]) setNewStatus(OUTCOME_STATUS[outcome]);
  }, [outcome]);

  const defaultFollowUp = () => {
    const d = new Date(); d.setDate(d.getDate() + 1);
    return d.toISOString().slice(0, 16);
  };

  // ─── تگ‌گذاری ───────────────────────────────────────────
  const currentTags = () => (lead.tags || '').split(',').filter(Boolean);

  const addTag = () => {
    const t = tagInput.trim().replace(/^#/, '').replace(/,/g, '').replace(/\s+/g, '_');
    if (!t) return;
    const existing = currentTags();
    if (existing.includes(t)) { setTagInput(''); return; }
    const newTags = [...existing, t].join(',');
    setTagSaving(true);
    fetch(`/api/leads/${lead.id}`, {
      method: 'PUT', headers,
      body: JSON.stringify({ tags: newTags }),
    }).then(r => r.json()).then(d => {
      if (d.success) {
        setLead(l => ({ ...l, tags: newTags }));
        onUpdate && onUpdate();
      }
    }).finally(() => { setTagSaving(false); setTagInput(''); });
  };

  const removeTag = (tag) => {
    const newTags = currentTags().filter(t => t !== tag).join(',');
    fetch(`/api/leads/${lead.id}`, {
      method: 'PUT', headers,
      body: JSON.stringify({ tags: newTags }),
    }).then(r => r.json()).then(d => {
      if (d.success) {
        setLead(l => ({ ...l, tags: newTags }));
        onUpdate && onUpdate();
      }
    });
  };

  const saveLog = () => {
    if (!note.trim() && !outcome) return;
    setSaving(true);
    let followUpUtc = null;
    if (followUpAt) { try { followUpUtc = new Date(followUpAt).toISOString().slice(0, 16); } catch {} }
    const body = { note, outcome, new_status: newStatus, follow_up_at: followUpUtc };
    if (outcome === 'sold' && saleAmountInline) body.sale_amount = parseFloat(saleAmountInline) || 0;
    if (['not_interested','cancelled'].includes(outcome) && lostReasonInline) body.lost_reason = lostReasonInline;
    fetch(`/api/leads/${lead.id}/call-log`, {
      method: 'POST', headers,
      body: JSON.stringify(body),
    })
      .then(r => r.json())
      .then(d => {
        if (d.success) {
          if (newStatus && newStatus !== status) setStatus(newStatus);
          onUpdate && onUpdate();
          setShowInlineLog(false);
          setNote(''); setOutcome(''); setFollowUpAt(''); setSaleAmountInline(''); setLostReasonInline('');
          loadDetail();
        }
      })
      .finally(() => setSaving(false));
  };

  return (
    <>
      {/* ─── هدر ─── */}
      <div className="slide-head">
        <button className="icon-btn" onClick={onClose} style={{ width: 32, height: 32 }}><Icon name="x" size={14} /></button>
        <div style={{ flex: 1 }}>
          <div className="row gap-10">
            <div className="avatar" style={{ width: 36, height: 36, fontSize: 12 }}>
              {(lead.full_name || lead.username || '؟').slice(0, 2)}
            </div>
            <div>
              <div className="bold">{lead.full_name || lead.username || 'ناشناس'}</div>
              <div className="text-xs text-3 mono">{lead.phone || 'بدون شماره'}</div>
            </div>
          </div>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          <span style={{ fontSize: 11, padding: '3px 10px', borderRadius: 6, background: (statusColor[status] || '#6B7280') + '20', color: statusColor[status] || '#6B7280' }}>
            {statusLabel[status] || status}
          </span>
          {(onPrev || onNext) && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 2, paddingRight: 6, borderRight: '1px solid rgba(255,255,255,0.07)', marginRight: 2 }}>
              <button className="icon-btn" onClick={onPrev} disabled={!onPrev} style={{ width: 26, height: 26, opacity: onPrev ? 1 : 0.25 }}>
                <Icon name="chevron-right" size={13} />
              </button>
              <span className="text-xs text-3 mono" style={{ minWidth: 38, textAlign: 'center', fontSize: 10 }}>
                {fa(currentIndex)}/{fa(totalCount)}
              </span>
              <button className="icon-btn" onClick={onNext} disabled={!onNext} style={{ width: 26, height: 26, opacity: onNext ? 1 : 0.25 }}>
                <Icon name="chevron-left" size={13} />
              </button>
            </div>
          )}
        </div>
      </div>

      <div className="slide-body">
        <div className="col gap-20">

          {/* ─── یادآور آینده ─── */}
          {nextReminder && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderRadius: 8, background: 'rgba(251,191,36,0.07)', border: '1px solid rgba(251,191,36,0.22)' }}>
              <span style={{ fontSize: 18 }}>🔔</span>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 12, fontWeight: 600, color: '#fbbf24' }}>یادآور تماس</div>
                <div style={{ fontSize: 11, color: '#94a3b8', marginTop: 2 }}>
                  {toShamsiTime(nextReminder.follow_up_at)}
                </div>
              </div>
              <button onClick={() => setShowInlineLog(true)} style={{
                padding: '5px 12px', borderRadius: 7, fontSize: 12, cursor: 'pointer', border: 'none',
                background: 'rgba(251,191,36,0.15)', color: '#fbbf24', fontWeight: 600,
              }}>📞 تماس</button>
            </div>
          )}

          {/* ─── اطلاعات پایه ─── */}
          <div className="card" style={{ padding: 14 }}>
            <div className="grid grid-2 gap-12">
              <Info label="پلتفرم" value={lead.platform === 'telegram' ? 'تلگرام' : 'بله'} />
              <Info label="یوزرنیم" value={lead.username ? '@' + lead.username : '—'} mono />
              <Info label="امتیاز" value={`${fa(lead.score || 0)} از ۱۰`} />
              <Info label="تاریخ ثبت" value={toShamsiTimeUTC(lead.created_at)} mono />
            </div>
          </div>

          {/* ─── هشتک‌ها (قابل ویرایش) ─── */}
          <section>
            <div className="text-xs text-3 semi" style={{ marginBottom: 8 }}>🏷️ هشتک‌ها</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
              {currentTags().map(tag => (
                <span key={tag} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  fontSize: 12, padding: '3px 8px 3px 10px', borderRadius: 20,
                  background: 'rgba(99,102,241,0.14)', color: '#818CF8',
                  border: '1px solid rgba(99,102,241,0.25)',
                }}>
                  #{tag}
                  <button onClick={() => removeTag(tag)} style={{
                    background: 'none', border: 'none', cursor: 'pointer',
                    color: '#818CF8', opacity: 0.6, padding: 0, lineHeight: 1,
                    fontSize: 13, display: 'flex', alignItems: 'center',
                  }}>×</button>
                </span>
              ))}
              {currentTags().length === 0 && (
                <span style={{ fontSize: 12, color: '#374151' }}>هنوز تگی ندارد</span>
              )}
            </div>
            {/* فرم افزودن تگ */}
            <div style={{ display: 'flex', gap: 6 }}>
              <input
                value={tagInput}
                onChange={e => setTagInput(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter') addTag(); }}
                placeholder="تگ جدید... (Enter)"
                style={{
                  flex: 1, background: 'rgba(255,255,255,0.04)',
                  border: '1px solid rgba(99,102,241,0.25)', borderRadius: 8,
                  padding: '6px 10px', color: '#e2e8f0', fontSize: 12,
                  outline: 'none', direction: 'rtl',
                }}
              />
              <button onClick={addTag} disabled={tagSaving || !tagInput.trim()} style={{
                padding: '6px 14px', borderRadius: 8, fontSize: 12, cursor: 'pointer',
                background: 'rgba(99,102,241,0.18)', border: '1px solid rgba(99,102,241,0.3)',
                color: '#818CF8', fontWeight: 600, opacity: tagInput.trim() ? 1 : 0.4,
              }}>+ افزودن</button>
            </div>
          </section>

          {/* ─── مسئول معامله ─── */}
          <SellerAssignSection lead={lead} headers={headers} onUpdate={(newSellerId, sellerName) => {
            setLead(l => ({ ...l, seller_id: newSellerId, seller_name: sellerName }));
            onUpdate && onUpdate();
          }} />

          {/* ─── وضعیت فعلی ─── */}
          <section>
            <div className="text-xs text-3 semi" style={{ marginBottom: 8 }}>وضعیت</div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderRadius: 8, background: (statusColor[status] || '#6B7280') + '10', border: `1px solid ${(statusColor[status] || '#6B7280')}28` }}>
              <div style={{ width: 8, height: 8, borderRadius: '50%', background: statusColor[status] || '#6B7280', flexShrink: 0 }} />
              <span style={{ fontSize: 13, fontWeight: 600, color: statusColor[status] || '#6B7280' }}>{statusLabel[status] || status}</span>
              <span style={{ fontSize: 11, color: '#374151', marginRight: 'auto' }}>بر اساس قوانین و نتیجه تماس</span>
            </div>
          </section>

          {/* ─── استیت اسکریپت ─── */}
          {scriptState && (
            <section>
              <div className="text-xs text-3 semi" style={{ marginBottom: 8 }}>موقعیت در اسکریپت</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderRadius: 8, background: 'rgba(99,102,241,0.08)', border: '1px solid rgba(99,102,241,0.2)' }}>
                <span style={{ fontSize: 18 }}>🗺️</span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 12, fontWeight: 600, color: '#818CF8' }}>
                    {scriptState.current_state_name || '(استیت مشخص نشده)'}
                  </div>
                  {scriptState.current_step > 0 && (
                    <div style={{ fontSize: 10, color: 'var(--text-3)', marginTop: 1 }}>مرحله {fa(scriptState.current_step)}</div>
                  )}
                  {scriptState.script_name && (
                    <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 2 }}>اسکریپت: {scriptState.script_name}</div>
                  )}
                </div>
                {scriptState.last_msg_at && (
                  <div style={{ fontSize: 10, color: 'var(--text-3)', whiteSpace: 'nowrap' }}>
                    {toShamsiTimeUTC(scriptState.last_msg_at)}
                  </div>
                )}
              </div>
            </section>
          )}

          {/* ─── کمپین‌های فعال ─── */}
          {campaignMemberships.length > 0 && (
            <section>
              <div className="text-xs text-3 semi" style={{ marginBottom: 8 }}>📣 کمپین‌های فعال</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                {campaignMemberships.map((m, idx) => (
                  <div key={idx} style={{
                    display: 'flex', alignItems: 'flex-start', gap: 10,
                    padding: '10px 14px', borderRadius: 8,
                    background: 'rgba(251,146,60,0.07)',
                    border: '1px solid rgba(251,146,60,0.2)',
                  }}>
                    <span style={{ fontSize: 16, flexShrink: 0 }}>📣</span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 12, fontWeight: 600, color: '#FB923C' }}>
                        {m.campaignName || m.campaignId}
                      </div>
                      {m.currentNode ? (
                        <div style={{ fontSize: 11, color: 'var(--text-2)', marginTop: 3 }}>
                          <span style={{ color: '#FCD34D', marginLeft: 4 }}>◉</span>
                          نود جاری: {m.currentNode.nodeTitle || m.currentNode.nodeId}
                          {m.currentNode.taskStatus === 'pending' && (
                            <span style={{ marginRight: 6, fontSize: 10, color: 'var(--text-3)' }}>
                              (در صف)
                            </span>
                          )}
                        </div>
                      ) : (
                        <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: 3 }}>
                          نودی در صف ندارد
                        </div>
                      )}
                      <div style={{ fontSize: 10, color: 'var(--text-3)', marginTop: 3 }}>
                        وضعیت عضویت: {m.memberStatus}
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </section>
          )}

          {/* ─── داده‌های جمع‌آوری‌شده ─── */}
          {collectedData.length > 0 && (
            <section>
              <div className="text-xs text-3 semi" style={{ marginBottom: 8 }}>📋 اطلاعات مشتری</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                {collectedData.map((item, idx) => (
                  <div key={idx} style={{
                    display: 'flex', alignItems: 'flex-start', gap: 8,
                    padding: '8px 12px', borderRadius: 8,
                    background: 'rgba(16,185,129,0.06)',
                    border: '1px solid rgba(16,185,129,0.15)',
                  }}>
                    <div style={{ minWidth: 0, flex: 1 }}>
                      <div style={{ fontSize: 10, color: '#6EE7B7', fontWeight: 600, marginBottom: 2 }}>
                        {item.field_name}
                      </div>
                      <div style={{ fontSize: 12, color: 'var(--text-1)', lineHeight: 1.5 }}>
                        {item.field_value}
                      </div>
                    </div>
                    <div style={{ fontSize: 9, color: 'var(--text-3)', whiteSpace: 'nowrap', marginTop: 2 }}>
                      {item.state_name}
                    </div>
                  </div>
                ))}
              </div>
            </section>
          )}

          {/* ─── تاریخچه تماس ─── */}
          <section>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
              <div className="text-xs text-3 semi">
                تاریخچه تماس
                {callLogs.length > 0 && <span className="mono" style={{ opacity: 0.5, marginRight: 5 }}>({fa(callLogs.length)})</span>}
              </div>
              <button onClick={() => setShowInlineLog(p => !p)} style={{
                display: 'flex', alignItems: 'center', gap: 5,
                padding: '4px 12px', borderRadius: 7, fontSize: 11, cursor: 'pointer',
                border: showInlineLog ? '1px solid rgba(248,113,113,0.3)' : '1px solid rgba(99,102,241,0.3)',
                background: showInlineLog ? 'rgba(248,113,113,0.08)' : 'rgba(99,102,241,0.08)',
                color: showInlineLog ? '#F87171' : '#818CF8',
                transition: 'all 0.15s',
              }}>
                <Icon name={showInlineLog ? 'x' : 'plus'} size={11} />
                {showInlineLog ? 'بستن' : 'ثبت فعالیت'}
              </button>
            </div>

            {/* ─── فرم inline ثبت فعالیت ─── */}
            {showInlineLog && (
              <div style={{ marginBottom: 14, padding: 14, borderRadius: 10, background: 'rgba(99,102,241,0.05)', border: '1px solid rgba(99,102,241,0.18)' }}>
                <div className="col gap-12">
                  {/* نتیجه تماس */}
                  <div>
                    <div style={{ fontSize: 11, color: '#64748b', marginBottom: 6 }}>نتیجه تماس</div>
                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                      {Object.entries(OUTCOME_LABEL).map(([id, o]) => (
                        <button key={id} onClick={() => setOutcome(id)} style={{
                          padding: '5px 10px', borderRadius: 8, fontSize: 11, cursor: 'pointer', border: 'none',
                          background: outcome === id ? (o.color + '28') : 'rgba(255,255,255,0.06)',
                          color: outcome === id ? o.color : '#94a3b8',
                          fontWeight: outcome === id ? 600 : 400,
                          transition: 'all 0.12s',
                        }}>{o.icon} {o.label}</button>
                      ))}
                    </div>
                  </div>
                  {/* مبلغ فروش inline */}
                  {outcome === 'sold' && (
                    <div style={{ padding: '8px 12px', borderRadius: 8, background: 'rgba(52,211,153,0.08)', border: '1px solid rgba(52,211,153,0.25)' }}>
                      <div style={{ fontSize: 11, color: '#34D399', marginBottom: 5, fontWeight: 600 }}>💰 مبلغ فروش</div>
                      <input type="number" value={saleAmountInline} onChange={e => setSaleAmountInline(e.target.value)}
                        placeholder="مثلا: 2500000 (تومان)"
                        style={{ width: '100%', padding: '6px 10px', borderRadius: 7, background: 'rgba(52,211,153,0.08)', border: '1px solid rgba(52,211,153,0.3)', color: '#34D399', fontSize: 13, outline: 'none', fontFamily: 'JetBrains Mono', boxSizing: 'border-box', direction: 'ltr' }} />
                    </div>
                  )}
                  {/* دلیل باخت */}
                  {['not_interested', 'cancelled'].includes(outcome) && (
                    <div style={{ padding: '8px 12px', borderRadius: 8, background: 'rgba(107,114,128,0.08)', border: '1px solid rgba(107,114,128,0.25)' }}>
                      <div style={{ fontSize: 11, color: '#9CA3AF', marginBottom: 8, fontWeight: 600 }}>❓ دلیل از دست رفتن لید</div>
                      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                        {[
                          { id: 'price',          label: '💸 قیمت گران' },
                          { id: 'budget',         label: '💰 بودجه ندارد' },
                          { id: 'timing',         label: '⏳ زمان مناسب نیست' },
                          { id: 'competitor',     label: '🏃 رفت پیش رقیب' },
                          { id: 'no_need',        label: '🙅 نیازی ندارد' },
                          { id: 'already_bought', label: '🛒 جای دیگری خریده' },
                          { id: 'other',          label: '📌 سایر' },
                        ].map(r => (
                          <button key={r.id} onClick={() => setLostReasonInline(lostReasonInline === r.id ? '' : r.id)} style={{
                            padding: '4px 9px', borderRadius: 8, fontSize: 11, cursor: 'pointer', border: 'none',
                            background: lostReasonInline === r.id ? 'rgba(107,114,128,0.35)' : 'rgba(255,255,255,0.05)',
                            color: lostReasonInline === r.id ? '#e2e8f0' : '#64748b',
                            fontWeight: lostReasonInline === r.id ? 600 : 400,
                            transition: 'all 0.12s',
                          }}>{r.label}</button>
                        ))}
                      </div>
                    </div>
                  )}
                  {/* یادآور */}
                  <div>
                    <div style={{ fontSize: 11, color: '#64748b', marginBottom: 6 }}>🔔 یادآور بعدی <span style={{ color: '#374151' }}>(اختیاری)</span></div>
                    <div style={{ display: 'flex', gap: 6 }}>
                      <input type="datetime-local" value={followUpAt} onChange={e => setFollowUpAt(e.target.value)}
                        style={{ flex: 1, background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 8, padding: '6px 8px', color: '#e2e8f0', fontSize: 12, outline: 'none', colorScheme: 'dark' }} />
                      <button onClick={() => setFollowUpAt(defaultFollowUp())} style={{ padding: '6px 10px', borderRadius: 8, fontSize: 11, cursor: 'pointer', border: '1px solid #3730a3', background: 'rgba(99,102,241,0.12)', color: '#818CF8', whiteSpace: 'nowrap' }}>فردا</button>
                      {followUpAt && <button onClick={() => setFollowUpAt('')} style={{ padding: '6px 8px', borderRadius: 8, fontSize: 11, cursor: 'pointer', border: 'none', background: 'rgba(248,113,113,0.1)', color: '#F87171' }}>✕</button>}
                    </div>
                  </div>
                  {/* یادداشت */}
                  <div>
                    <div style={{ fontSize: 11, color: '#64748b', marginBottom: 6 }}>یادداشت</div>
                    <textarea value={note} onChange={e => setNote(e.target.value)} rows={3}
                      placeholder="خلاصه مکالمه، نکات مهم..."
                      style={{ width: '100%', background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 8, padding: 10, color: '#e2e8f0', fontSize: 12, resize: 'vertical', outline: 'none', direction: 'rtl', fontFamily: 'inherit', boxSizing: 'border-box' }} />
                  </div>
                  {/* تغییر وضعیت خودکار */}
                  {newStatus !== lead.status && (
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 12px', borderRadius: 8, background: (statusColor[newStatus] || '#6B7280') + '12', border: `1px solid ${(statusColor[newStatus] || '#6B7280')}30` }}>
                      <span style={{ fontSize: 11, color: '#475569' }}>وضعیت لید:</span>
                      <span style={{ fontSize: 11, color: '#6B7280', textDecoration: 'line-through' }}>{statusLabel[lead.status] || lead.status}</span>
                      <span style={{ fontSize: 11, color: '#475569' }}>←</span>
                      <span style={{ fontSize: 12, fontWeight: 700, color: statusColor[newStatus] || '#6B7280' }}>{statusLabel[newStatus] || newStatus}</span>
                      <span style={{ fontSize: 10, color: '#475569', marginRight: 'auto' }}>خودکار</span>
                    </div>
                  )}
                  <Button kind="primary" icon="save" onClick={saveLog} disabled={saving || (!note.trim() && !outcome)}>
                    {saving ? 'در حال ذخیره...' : 'ذخیره فعالیت'}
                  </Button>
                </div>
              </div>
            )}

            {/* ─── لیست تاریخچه با تاریخ شمسی ─── */}
            {detailLoading ? (
              <div style={{ padding: '16px', textAlign: 'center', color: '#374151', fontSize: 12 }}>...</div>
            ) : callLogs.length === 0 ? (
              <div style={{ padding: '16px', textAlign: 'center', color: '#374151', fontSize: 12, borderRadius: 8, border: '1px dashed rgba(255,255,255,0.07)' }}>
                هنوز تماسی ثبت نشده
              </div>
            ) : (
              <div className="col gap-6">
                {callLogs.map((log, i) => {
                  // ─── رویداد ارجاع ───
                  if (log.event_type === 'refer') {
                    return (
                      <div key={log.id} style={{ padding: '9px 12px', borderRadius: 8, background: 'rgba(251,146,60,0.07)', border: '1px solid rgba(251,146,60,0.2)' }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                          <span style={{ fontSize: 14 }}>🔀</span>
                          <div style={{ flex: 1 }}>
                            <div style={{ fontSize: 12, fontWeight: 600, color: '#FB923C' }}>
                              ارجاع به {log.refer_to_name || '—'}
                            </div>
                            {log.refer_reason && (
                              <div style={{ fontSize: 11, color: '#94a3b8', marginTop: 2 }}>دلیل: {log.refer_reason}</div>
                            )}
                          </div>
                          <span style={{ fontSize: 10, color: '#475569', fontFamily: 'JetBrains Mono', flexShrink: 0 }}>
                            {toShamsiTimeUTC(log.created_at)}
                          </span>
                        </div>
                      </div>
                    );
                  }
                  // ─── رویداد تماس ───
                  const o = OUTCOME_LABEL[log.outcome];
                  return (
                    <div key={log.id} style={{
                      padding: '10px 12px', borderRadius: 8,
                      background: i === 0 ? 'rgba(255,255,255,0.04)' : 'rgba(255,255,255,0.02)',
                      border: `1px solid rgba(255,255,255,${i === 0 ? '0.08' : '0.04'})`,
                    }}>
                      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
                          {o ? (
                            <span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 20, background: o.color + '18', color: o.color, whiteSpace: 'nowrap' }}>
                              {o.icon} {o.label}
                            </span>
                          ) : (
                            <span style={{ fontSize: 11, color: '#475569' }}>—</span>
                          )}
                          {/* نام فروشنده‌ای که تماس گرفته */}
                          {log.seller_name && (
                            <span style={{ fontSize: 10, padding: '2px 7px', borderRadius: 20, background: 'rgba(99,102,241,0.12)', color: '#818CF8', whiteSpace: 'nowrap' }}>
                              👤 {log.seller_name}
                            </span>
                          )}
                          {log.follow_up_at && (
                            <span style={{ fontSize: 10, color: '#fbbf24', whiteSpace: 'nowrap' }}>🔔 {toShamsi(log.follow_up_at)}</span>
                          )}
                        </div>
                        <span style={{ fontSize: 10, color: '#475569', fontFamily: 'JetBrains Mono', flexShrink: 0, direction: 'ltr' }}>
                          {toShamsiTimeUTC(log.created_at)}
                        </span>
                      </div>
                      {log.note && (
                        <div style={{ fontSize: 12, color: '#94a3b8', marginTop: 6, lineHeight: 1.7, direction: 'rtl' }}>
                          {log.note}
                        </div>
                      )}
                      {log.lost_reason && (
                        <div style={{ marginTop: 5 }}>
                          <span style={{ fontSize: 10, padding: '2px 7px', borderRadius: 6, background: 'rgba(107,114,128,0.18)', color: '#9CA3AF' }}>
                            {{
                              price: '💸 قیمت گران', budget: '💰 بودجه ندارد',
                              timing: '⏳ زمان مناسب نیست', competitor: '🏃 رفت پیش رقیب',
                              no_need: '🙅 نیازی ندارد', already_bought: '🛒 جای دیگری خریده',
                              other: '📌 سایر',
                            }[log.lost_reason] || log.lost_reason}
                          </span>
                        </div>
                      )}
                      {log.sale_amount && (
                        <div style={{ fontSize: 11, color: '#34D399', marginTop: 5, fontFamily: 'JetBrains Mono' }}>
                          💰 {Number(log.sale_amount).toLocaleString('fa-IR')} تومان
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            )}
          </section>

          {/* ─── مکالمه ─── */}
          <Button kind="ghost" icon="message-circle" onClick={() => setShowConvPopup(true)}>مشاهده مکالمه</Button>
          {showConvPopup && <ConvPopup lead={lead} token={token} onClose={() => setShowConvPopup(false)} />}

        </div>
      </div>

      {/* ─── فوتر: دکمه دستیار AI ─── */}
      <div style={{
        padding: '10px 16px', flexShrink: 0,
        borderTop: '1px solid rgba(255,255,255,0.06)',
        background: '#0d0d1a',
      }}>
        <button onClick={() => setShowAI(p => !p)} style={{
          width: '100%', display: 'flex', alignItems: 'center', gap: 8,
          padding: '9px 14px', borderRadius: 8, cursor: 'pointer',
          background: showAI ? 'rgba(99,102,241,0.14)' : 'rgba(255,255,255,0.04)',
          border: `1px solid ${showAI ? 'rgba(99,102,241,0.38)' : 'rgba(255,255,255,0.08)'}`,
          color: showAI ? '#818CF8' : '#64748b',
          transition: 'all 0.15s',
        }}>
          <span style={{ fontSize: 16 }}>🤖</span>
          <span style={{ fontSize: 12, fontWeight: 600 }}>دستیار هوش مصنوعی</span>
          <span style={{ fontSize: 10, marginRight: 'auto', opacity: 0.6 }}>{showAI ? '▼ بستن' : '▲ باز کردن'}</span>
        </button>
      </div>

      {/* ─── پنل داک‌شده AI ─── */}
      {showAI && <AIDockedPanel lead={lead} token={token} onClose={() => setShowAI(false)} />}
    </>
  );
};

// ─── پنل داک‌شده دستیار AI (چسبیده به پایین صفحه) ──────────
const AIDockedPanel = ({ lead, token, onClose }) => {
  const { Button } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };
  const [brief, setBrief] = useState(null);
  const [loading, setLoading] = useState(true);
  const [minimized, setMinimized] = useState(false);

  const cacheKey = `brief_${lead.id}_${lead.call_count || 0}_${(lead.updated_at || '').slice(0, 16)}`;
  const moodLabel = { eager: '🔥 آماده خرید', interested: '😊 علاقمند', hesitant: '🤔 مردد', cold: '❄️ سرد', unknown: '❓ نامشخص' };
  const moodColor = { eager: '#34D399', interested: '#60A5FA', hesitant: '#FB923C', cold: '#94A3B8', unknown: '#6B7280' };

  useEffect(() => {
    try {
      const cached = sessionStorage.getItem(cacheKey);
      if (cached) { setBrief(JSON.parse(cached)); setLoading(false); return; }
    } catch {}
    setLoading(true);
    const products = (window.SB_DATA?.PRODUCTS || []).filter(p => p.active !== false);
    fetch(`/api/leads/${lead.id}/call-brief`, {
      method: 'POST', headers,
      body: JSON.stringify({ products }),
    })
      .then(r => r.json())
      .then(d => {
        if (d.success) {
          setBrief(d.data);
          try { sessionStorage.setItem(cacheKey, JSON.stringify(d.data)); } catch {}
        }
      })
      .catch(() => {})
      .finally(() => setLoading(false));
  }, []);

  return (
    <div style={{
      position: 'fixed', bottom: 0, left: 24, width: 360, zIndex: 9998,
      background: '#13131f', border: '1px solid #2a2a3d',
      borderRadius: '12px 12px 0 0',
      boxShadow: '0 -8px 40px rgba(0,0,0,0.65)',
      display: 'flex', flexDirection: 'column',
      transition: 'max-height 0.2s ease',
    }}>
      {/* ─── هدر: کلیک = minimize ─── */}
      <div onClick={() => setMinimized(p => !p)} style={{
        display: 'flex', alignItems: 'center', gap: 10,
        padding: '11px 14px', cursor: 'pointer', userSelect: 'none',
        background: 'rgba(99,102,241,0.09)',
        borderRadius: minimized ? '12px 12px 0 0' : '12px 12px 0 0',
        borderBottom: minimized ? 'none' : '1px solid #2a2a3d',
      }}>
        <div style={{ width: 30, height: 30, borderRadius: '50%', background: 'rgba(99,102,241,0.2)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 15, flexShrink: 0 }}>🤖</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 12, fontWeight: 700, color: '#818CF8' }}>دستیار تماس</div>
          <div style={{ fontSize: 10, color: '#475569', marginTop: 1 }}>{lead.full_name || lead.username || 'ناشناس'}</div>
        </div>
        {loading && <span style={{ fontSize: 10, color: '#475569' }}>در حال تحلیل...</span>}
        <span style={{ fontSize: 11, color: '#475569', marginLeft: 4 }}>{minimized ? '▲' : '▼'}</span>
        <button onClick={e => { e.stopPropagation(); onClose(); }} style={{
          background: 'rgba(255,255,255,0.05)', border: 'none', cursor: 'pointer',
          color: '#64748b', fontSize: 13, width: 24, height: 24, borderRadius: 6,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>✕</button>
      </div>

      {/* ─── محتوا ─── */}
      {!minimized && (
        <div style={{ padding: '12px 14px', overflowY: 'auto', maxHeight: 420, display: 'flex', flexDirection: 'column', gap: 10 }}>
          {loading && (
            <div style={{ textAlign: 'center', padding: '28px 0', color: '#64748b' }}>
              <div style={{ fontSize: 32, marginBottom: 8 }}>🤖</div>
              <div style={{ fontSize: 12 }}>در حال تحلیل مکالمه...</div>
              <div style={{ fontSize: 10, color: '#374151', marginTop: 4 }}>چند ثانیه صبر کنید</div>
            </div>
          )}
          {!loading && !brief && (
            <div style={{ textAlign: 'center', padding: '20px 0', color: '#64748b', fontSize: 12 }}>
              اطلاعات کافی برای تحلیل موجود نیست
            </div>
          )}
          {!loading && brief && (
            <>
              {/* mood */}
              <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
                <span style={{ fontSize: 18 }}>{(moodLabel[brief.mood] || '').split(' ')[0]}</span>
                <span style={{ fontSize: 11, padding: '2px 9px', borderRadius: 20, background: (moodColor[brief.mood] || '#6B7280') + '22', color: moodColor[brief.mood] || '#6B7280' }}>
                  {(moodLabel[brief.mood] || '').replace(/^.+ /, '')}
                </span>
                <span style={{ fontSize: 11, padding: '2px 9px', borderRadius: 20, background: 'rgba(99,102,241,0.15)', color: '#818CF8' }}>
                  📞 {fa(lead.call_count || 0)} تماس
                </span>
                {brief.main_concern && (
                  <span style={{ fontSize: 10, padding: '2px 8px', borderRadius: 20, background: 'rgba(251,146,60,0.15)', color: '#FB923C' }}>⚠️ {brief.main_concern}</span>
                )}
              </div>
              {/* استراتژی */}
              {brief.call_strategy && (
                <div style={{ padding: '9px 12px', borderRadius: 8, background: 'rgba(99,102,241,0.1)', borderRight: '3px solid #818CF8', fontSize: 12, lineHeight: 1.6, color: '#e2e8f0', direction: 'rtl' }}>
                  🎯 {brief.call_strategy}
                </div>
              )}
              {/* خلاصه + پیشنهادها */}
              <div style={{ background: 'rgba(255,255,255,0.03)', borderRadius: 8, padding: '10px 12px', display: 'flex', flexDirection: 'column', gap: 6 }}>
                <div style={{ fontSize: 12, color: '#94a3b8', lineHeight: 1.7, direction: 'rtl' }}>{brief.summary}</div>
                {brief.suggestions?.map((s, i) => (
                  <div key={i} style={{ display: 'flex', gap: 6, fontSize: 12, color: '#cbd5e1', direction: 'rtl' }}>
                    <span style={{ color: '#818CF8', flexShrink: 0 }}>←</span><span>{s}</span>
                  </div>
                ))}
              </div>
              {/* محصولات */}
              {brief.product_picks?.length > 0 && (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
                  {brief.product_picks.map((p, i) => (
                    <span key={i} style={{ fontSize: 10, padding: '3px 8px', borderRadius: 20, background: 'rgba(99,102,241,0.18)', color: '#a5b4fc' }}>📦 {p.name} — {p.pitch}</span>
                  ))}
                </div>
              )}
              {/* هشدار */}
              {brief.warning && (
                <div style={{ padding: '7px 10px', borderRadius: 8, background: 'rgba(248,113,113,0.1)', borderRight: '3px solid #F87171', fontSize: 11, color: '#F87171', direction: 'rtl' }}>
                  🚨 {brief.warning}
                </div>
              )}
              {/* دکمه تماس */}
              {lead.phone && (
                <a href={`tel:${lead.phone}`} style={{ textDecoration: 'none' }}>
                  <Button kind="primary" icon="phone" style={{ width: '100%' }}>
                    تماس — {lead.phone}
                  </Button>
                </a>
              )}
            </>
          )}
        </div>
      )}
    </div>
  );
};

const Info = ({ label, value, mono }) => (
  <div className="col gap-4">
    <div className="text-xs text-3">{label}</div>
    <div className={`text-sm semi ${mono ? 'mono' : ''}`}>{value}</div>
  </div>
);

// ─── helper: draggable panel ──────────────────────────────
const useDrag = (initX, initY) => {
  const [pos, setPos] = useState({ x: initX, y: initY });
  const drag = useRef({ on: false, ox: 0, oy: 0, px: 0, py: 0 });
  const onMouseDown = (e) => {
    if (e.target.closest('button,input,textarea,a,select')) return;
    drag.current = { on: true, ox: e.clientX, oy: e.clientY, px: pos.x, py: pos.y };
    e.preventDefault();
  };
  useEffect(() => {
    const move = (e) => {
      if (!drag.current.on) return;
      setPos({ x: drag.current.px + (e.clientX - drag.current.ox), y: drag.current.py + (e.clientY - drag.current.oy) });
    };
    const up = () => { drag.current.on = false; };
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
    return () => { window.removeEventListener('mousemove', move); window.removeEventListener('mouseup', up); };
  }, []);
  return [pos, onMouseDown];
};

// ─── Modal دستیار تماس ────────────────────────────────────
const CallModal = ({ lead, token, onClose, onDone }) => {
  const { Icon, Button } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };

  const [brief, setBrief] = useState(null);
  const [loading, setLoading] = useState(false);
  const [showLog, setShowLog] = useState(false);

  // ─── Cache key: تغییر می‌کنه فقط وقتی تماس جدید یا پیام جدید باشه
  const cacheKey = `brief_${lead.id}_${lead.call_count || 0}_${(lead.updated_at || '').slice(0, 16)}`;

  const moodLabel = { eager: '🔥 آماده خرید', interested: '😊 علاقمند', hesitant: '🤔 مردد', cold: '❄️ سرد', unknown: '❓ نامشخص' };
  const moodColor = { eager: '#34D399', interested: '#60A5FA', hesitant: '#FB923C', cold: '#94A3B8', unknown: '#6B7280' };

  useEffect(() => {
    // از cache بخون اگه موجوده
    try {
      const cached = sessionStorage.getItem(cacheKey);
      if (cached) { setBrief(JSON.parse(cached)); return; }
    } catch {}
    // وگرنه از API بگیر
    setLoading(true);
    const products = (window.SB_DATA?.PRODUCTS || []).filter(p => p.active !== false);
    fetch(`/api/leads/${lead.id}/call-brief`, {
      method: 'POST', headers,
      body: JSON.stringify({ products }),
    })
      .then(r => r.json())
      .then(d => {
        if (d.success) {
          setBrief(d.data);
          try { sessionStorage.setItem(cacheKey, JSON.stringify(d.data)); } catch {}
        }
      })
      .catch(() => {})
      .finally(() => setLoading(false));
  }, []);

  // ─── پنجره ۱: راهنما (draggable)
  const [briefMin, setBriefMin] = useState(false);
  const [briefPos, onBriefDrag] = useDrag(24, window.innerHeight - 520);

  // ─── پنجره ۲: ثبت نتیجه (draggable، جدا)
  const [note, setNote] = useState('');
  const [outcome, setOutcome] = useState('');
  const [newStatus, setNewStatus] = useState(lead.status);

  // وقتی نتیجه انتخاب می‌شه، وضعیت رو خودکار پیشنهاد بده
  useEffect(() => {
    if (outcome && OUTCOME_STATUS[outcome]) setNewStatus(OUTCOME_STATUS[outcome]);
  }, [outcome]);
  const [followUpAt,  setFollowUpAt]  = useState('');
  const [saleAmount,  setSaleAmount]  = useState('');
  const [saving, setSaving] = useState(false);
  const [logMin, setLogMin] = useState(false);
  const [logPos, onLogDrag] = useDrag(420, window.innerHeight - 480);

  const defaultFollowUp = () => {
    const d = new Date(); d.setDate(d.getDate() + 1);
    return d.toISOString().slice(0, 16);
  };

  const saveLog = () => {
    if (!note.trim() && !outcome) return;
    setSaving(true);
    let followUpUtc = null;
    if (followUpAt) { try { followUpUtc = new Date(followUpAt).toISOString().slice(0, 16); } catch {} }
    const body = { note, outcome, new_status: newStatus, follow_up_at: followUpUtc };
    if (outcome === 'sold' && saleAmount) body.sale_amount = parseFloat(saleAmount) || 0;
    fetch(`/api/leads/${lead.id}/call-log`, {
      method: 'POST', headers,
      body: JSON.stringify(body),
    })
      .then(r => r.json())
      .then(d => {
        if (d.success) {
          // حذف cache تا دفعه بعد دوباره تحلیل بشه
          try { sessionStorage.removeItem(cacheKey); } catch {}
          onDone(newStatus);
        }
      })
      .finally(() => setSaving(false));
  };

  const panelBase = (pos) => ({
    position: 'fixed', left: pos.x, top: pos.y, zIndex: 9999,
    width: 360, background: '#13131f', border: '1px solid #2a2a3d',
    borderRadius: 12, boxShadow: '0 16px 48px rgba(0,0,0,0.7)',
    display: 'flex', flexDirection: 'column', overflow: 'hidden',
  });

  const headerStyle = (color = '#1a1a2e') => ({
    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    padding: '10px 12px', background: color, cursor: 'grab',
    borderBottom: '1px solid #2a2a3d', userSelect: 'none',
  });

  const BtnMin = ({ min, onToggle }) => (
    <button onClick={onToggle} style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#64748b', fontSize: 15, padding: '0 4px' }}>
      {min ? '▲' : '▼'}
    </button>
  );
  const BtnClose = ({ onClick }) => (
    <button onClick={onClick} style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#64748b', fontSize: 15, padding: '0 4px' }}>✕</button>
  );

  return (
    <>
      {/* ══ پنجره ۱: راهنمای تماس ══ */}
      <div style={panelBase(briefPos)}>
        <div style={headerStyle()} onMouseDown={onBriefDrag}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{ fontSize: 14 }}>🤖</span>
            <div>
              <div style={{ fontSize: 12, fontWeight: 600, color: '#e2e8f0' }}>راهنمای تماس</div>
              <div style={{ fontSize: 10, color: '#64748b' }}>{lead.full_name || lead.username || 'ناشناس'}</div>
            </div>
          </div>
          <div style={{ display: 'flex', gap: 2 }}>
            <button onClick={() => {
              if (!note && brief) {
                const lines = [];
                if (brief.summary) lines.push(`وضعیت: ${brief.summary}`);
                if (brief.main_concern) lines.push(`نگرانی: ${brief.main_concern}`);
                lines.push('نتیجه تماس: '); lines.push('قدم بعدی: ');
                setNote(lines.join('\n'));
              }
              setShowLog(true);
            }} style={{ background: 'rgba(99,102,241,0.2)', border: 'none', cursor: 'pointer', color: '#818CF8', fontSize: 10, padding: '3px 8px', borderRadius: 6 }}>
              📝 ثبت
            </button>
            <BtnMin min={briefMin} onToggle={() => setBriefMin(p => !p)} />
            <BtnClose onClick={onClose} />
          </div>
        </div>

        {!briefMin && (
          <div style={{ padding: '12px', display: 'flex', flexDirection: 'column', gap: 10, maxHeight: 'calc(100vh - 200px)', overflowY: 'auto' }}>
            {loading && (
              <div style={{ textAlign: 'center', padding: '24px 0', color: '#64748b' }}>
                <div style={{ fontSize: 24, marginBottom: 8 }}>🤖</div>
                <div style={{ fontSize: 12 }}>در حال تحلیل...</div>
              </div>
            )}
            {!loading && !brief && (
              <div style={{ textAlign: 'center', padding: '20px 0', color: '#64748b', fontSize: 12 }}>اطلاعات کافی موجود نیست</div>
            )}
            {!loading && brief && (
              <>
                <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
                  <span style={{ fontSize: 16 }}>{moodLabel[brief.mood]?.split(' ')[0]}</span>
                  <span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 20, background: (moodColor[brief.mood] || '#6B7280') + '22', color: moodColor[brief.mood] || '#6B7280' }}>
                    {(moodLabel[brief.mood] || '').replace(/^.+ /, '')}
                  </span>
                  <span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 20, background: 'rgba(99,102,241,0.15)', color: '#818CF8' }}>
                    📞 {fa(lead.call_count || 0)} تماس
                  </span>
                  {brief.main_concern && (
                    <span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 20, background: 'rgba(251,146,60,0.15)', color: '#FB923C' }}>⚠️ {brief.main_concern}</span>
                  )}
                </div>
                {brief.call_strategy && (
                  <div style={{ padding: '8px 12px', borderRadius: 8, background: 'rgba(99,102,241,0.12)', borderRight: '3px solid #818CF8', fontSize: 12, lineHeight: 1.6, color: '#e2e8f0' }}>
                    🎯 {brief.call_strategy}
                  </div>
                )}
                <div style={{ background: '#1a1a2e', borderRadius: 8, padding: '10px 12px', display: 'flex', flexDirection: 'column', gap: 6 }}>
                  <div style={{ fontSize: 12, color: '#94a3b8', lineHeight: 1.6 }}>{brief.summary}</div>
                  {brief.suggestions?.map((s, i) => (
                    <div key={i} style={{ display: 'flex', gap: 6, fontSize: 12, color: '#cbd5e1' }}>
                      <span style={{ color: '#818CF8' }}>←</span><span>{s}</span>
                    </div>
                  ))}
                </div>
                {brief.alternative_channels?.length > 0 && (
                  <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center', padding: '6px 10px', borderRadius: 8, background: 'rgba(52,211,153,0.08)', border: '1px dashed rgba(52,211,153,0.25)' }}>
                    <span style={{ fontSize: 11, color: '#34D399' }}>💡</span>
                    {brief.alternative_channels.map((c, i) => (
                      <span key={i} style={{ fontSize: 11, padding: '2px 7px', borderRadius: 20, background: 'rgba(52,211,153,0.15)', color: '#34D399' }}>{c}</span>
                    ))}
                  </div>
                )}
                {(brief.product_picks?.length > 0 || brief.talking_points?.length > 0) && (
                  <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
                    {brief.product_picks?.map((p, i) => (
                      <span key={i} style={{ fontSize: 10, padding: '3px 8px', borderRadius: 20, background: 'rgba(99,102,241,0.18)', color: '#a5b4fc' }}>📦 {p.name} — {p.pitch}</span>
                    ))}
                    {brief.talking_points?.map((t, i) => (
                      <span key={i} style={{ fontSize: 10, padding: '3px 8px', borderRadius: 20, background: 'rgba(255,255,255,0.05)', color: '#64748b' }}>{t}</span>
                    ))}
                  </div>
                )}
                {brief.warning && (
                  <div style={{ padding: '6px 10px', borderRadius: 8, background: 'rgba(248,113,113,0.1)', borderRight: '3px solid #F87171', fontSize: 11, color: '#F87171' }}>
                    🚨 {brief.warning}
                  </div>
                )}
                {lead.phone && (
                  <a href={`tel:${lead.phone}`} style={{ textDecoration: 'none', display: 'block' }}>
                    <Button kind="primary" icon="phone" style={{ width: '100%' }}>تماس بگیر — {lead.phone}</Button>
                  </a>
                )}
              </>
            )}
          </div>
        )}
      </div>

      {/* ══ پنجره ۲: ثبت نتیجه (مستقل) ══ */}
      {showLog && (
        <div style={panelBase(logPos)}>
          <div style={headerStyle('#1a1a2e')} onMouseDown={onLogDrag}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <span style={{ fontSize: 14 }}>📝</span>
              <div>
                <div style={{ fontSize: 12, fontWeight: 600, color: '#e2e8f0' }}>ثبت نتیجه تماس</div>
                <div style={{ fontSize: 10, color: '#64748b' }}>{lead.full_name || lead.username}</div>
              </div>
            </div>
            <div style={{ display: 'flex', gap: 2 }}>
              <BtnMin min={logMin} onToggle={() => setLogMin(p => !p)} />
              <BtnClose onClick={() => setShowLog(false)} />
            </div>
          </div>
          {!logMin && (
            <div style={{ padding: '12px', display: 'flex', flexDirection: 'column', gap: 12, maxHeight: 'calc(100vh - 200px)', overflowY: 'auto' }}>
              {/* نتیجه */}
              <div>
                <div style={{ fontSize: 11, color: '#64748b', marginBottom: 6 }}>نتیجه تماس</div>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                  {Object.entries(OUTCOME_LABEL).map(([id, o]) => (
                    <button key={id} onClick={() => setOutcome(id)} style={{
                      padding: '5px 10px', borderRadius: 8, fontSize: 11, cursor: 'pointer', border: 'none',
                      background: outcome === id ? (o.color + '28') : 'rgba(255,255,255,0.06)',
                      color: outcome === id ? o.color : '#94a3b8',
                      fontWeight: outcome === id ? 600 : 400,
                    }}>{o.icon} {o.label}</button>
                  ))}
                </div>
              </div>
              {/* مبلغ فروش — فقط وقتی نتیجه "فروش" انتخاب شده */}
              {outcome === 'sold' && (
                <div style={{ padding: '10px 12px', borderRadius: 8, background: 'rgba(52,211,153,0.08)', border: '1px solid rgba(52,211,153,0.25)' }}>
                  <div style={{ fontSize: 11, color: '#34D399', marginBottom: 6, fontWeight: 600 }}>💰 مبلغ فروش <span style={{ color: '#34D399', opacity: 0.6 }}>(برای ارزیابی عملکرد)</span></div>
                  <input
                    type="number" value={saleAmount} onChange={e => setSaleAmount(e.target.value)}
                    placeholder="مثلا: 2500000"
                    style={{ width: '100%', padding: '8px 12px', borderRadius: 8, background: 'rgba(52,211,153,0.08)', border: '1px solid rgba(52,211,153,0.3)', color: '#34D399', fontSize: 14, outline: 'none', fontFamily: 'JetBrains Mono', boxSizing: 'border-box', direction: 'ltr' }} />
                  <div style={{ fontSize: 10, color: '#374151', marginTop: 4 }}>تومان — اگه هنوز مشخص نیست خالی بذارید</div>
                </div>
              )}
              {/* یادآور */}
              <div>
                <div style={{ fontSize: 11, color: '#64748b', marginBottom: 6 }}>🔔 یادآور بعدی <span style={{ color: '#374151' }}>(اختیاری)</span></div>
                <div style={{ display: 'flex', gap: 6 }}>
                  <input type="datetime-local" value={followUpAt} onChange={e => setFollowUpAt(e.target.value)}
                    style={{ flex: 1, background: '#1a1a2e', border: '1px solid #2a2a3d', borderRadius: 8, padding: '6px 8px', color: '#e2e8f0', fontSize: 12, outline: 'none', colorScheme: 'dark' }} />
                  <button onClick={() => setFollowUpAt(defaultFollowUp())} style={{ padding: '6px 10px', borderRadius: 8, fontSize: 11, cursor: 'pointer', border: '1px solid #3730a3', background: 'rgba(99,102,241,0.12)', color: '#818CF8' }}>فردا</button>
                  {followUpAt && <button onClick={() => setFollowUpAt('')} style={{ padding: '6px 8px', borderRadius: 8, fontSize: 11, cursor: 'pointer', border: 'none', background: 'rgba(248,113,113,0.1)', color: '#F87171' }}>✕</button>}
                </div>
              </div>
              {/* یادداشت */}
              <div>
                <div style={{ fontSize: 11, color: '#64748b', marginBottom: 6 }}>یادداشت</div>
                <textarea value={note} onChange={e => setNote(e.target.value)}
                  style={{ width: '100%', minHeight: 90, background: '#1a1a2e', border: '1px solid #2a2a3d', borderRadius: 8, padding: 10, color: '#e2e8f0', fontSize: 12, resize: 'vertical', outline: 'none', direction: 'rtl', fontFamily: 'inherit', boxSizing: 'border-box' }} />
              </div>
              {/* وضعیت: خودکار از نتیجه تماس، فقط نمایش */}
              {newStatus !== lead.status && (
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 12px', borderRadius: 8, background: (statusColor[newStatus] || '#6B7280') + '12', border: `1px solid ${(statusColor[newStatus] || '#6B7280')}30` }}>
                  <span style={{ fontSize: 11, color: '#475569' }}>وضعیت لید:</span>
                  <span style={{ fontSize: 11, color: '#6B7280', textDecoration: 'line-through' }}>{statusLabel[lead.status] || lead.status}</span>
                  <span style={{ fontSize: 11, color: '#475569' }}>←</span>
                  <span style={{ fontSize: 12, fontWeight: 700, color: statusColor[newStatus] || '#6B7280' }}>{statusLabel[newStatus] || newStatus}</span>
                  <span style={{ fontSize: 10, color: '#475569', marginRight: 'auto' }}>خودکار</span>
                </div>
              )}
              <Button kind="primary" icon="save" onClick={saveLog} disabled={saving || (!note.trim() && !outcome)}>
                {saving ? 'در حال ذخیره...' : 'ذخیره'}
              </Button>
            </div>
          )}
        </div>
      )}
    </>
  );
};


// ─── از market.jsx ────────────────────────────────────────
const PLATFORM_CONFIG = {
  telegram:  { label: 'تلگرام',  icon: '✈️',  color: '#38BDF8' },
  bale:      { label: 'بله',     icon: '🟣',  color: '#A78BFA' },
  instagram: { label: 'اینستا',  icon: '📸',  color: '#F472B6' },
  whatsapp:  { label: 'واتساپ', icon: '💬',  color: '#34D399' },
  direct:    { label: 'دایرکت', icon: '📩',  color: '#FB923C' },
  manual:    { label: 'دستی',   icon: '✍️',  color: '#818CF8' },
};

const STATUS_COLOR = {
  new: '#60A5FA', follow_up: '#818CF8',
  buyer: '#34D399', lost: '#6B7280',
  cancelled: '#EF4444', bad_number: '#DC2626',
};
const STATUS_LABEL = {
  new: 'جدید', follow_up: 'پیگیری', buyer: 'خریدار',
  lost: 'از دست رفته', cancelled: 'کنسل', bad_number: 'شماره اشتباه',
};

const CreateTab = ({ api, headers, toast, fa, hideTitle, onCreated, onOpenExisting }) => {
  const { useState, useEffect } = React;
  const [form, setForm] = useState({
    full_name: '', phone: '', email: '', lead_type: 'manual_customer',
    source: '', interest: '', notes: '', seller_id: '', product_id: '',
    novinhub_age: '', novinhub_budget: '', novinhub_has_system: '', novinhub_segment: '',
  });
  const [sellers,  setSellers]  = useState([]);
  const [products, setProducts] = useState([]);
  const [saving,   setSaving]   = useState(false);
  const [lastId,   setLastId]   = useState(null);
  const [dupLead,  setDupLead]  = useState(null); // {id,name,unit,status} — وقتی شماره قبلاً ثبت شده

  useEffect(() => {
    Promise.all([
      fetch('/api/market/sellers',  { headers }).then(r => r.json()),
      fetch('/api/market/products', { headers }).then(r => r.json()),
    ]).then(([s, p]) => {
      if (s.success) setSellers((s.data.sellers || []).filter(s => s.is_active));
      if (p.success) setProducts((p.data.products || []).filter(p => p.is_active !== 0));
    });
  }, []);

  const F = (k) => (e) => { setForm(f => ({ ...f, [k]: e.target.value })); if (k === 'phone') setDupLead(null); };

  const submit = () => {
    if (!form.full_name.trim() && !form.phone.trim()) {
      toast('نام یا شماره الزامی است', 'error'); return;
    }
    setSaving(true);
    setDupLead(null);
    fetch('/api/market/leads/create', {
      method: 'POST', headers,
      body: JSON.stringify({
        full_name: form.full_name.trim() || null,
        phone:     form.phone.trim()     || null,
        email:     form.email.trim()     || null,
        lead_type: form.lead_type,
        source:    form.source   || null,
        interest:  form.interest || null,
        notes:     form.notes    || null,
        seller_id: form.seller_id  || null,
        product_id:form.product_id || null,
        platform:  'manual',
        novinhub_age:         form.novinhub_age         !== '' ? form.novinhub_age         : null,
        novinhub_budget:      form.novinhub_budget      !== '' ? form.novinhub_budget      : null,
        novinhub_has_system:  form.novinhub_has_system  !== '' ? form.novinhub_has_system  : null,
        novinhub_segment:     form.novinhub_segment     || null,
      }),
    }).then(r => r.json()).then(d => {
      setSaving(false);
      if (d.success) {
        toast('لید ثبت شد', 'success');
        setLastId(d.data.id);
        setForm({ full_name: '', phone: '', email: '', lead_type: 'manual_customer', source: '', interest: '', notes: '', seller_id: '', product_id: '',
          novinhub_age: '', novinhub_budget: '', novinhub_has_system: '', novinhub_segment: '' });
        onCreated && onCreated(d.data.id);
      } else {
        toast(d.message || 'خطا', 'error');
        if (d.data?.existing_lead_id) {
          setDupLead({ id: d.data.existing_lead_id, name: d.data.existing_lead_name, unit: d.data.existing_lead_unit, status: d.data.existing_lead_status });
        }
      }
    }).catch(() => { setSaving(false); toast('خطای شبکه', 'error'); });
  };

  const inp = (label, key, placeholder, type = 'text') => (
    <div>
      <div style={{ fontSize: 11, color: '#64748b', marginBottom: 5 }}>{label}</div>
      <input type={type} value={form[key]} onChange={F(key)} placeholder={placeholder}
        style={{ width: '100%', padding: '9px 12px', borderRadius: 8, background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.12)', color: '#e2e8f0', fontSize: 13, outline: 'none', boxSizing: 'border-box' }} />
    </div>
  );

  const sel = (label, key, options) => (
    <div>
      <div style={{ fontSize: 11, color: '#64748b', marginBottom: 5 }}>{label}</div>
      <select value={form[key]} onChange={F(key)}
        style={{ width: '100%', padding: '9px 12px', borderRadius: 8, background: '#1a1a2e', border: '1px solid rgba(255,255,255,0.12)', color: form[key] ? '#e2e8f0' : '#475569', fontSize: 13, outline: 'none', boxSizing: 'border-box' }}>
        {options.map(o => <option key={o.v} value={o.v} style={{ background: '#1a1a2e', color: o.v ? '#e2e8f0' : '#475569' }}>{o.l}</option>)}
      </select>
    </div>
  );

  return (
    <div>
      {!hideTitle && <div style={{ fontSize: 13, fontWeight: 700, color: '#e2e8f0', marginBottom: 18 }}>ثبت دستی لید جدید</div>}

      {lastId && (
        <div style={{ marginBottom: 16, padding: '10px 14px', borderRadius: 9, background: 'rgba(52,211,153,0.1)', border: '1px solid rgba(52,211,153,0.3)', display: 'flex', alignItems: 'center', gap: 10 }}>
          <span style={{ fontSize: 12, color: '#34D399', flex: 1 }}>✅ لید ثبت شد</span>
          <button onClick={() => window.SB_setPage?.('leads')} style={{
            padding: '4px 12px', borderRadius: 7, fontSize: 11, cursor: 'pointer',
            border: '1px solid rgba(52,211,153,0.4)', background: 'rgba(52,211,153,0.12)', color: '#34D399', fontWeight: 600,
          }}>مشاهده در لیدها →</button>
        </div>
      )}

      {dupLead && (
        <div style={{ marginBottom: 16, padding: '10px 14px', borderRadius: 9, background: 'rgba(251,146,60,0.1)', border: '1px solid rgba(251,146,60,0.3)', display: 'flex', alignItems: 'center', gap: 10 }}>
          <span style={{ fontSize: 12, color: '#FB923C', flex: 1 }}>⚠️ این شماره قبلاً برای «{dupLead.name || dupLead.id}» ثبت شده</span>
          <button onClick={() => onOpenExisting ? onOpenExisting(dupLead.id, dupLead.name) : window.SB_setPage?.('leads')} style={{
            padding: '4px 12px', borderRadius: 7, fontSize: 11, cursor: 'pointer',
            border: '1px solid rgba(251,146,60,0.4)', background: 'rgba(251,146,60,0.12)', color: '#FB923C', fontWeight: 600,
          }}>مشاهده لیدِ موجود →</button>
        </div>
      )}

      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          {inp('نام کامل', 'full_name', 'مثلاً: علی رضایی')}
          {inp('شماره تماس', 'phone', '09xxxxxxxxx', 'tel')}
        </div>

        {inp('ایمیل (اختیاری)', 'email', 'example@email.com', 'email')}

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          {sel('نوع لید', 'lead_type', [
            { v: 'manual_customer', l: '✍️ مشتری دستی' },
            { v: 'seller',          l: '🧑‍💼 معرف' },
            { v: 'referral',        l: '🔗 ارجاعی' },
          ])}
          {sel('محصول مورد نظر', 'product_id', [
            { v: '', l: '— بدون محصول —' },
            ...products.map(p => ({ v: p.id, l: p.name })),
          ])}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          {inp('شیوه آشنایی', 'source', 'مثلاً: اینستاگرام، دوست')}
          {inp('هدف', 'interest', 'مثلاً: دوره پیشرفته')}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          {inp('سن', 'novinhub_age', 'مثلاً: 28', 'number')}
          {inp('بودجه (میلیون تومان)', 'novinhub_budget', 'مثلاً: 30', 'number')}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          {sel('سیستم دارد یا خیر', 'novinhub_has_system', [
            { v: '', l: '— مشخص نیست —' },
            { v: '1', l: '✅ دارد' },
            { v: '0', l: '📱 فقط موبایل' },
            { v: '-1', l: '❌ ندارد' },
          ])}
          {sel('سگمنت', 'novinhub_segment', [
            { v: '', l: '— مشخص نیست —' },
            { v: 'گرم', l: '🔴 گرم' },
            { v: 'ولرم', l: '🟡 ولرم' },
            { v: 'سرد', l: '🔵 سرد' },
          ])}
        </div>

        {sel('ارجاع مستقیم به فروشنده (اختیاری)', 'seller_id', [
          { v: '', l: '— وارد استخر مارکت شود —' },
          ...sellers.map(s => ({ v: s.id, l: `${s.name} (${s.active_leads || 0}/${s.max_active_leads || 50})` })),
        ])}

        <div>
          <div style={{ fontSize: 11, color: '#64748b', marginBottom: 5 }}>یادداشت</div>
          <textarea value={form.notes} onChange={F('notes')} rows={3} placeholder="اطلاعات تکمیلی..."
            style={{ width: '100%', padding: '9px 12px', borderRadius: 8, background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.12)', color: '#e2e8f0', fontSize: 13, outline: 'none', resize: 'vertical', boxSizing: 'border-box', fontFamily: 'inherit' }} />
        </div>

        <button onClick={submit} disabled={saving} style={{
          padding: '11px 0', borderRadius: 9, border: 'none', cursor: saving ? 'default' : 'pointer',
          background: saving ? 'rgba(99,102,241,0.3)' : '#6366F1', color: saving ? '#475569' : '#fff',
          fontWeight: 700, fontSize: 13,
        }}>
          {saving ? 'در حال ثبت...' : '✅ ثبت لید'}
        </button>
      </div>
    </div>
  );
};

// ─────────────────────────────────────────────────────────────────
// MarketRulesTab — قانون‌هایِ market_rules (چرخه‌ی لید/رفتار/فریز/فروشنده/دسترسی)
// قانونِ کاربر (۲۰۲۶-۰۸-۰۴): قبلاً «منتقل شده به distrules.jsx» علامت خورده بود، ولی
// اون فایل اصلاً تو پروژه وجود نداشت — این کامپوننت کاملاً یتیم/بی‌استفاده مونده بود.
// تعریفش همینجاست (چون index.html این فایل رو زودتر لود می‌کنه)، ولی خودِ رندرش از
// صفحه‌ی مستقلِ «قوانین» (rules.jsx → تبِ «⚙️ عملیاتی» → rules_ops.jsx) اتفاق می‌افته،
// نه تو تب‌هایِ همین صفحه‌ی استخر — طبقِ خواستِ کاربر، این بخش کاملاً منتقل شد به «قوانین».
// ─────────────────────────────────────────────────────────────────
// قانونِ کاربر (۲۰۲۶-۰۸-۲۰): این کامپوننت قبلاً ۳ بخش داشت (ارزیابیِ عملکرد، قوانینِ
// عملیاتی، توقفِ خودکار) — ولی «ارزیابیِ عملکرد» و «توقفِ خودکار» عیناً تویِ تبِ «توزیع»
// (RulesDistTab) هم بودن، یه تکرارِ کاملِ بی‌فایده. فقط «قوانینِ عملیاتی» نگه داشته شد،
// چون تنها جاییه که دسته‌هایِ re_request/dist_config/notifications دیده می‌شن.
const MarketRulesTab = ({ api, headers, toast, fa }) => {
  const { useState, useEffect } = React;
  const [opsRules,  setOpsRules]  = useState([]);
  const [loading,   setLoading]   = useState(true);
  const [editing,   setEditing]   = useState(null); // { rule, type: 'ops' }
  const [saving,    setSaving]    = useState(false);

  const OPS_CAT = { lead_lifecycle:'🔄 چرخه لید', behavior:'📞 رفتار تماس', freeze:'❄️ فریز', seller:'👥 فروشنده', access:'🔑 دسترسی', entry:'🚪 ورود لید', return_policy:'↩️ برگشتِ راکد', re_request:'🔁 درخواستِ مجدد', graveyard:'🪦 قبرستان', dist_config:'📤 تنظیماتِ توزیع', notifications:'🔔 اطلاع‌رسانی' };

  const load = () => {
    setLoading(true);
    fetch('/api/market/rules', { headers }).then(r => r.json()).then(o => {
      if (o.success) setOpsRules(o.data.rules || []);
      setLoading(false);
    }).catch(() => setLoading(false));
  };
  useEffect(load, []);

  const save = () => {
    if (!editing) return;
    setSaving(true);
    const { rule } = editing;
    fetch(`/api/market/rules/${rule.id}`, { method: 'PUT', headers, body: JSON.stringify({ value: rule.value, is_active: rule.is_active }) })
      .then(r => r.json()).then(d => {
        setSaving(false);
        if (d.success) { toast('ذخیره شد', 'success'); setEditing(null); load(); }
        else toast(d.message || 'خطا', 'error');
      }).catch(() => { setSaving(false); toast('خطای شبکه', 'error'); });
  };

  // ── کامپوننت یک قانون ──────────────────────────────────────
  const RuleRow = ({ rule }) => {
    const active  = rule.is_active;
    const valDisp = rule.value_type === 'boolean'
      ? (rule.value === 'true' ? '✅ بله' : '❌ خیر')
      : (rule.value + (rule.unit ? ' ' + rule.unit : ''));
    return (
      <div style={{
        display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderRadius: 9,
        background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.07)',
        opacity: active ? 1 : 0.45, transition: 'opacity 0.15s',
      }}>
        {/* toggle فعال/غیرفعال */}
        <button
          onClick={() => {
            const nextActive = rule.is_active ? 0 : 1;
            fetch(`/api/market/rules/${rule.id}`, { method: 'PUT', headers, body: JSON.stringify({ is_active: nextActive }) })
              .then(r => r.json()).then(d => { if (d.success) load(); else toast('خطا', 'error'); });
          }}
          title={active ? 'غیرفعال کن' : 'فعال کن'}
          style={{
            width: 28, height: 16, borderRadius: 8, padding: 0, border: 'none', cursor: 'pointer', flexShrink: 0,
            background: active ? 'rgba(52,211,153,0.3)' : 'rgba(107,114,128,0.2)',
            position: 'relative', transition: 'background 0.2s',
          }}>
          <div style={{
            width: 10, height: 10, borderRadius: '50%', position: 'absolute', top: 3,
            left: active ? 14 : 4, background: active ? '#34D399' : '#6B7280',
            transition: 'left 0.2s',
          }} />
        </button>

        {/* محتوا */}
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 12, fontWeight: 600, color: '#e2e8f0' }}>{rule.label || rule.name}</div>
          {rule.description && <div style={{ fontSize: 10, color: '#475569', marginTop: 2, lineHeight: 1.5 }}>{rule.description}</div>}
        </div>

        {/* مقدار */}
        <div style={{ fontSize: 12, fontWeight: 700, color: active ? '#38BDF8' : '#374151', flexShrink: 0, whiteSpace: 'nowrap' }}>
          {valDisp}
        </div>

        {/* دکمه ویرایش */}
        <button onClick={() => setEditing({ rule: { ...rule } })} style={{
          padding: '4px 10px', borderRadius: 7, fontSize: 11, cursor: 'pointer', flexShrink: 0,
          border: '1px solid rgba(99,102,241,0.25)', background: 'rgba(99,102,241,0.08)', color: '#818CF8',
        }}>
          ویرایش
        </button>
      </div>
    );
  };

  // ── گروه‌بندی ───────────────────────────────────────────────
  const opsGrouped  = opsRules.reduce((acc, r) => { (acc[r.category]  = acc[r.category]  || []).push(r); return acc; }, {});

  return (
    <div className="col gap-14">
      {loading ? (
        <div style={{ padding: 40, textAlign: 'center', color: '#374151' }}>در حال بارگذاری...</div>
      ) : (
        <div className="col gap-16">
          {Object.entries(opsGrouped).map(([cat, catRules]) => (
            <div key={cat}>
              <div style={{ fontSize: 12, fontWeight: 700, color: '#818CF8', marginBottom: 8, padding: '6px 0', borderBottom: '1px solid rgba(99,102,241,0.2)' }}>
                {OPS_CAT[cat] || cat}
              </div>
              <div className="col gap-6">
                {catRules.map(r => <RuleRow key={r.id} rule={r} />)}
              </div>
            </div>
          ))}
        </div>
      )}

      {/* ─── Modal ویرایش ─── */}
      {editing && (() => {
        const { rule } = editing;
        const name    = rule.label || rule.name;
        const desc    = rule.description;
        const vType   = rule.value_type;
        const hasRange = rule.min_value !== null && rule.max_value !== null;
        return (
          <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,0.7)', zIndex:9999, display:'flex', alignItems:'center', justifyContent:'center' }}
            onClick={e => e.target === e.currentTarget && setEditing(null)}>
            <div style={{ background:'#111118', border:'1px solid rgba(255,255,255,0.1)', borderRadius:14, padding:24, width:400 }}>
              <div style={{ fontSize:14, fontWeight:700, color:'#e2e8f0', marginBottom:4 }}>{name}</div>
              {desc && <div style={{ fontSize:11, color:'#475569', marginBottom:16, lineHeight:1.6 }}>{desc}</div>}

              {/* ورودی مقدار */}
              <div style={{ marginBottom:14 }}>
                <div style={{ fontSize:11, color:'#64748b', marginBottom:6 }}>
                  مقدار {rule.unit ? `(${rule.unit})` : ''}
                  {hasRange && <span style={{ color:'#64748b' }}> — بازه: {rule.min_value} تا {rule.max_value}</span>}
                </div>
                {vType === 'boolean' ? (
                  <div style={{ display:'flex', gap:8 }}>
                    {['true','false'].map(v => (
                      <button key={v} onClick={() => setEditing(p => ({ ...p, rule: { ...p.rule, value: v } }))} style={{
                        flex:1, padding:'9px 0', borderRadius:8, fontSize:12, cursor:'pointer', border:'none',
                        background: rule.value === v ? (v === 'true' ? 'rgba(52,211,153,0.2)' : 'rgba(248,113,113,0.2)') : 'rgba(255,255,255,0.06)',
                        color: rule.value === v ? (v === 'true' ? '#34D399' : '#F87171') : '#64748b',
                        fontWeight: rule.value === v ? 700 : 400,
                      }}>{v === 'true' ? '✅ بله' : '❌ خیر'}</button>
                    ))}
                  </div>
                ) : vType === 'text' ? (
                  <input type="text"
                    value={rule.value}
                    onChange={e => setEditing(p => ({ ...p, rule: { ...p.rule, value: e.target.value } }))}
                    style={{ width:'100%', padding:'9px 12px', borderRadius:8, background:'rgba(255,255,255,0.06)', border:'1px solid rgba(255,255,255,0.12)', color:'#e2e8f0', fontSize:13, outline:'none', fontFamily:'JetBrains Mono', boxSizing:'border-box', direction:'ltr' }} />
                ) : (
                  <input type="number"
                    value={rule.value}
                    min={rule.min_value ?? undefined}
                    max={rule.max_value ?? undefined}
                    onChange={e => setEditing(p => ({ ...p, rule: { ...p.rule, value: e.target.value } }))}
                    style={{ width:'100%', padding:'9px 12px', borderRadius:8, background:'rgba(255,255,255,0.06)', border:'1px solid rgba(255,255,255,0.12)', color:'#e2e8f0', fontSize:15, outline:'none', fontFamily:'JetBrains Mono', boxSizing:'border-box', direction:'ltr' }} />
                )}
              </div>

              {/* toggle فعال/غیرفعال */}
              <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:18, padding:'8px 12px', borderRadius:8, background:'rgba(255,255,255,0.04)' }}>
                <span style={{ flex:1, fontSize:12, color:'#94a3b8' }}>وضعیت قانون</span>
                <button
                  onClick={() => setEditing(p => ({ ...p, rule: { ...p.rule, is_active: p.rule.is_active ? 0 : 1 } }))}
                  style={{
                    padding:'4px 14px', borderRadius:20, fontSize:11, cursor:'pointer', border:'none', fontWeight:600,
                    background: rule.is_active ? 'rgba(52,211,153,0.15)' : 'rgba(107,114,128,0.15)',
                    color:      rule.is_active ? '#34D399' : '#6B7280',
                  }}>
                  {rule.is_active ? '✅ فعال' : '⏸ غیرفعال'}
                </button>
              </div>

              <div style={{ display:'flex', gap:8, justifyContent:'flex-end' }}>
                <button onClick={() => setEditing(null)} style={{ padding:'7px 16px', borderRadius:8, fontSize:12, cursor:'pointer', border:'1px solid rgba(255,255,255,0.12)', background:'transparent', color:'#64748b' }}>انصراف</button>
                <button onClick={save} disabled={saving} style={{ padding:'7px 16px', borderRadius:8, fontSize:12, cursor:'pointer', border:'none', background:'#6366F1', color:'#fff', fontWeight:600 }}>
                  {saving ? 'در حال ذخیره...' : 'ذخیره'}
                </button>
              </div>
            </div>
          </div>
        );
      })()}
    </div>
  );
};

// ─────────────────────────────────────────────────────────────────
// تب وضعیت مکالمات (ادامه)


// ─────────────────────────────────────────────────────────────────
// تب وضعیت مکالمات — دیدبانیِ گیر کردن لیدها در اسکریپت
// (از ماژول فالوآپ به اینجا منتقل شد چون پایشِ استخر لیدهاست)
// ─────────────────────────────────────────────────────────────────
const stuckColor = (h) =>
  h < 1 ? '#34D399' : h < 24 ? '#FBBF24' : h < 72 ? '#F97316' : '#F87171';
const stuckLabel = (h) => {
  if (h == null || h < 0) return 'همین الان';
  if (h < 1)  return `${Math.round(h * 60)} دقیقه`;
  if (h < 24) return `${Math.round(h)} ساعت`;
  return `${Math.round(h / 24)} روز`;
};

const ConversationStatesTab = ({ api, headers, toast, fa }) => {
  const { useState, useEffect } = React;
  const [items,    setItems]    = useState([]);
  const [loading,  setLoading]  = useState(true);
  const [selected, setSelected] = useState(null);
  const [search,   setSearch]   = useState('');
  const [bucketFilter, setBucketFilter] = useState('');
  const [sellers,  setSellers]  = useState([]);

  useEffect(() => {
    fetch('/api/market/sellers', { headers }).then(r => r.json())
      .then(d => { if (d.success) setSellers(d.data.sellers || []); }).catch(() => {});
  }, []);

  const load = () => {
    setLoading(true);
    fetch('/api/market/conversation-states?limit=300', { headers })
      .then(r => r.json())
      .then(d => { if (d.success) setItems(d.data.items || []); })
      .finally(() => setLoading(false));
  };
  useEffect(() => {
    load();
    const t = setInterval(load, 30000);
    return () => clearInterval(t);
  }, []);

  const platformIcon = (p) => (PLATFORM_CONFIG[p] || { icon: '📡' }).icon;

  if (loading) return (
    <div style={{ textAlign:'center', padding:60, color:'var(--text-3)' }}>در حال بارگذاری...</div>
  );

  if (items.length === 0) return (
    <div className="card" style={{ textAlign:'center', padding:60 }}>
      <div style={{ fontSize:40, marginBottom:10 }}>🗂️</div>
      <div style={{ fontSize:14, color:'var(--text-3)' }}>هنوز هیچ مکالمه‌ای ثبت نشده</div>
      <div style={{ fontSize:12, color:'var(--text-3)', marginTop:6, lineHeight:1.8 }}>
        بعد از اولین پیام از بات، وضعیت مکالمات اینجا نشان داده می‌شه
      </div>
    </div>
  );

  // فیلتر متن
  const q = search.trim().toLowerCase();
  const filtered = items.filter(i => {
    if (!q) return true;
    return (i.full_name || '').toLowerCase().includes(q)
        || (i.phone || '').includes(q)
        || (i.last_bot_msg || '').toLowerCase().includes(q);
  });

  const buckets = {
    active:  filtered.filter(i => i.stuck_hours <  1),
    slowing: filtered.filter(i => i.stuck_hours >= 1  && i.stuck_hours < 24),
    stalled: filtered.filter(i => i.stuck_hours >= 24 && i.stuck_hours < 72),
    dropped: filtered.filter(i => i.stuck_hours >= 72),
  };

  const META = [
    { key:'active',  title:'🟢 فعال — در حال مکالمه',            color:'#34D399', short:'فعال' },
    { key:'slowing', title:'🟡 کند شده — چند ساعته جواب نداده', color:'#FBBF24', short:'کند شده' },
    { key:'stalled', title:'🟠 گیر کرده — یک تا سه روز',         color:'#F97316', short:'گیر کرده' },
    { key:'dropped', title:'🔴 رها کرده — بیش از سه روز',         color:'#F87171', short:'رها کرده' },
  ];

  const Section = ({ title, list, color }) => {
    if (!list.length) return null;
    return (
      <div className="card" style={{ padding:0, overflow:'hidden', marginBottom:12 }}>
        <div style={{ padding:'10px 16px', borderBottom:'1px solid rgba(255,255,255,0.06)',
          display:'flex', alignItems:'center', gap:10 }}>
          <div style={{ width:8, height:8, borderRadius:'50%', background:color, flexShrink:0 }} />
          <div style={{ fontSize:12, fontWeight:600, color:'var(--text-2)' }}>{title}</div>
          <div style={{ fontSize:11, color:'var(--text-3)', marginRight:'auto' }}>
            {fa(list.length)} نفر
          </div>
        </div>
        {list.map((item, i) => (
          <div key={item.id} onClick={() => setSelected(item)}
            style={{ display:'flex', alignItems:'center', gap:12, padding:'11px 16px', cursor:'pointer',
              borderBottom: i < list.length-1 ? '1px solid rgba(255,255,255,0.03)' : 'none',
              transition:'background .15s' }}
            onMouseEnter={e => e.currentTarget.style.background='rgba(255,255,255,0.03)'}
            onMouseLeave={e => e.currentTarget.style.background='transparent'}>

            <div style={{ fontSize:16, flexShrink:0 }}>{platformIcon(item.platform)}</div>

            <div style={{ flex:1, minWidth:0 }}>
              <div style={{ fontSize:13, fontWeight:600, color:'var(--text-1)', marginBottom:2 }}>
                {item.full_name || '—'}
                {item.phone && (
                  <span style={{ marginRight:8, fontSize:11, fontFamily:'JetBrains Mono',
                    color:'var(--text-3)', fontWeight:400 }}>
                    {item.phone}
                  </span>
                )}
              </div>
              <div style={{ display:'flex', gap:8, alignItems:'center', marginBottom:3, flexWrap:'wrap' }}>
                <span style={{ fontSize:11, color:'var(--text-3)' }}>
                  📝 {item.script_name || 'پیش‌فرض'}
                </span>
                <span style={{ fontSize:11, color:'#818CF8' }}>
                  ⚡ {item.current_state_name
                    ? item.current_state_name
                    : `مرحله ${fa(item.current_step)}`}
                </span>
                {item.seller_name && (
                  <span style={{ fontSize:11, color:'#FB923C' }}>
                    🧑‍💼 {item.seller_name}
                  </span>
                )}
              </div>
              {item.last_bot_msg && (
                <div style={{ fontSize:11, color:'var(--text-3)', overflow:'hidden',
                  textOverflow:'ellipsis', whiteSpace:'nowrap', maxWidth:400 }}>
                  🤖 «{item.last_bot_msg.slice(0,70)}{item.last_bot_msg.length > 70 ? '…' : ''}»
                </div>
              )}
            </div>

            <div style={{ textAlign:'center', flexShrink:0, minWidth:64 }}>
              <div style={{ fontFamily:'JetBrains Mono', fontSize:13, fontWeight:700,
                color:stuckColor(item.stuck_hours) }}>
                {stuckLabel(item.stuck_hours)}
              </div>
              <div style={{ fontSize:10, color:'var(--text-3)', marginTop:2 }}>گیر کرده</div>
            </div>

            <div style={{ color:'var(--text-3)', fontSize:12, flexShrink:0 }}>←</div>
          </div>
        ))}
      </div>
    );
  };

  const shown = bucketFilter ? [META.find(m => m.key === bucketFilter)] : META;

  return (
    <div className="col gap-12">
      {/* جستجو + رفرش */}
      <div style={{ display:'flex', gap:8, alignItems:'center', flexWrap:'wrap' }}>
        <input value={search} onChange={e => setSearch(e.target.value)}
          placeholder="جستجوی نام، شماره یا متن پیام..."
          style={{ flex:1, minWidth:200, padding:'7px 12px', borderRadius:8,
            border:'1px solid rgba(255,255,255,0.1)', background:'rgba(255,255,255,0.04)',
            color:'var(--text-1)', fontSize:12, fontFamily:'inherit', textAlign:'right' }} />
        <button onClick={load} style={{ padding:'7px 14px', borderRadius:8, fontSize:12, cursor:'pointer',
          border:'none', background:'rgba(99,102,241,0.15)', color:'#818CF8' }}>🔄 بروزرسانی</button>
      </div>

      {/* کارت‌های شمارش (فیلتر باکت) */}
      <div style={{ display:'flex', gap:8, flexWrap:'wrap' }}>
        {META.map(m => {
          const active = bucketFilter === m.key;
          return (
            <button key={m.key} onClick={() => setBucketFilter(active ? '' : m.key)} style={{
              flex:'1 1 120px', minWidth:120, padding:'10px 12px', borderRadius:10, cursor:'pointer',
              border:`1px solid ${active ? m.color : 'rgba(255,255,255,0.08)'}`,
              background: active ? `${m.color}18` : 'rgba(255,255,255,0.04)', textAlign:'right' }}>
              <div style={{ fontSize:20, fontWeight:700, color:m.color }}>{fa(buckets[m.key].length)}</div>
              <div style={{ fontSize:11, color:'var(--text-3)', marginTop:2 }}>{m.short}</div>
            </button>
          );
        })}
      </div>

      {shown.map(m => (
        <Section key={m.key} title={m.title} list={buckets[m.key]} color={m.color} />
      ))}

      {filtered.length === 0 && (
        <div className="card" style={{ textAlign:'center', padding:40, color:'var(--text-3)', fontSize:13 }}>
          نتیجه‌ای یافت نشد
        </div>
      )}

      {selected && (
        <StateDetailModal item={selected} headers={headers} fa={fa} sellers={sellers}
          onClose={() => setSelected(null)} />
      )}
    </div>
  );
};

const StateDetailModal = ({ item, headers, fa, onClose, sellers = [] }) => {
  const { useState, useEffect } = React;
  const { Modal } = window.SB_UI;
  const [messages, setMessages] = useState([]);
  const [loading,  setLoading]  = useState(true);
  const [assignSel, setAssignSel] = useState('');
  const [assigning, setAssigning] = useState(false);
  const [assignDone, setAssignDone] = useState(false);

  const doAssign = () => {
    if (!assignSel) return;
    setAssigning(true);
    fetch('/api/market/pool/assign', {
      method: 'POST', headers,
      body: JSON.stringify({ lead_id: item.lead_id, seller_id: assignSel }),
    }).then(r => r.json()).then(d => {
      setAssigning(false);
      if (d.success) { setAssignDone(true); }
    }).catch(() => setAssigning(false));
  };

  useEffect(() => {
    fetch(`/api/market/lead-messages/${item.lead_id}?limit=40`, { headers })
      .then(r => r.json())
      .then(d => { if (d.success) setMessages(d.data); })
      .finally(() => setLoading(false));
  }, [item.lead_id]);

  const sc = stuckColor(item.stuck_hours);

  return (
    <Modal open={true} onClose={onClose} title="جزئیات مکالمه" width={560}>
      {/* هدر لید */}
      <div style={{ display:'flex', gap:12, alignItems:'flex-start', marginBottom:20,
        padding:'14px 16px', borderRadius:12, background:'var(--bg-2)' }}>
        <div style={{ fontSize:28, lineHeight:1 }}>👤</div>
        <div style={{ flex:1 }}>
          <div style={{ fontSize:15, fontWeight:700, color:'var(--text-1)', marginBottom:6 }}>
            {item.full_name || 'بدون نام'}
          </div>
          {item.phone && (
            <div style={{ fontSize:12, fontFamily:'JetBrains Mono', color:'var(--text-3)', marginBottom:6 }}>
              📞 {item.phone}
            </div>
          )}
          <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
            <span style={{ fontSize:11, padding:'2px 8px', borderRadius:20,
              background:'rgba(99,102,241,0.12)', color:'#818CF8' }}>
              📝 {item.script_name || 'پیش‌فرض'}
            </span>
            <span style={{ fontSize:11, padding:'2px 8px', borderRadius:20,
              background:'rgba(99,102,241,0.12)', color:'#818CF8' }}>
              ⚡ مرحله {fa(item.current_step)}
            </span>
            {item.seller_name && (
              <span style={{ fontSize:11, padding:'2px 8px', borderRadius:20,
                background:'rgba(251,146,60,0.12)', color:'#FB923C' }}>
                🧑‍💼 {item.seller_name}
              </span>
            )}
            <span style={{ fontSize:11, padding:'2px 8px', borderRadius:20,
              background:`${sc}15`, color:sc }}>
              ⏰ {stuckLabel(item.stuck_hours)} گیر کرده
            </span>
          </div>
        </div>
      </div>

      {/* آخرین تبادل */}
      {(item.last_bot_msg || item.last_user_msg) && (
        <div style={{ marginBottom:20 }}>
          <div style={{ fontSize:11, color:'var(--text-3)', marginBottom:8 }}>💬 آخرین تبادل</div>
          <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
            {item.last_bot_msg && (
              <div style={{ padding:'10px 14px', borderRadius:10,
                background:'rgba(99,102,241,0.07)', border:'1px solid rgba(99,102,241,0.15)',
                fontSize:12, lineHeight:1.7, color:'var(--text-2)', borderRight:'3px solid #6366F1' }}>
                <div style={{ fontSize:10, color:'#818CF8', marginBottom:4 }}>
                  🤖 ربات {item.stuck_hours > 0 ? '(بی‌پاسخ مانده)' : ''}
                </div>
                {item.last_bot_msg}
              </div>
            )}
            {item.last_user_msg && (
              <div style={{ padding:'10px 14px', borderRadius:10,
                background:'rgba(34,211,153,0.06)', border:'1px solid rgba(34,211,153,0.12)',
                fontSize:12, lineHeight:1.7, color:'var(--text-2)', borderRight:'3px solid #34D399' }}>
                <div style={{ fontSize:10, color:'#34D399', marginBottom:4 }}>👤 کاربر</div>
                {item.last_user_msg}
              </div>
            )}
          </div>
        </div>
      )}

      {/* ─── ارجاع سریع ─── */}
      {!assignDone && sellers.filter(s => s.is_active).length > 0 && (
        <div style={{ marginBottom:16, padding:'12px 14px', borderRadius:10, background:'rgba(99,102,241,0.06)', border:'1px solid rgba(99,102,241,0.18)' }}>
          <div style={{ fontSize:11, color:'#818CF8', fontWeight:600, marginBottom:8 }}>ارجاع به فروشنده</div>
          <div style={{ display:'flex', gap:8 }}>
            <select value={assignSel} onChange={e => setAssignSel(e.target.value)} style={{ flex:1, padding:'6px 10px', borderRadius:7, background:'#1a1a2e', border:'1px solid rgba(255,255,255,0.12)', color: assignSel ? '#e2e8f0' : '#64748b', fontSize:11, outline:'none' }}>
              <option value="">انتخاب فروشنده...</option>
              {sellers.filter(s => s.is_active).map(s => (
                <option key={s.id} value={s.id}>{s.name} ({s.active_leads||0}/{s.max_active_leads||50})</option>
              ))}
            </select>
            <button onClick={doAssign} disabled={!assignSel || assigning} style={{
              padding:'6px 16px', borderRadius:7, fontSize:11, cursor:'pointer', border:'none', fontWeight:600,
              background: assignSel ? '#6366F1' : 'rgba(99,102,241,0.3)',
              color: assignSel ? '#fff' : '#475569',
            }}>{assigning ? '...' : 'ارجاع'}</button>
          </div>
        </div>
      )}
      {assignDone && (
        <div style={{ marginBottom:16, padding:'8px 14px', borderRadius:8, background:'rgba(52,211,153,0.1)', border:'1px solid rgba(52,211,153,0.3)', fontSize:12, color:'#34D399' }}>
          ✅ لید به فروشنده ارجاع شد
        </div>
      )}

      {/* تاریخچه کامل */}
      <div style={{ fontSize:11, color:'var(--text-3)', marginBottom:8 }}>
        📜 تاریخچه مکالمه ({fa(messages.length)} پیام)
      </div>
      {loading ? (
        <div style={{ textAlign:'center', padding:24, color:'var(--text-3)' }}>در حال بارگذاری...</div>
      ) : messages.length === 0 ? (
        <div style={{ textAlign:'center', padding:24, color:'var(--text-3)', fontSize:12 }}>
          پیامی یافت نشد
        </div>
      ) : (
        <div style={{ maxHeight:320, overflowY:'auto', display:'flex', flexDirection:'column', gap:6,
          paddingLeft:4, paddingRight:4 }}>
          {messages.map((m, i) => (
            <div key={i} style={{ display:'flex', justifyContent: m.role === 'user' ? 'flex-end' : 'flex-start' }}>
              <div style={{
                maxWidth:'82%', padding:'8px 12px', borderRadius:12, fontSize:11, lineHeight:1.7,
                background: m.role === 'user' ? 'rgba(34,211,153,0.07)' : 'rgba(99,102,241,0.07)',
                border:`1px solid ${m.role==='user' ? 'rgba(34,211,153,0.15)' : 'rgba(99,102,241,0.15)'}`,
                color:'var(--text-2)',
              }}>
                <div style={{ fontSize:9, color: m.role==='user' ? '#34D399' : '#818CF8', marginBottom:3 }}>
                  {m.role==='user' ? '👤 کاربر' : '🤖 ربات'}
                  <span style={{ marginRight:8, color:'var(--text-4)', fontFamily:'JetBrains Mono' }}>
                    {m.created_at?.slice(11,16)}
                  </span>
                </div>
                {m.content}
              </div>
            </div>
          ))}
        </div>
      )}
    </Modal>
  );
};


// ─── استخر لید ────────────────────────────────────────────
// ─── استخر لید ───────────────────────────────────────────
const LeadPool = () => {
  const { Icon, Button, Modal, useToast } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const { useState, useEffect, useCallback, useRef } = React;
  const toast = useToast();
  const token = localStorage.getItem(window.TOKEN_KEY);
  const h = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };
  const api = (url, opts = {}) => fetch(url, { headers: h, ...opts }).then(r => r.json());

  const [tab, setTab] = window.useStickyState('tab_leadpool', 'pool');
  const [dash, setDash] = useState(null);
  const [sellers, setSellers] = useState([]);

  // قانونِ کاربر (۲۰۲۶-۰۸-۰۱): فیلترِ آمار/جدول بر اساسِ تاریخ + فروشنده، کنارِ دکمه‌ی
  // «توزیع خودکار» — برایِ همه‌ی ادمین‌ها آزاده (dash.canFilterBySeller الان همیشه true
  // برمی‌گرده، سمتِ سرور دیگه محدودیتی نمی‌ذاره).
  const [dashDateFrom, setDashDateFrom] = useState('');
  const [dashDateTo, setDashDateTo] = useState('');
  const [dashSellerId, setDashSellerId] = useState('');
  // قانونِ کاربر (۲۰۲۶-۰۸-۰۱): این فیلتر قبلاً یه ردیفِ همیشه‌بازِ جدا بود؛ حالا پشتِ یه
  // دکمه‌ی تک، دقیقاً جفتِ «توزیع خودکار»، جمع شده — کمتر شلوغ می‌کنه.
  const [showStatsFilter, setShowStatsFilter] = useState(false);

  const loadDash = useCallback(() => {
    const qs = new URLSearchParams();
    if (dashDateFrom) qs.set('date_from', dashDateFrom);
    if (dashDateTo) qs.set('date_to', dashDateTo);
    if (dashSellerId) qs.set('seller_id', dashSellerId);
    api(`/api/pool/dashboard${qs.toString() ? '?' + qs.toString() : ''}`).then(d => { if (d.success) setDash(d.data); });
  }, [dashDateFrom, dashDateTo, dashSellerId]);

  useEffect(() => { loadDash(); }, [loadDash]);
  useEffect(() => { api('/api/leads/sellers/list').then(d => { if (d.success) setSellers(d.data.sellers || []); }).catch(()=>{}); }, []);


  const TABS = [
    { id: 'pool',          label: '🌊 استخر'            },
    { id: 'segments',      label: '🧩 سگمنت‌ها'        },
    { id: 'graveyard',     label: '⚰️ قبرستان'          },
    { id: 'analytics',     label: '📊 تبدیل‌ها'         },
    { id: 'returns',       label: '↩️ برگشتی‌ها'        },
    { id: 'followup',      label: '💬 پیگیری'           },
  ];


  const statCards = dash ? [
    { label: 'کل استخر',     val: dash.pool_complete ?? dash.pool,    color: '#a78bfa', sub: 'آماده توزیع' },
    { label: 'دست فروشنده',  val: dash.sales,   color: '#60a5fa', sub: 'در حال کار' },
    { label: 'خریدار',       val: dash.buyers,  color: '#34d399', sub: `${dash.convRate}% تبدیل` },
    { label: 'فریز',         val: dash.frozen,  color: '#94a3b8', sub: 'موقتاً متوقف' },
    { label: 'از دست رفته',  val: dash.dead,    color: '#f87171', sub: 'بی‌پاسخیِ طولانی' },
    { label: 'فروش ۳۰روز',  val: dash.conv30,  color: '#fbbf24', sub: fa(Math.round(dash.rev30/1000)) + 'K تومان' },
  ] : [];

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

      {/* ─── Header ─── */}
      <div style={{ padding:'14px 20px 0', borderBottom:'1px solid var(--border)', background:'var(--surface)' }}>
        <div style={{ display:'flex', alignItems:'center', gap:12, marginBottom:12 }}>
          <div style={{ fontSize:20, fontWeight:700 }}>🌊 استخر لید</div>
          <div style={{ flex:1 }} />
          <Button size="sm" variant="ghost" onClick={() => api('/api/pool/segments/sync-novinhub-all', {method:'POST'}).then(d => { if(d.success) toast.success(`🌡️ ${d.data.updated} از ${d.data.total} لید سگمنت‌بندی شد`); })}>
            🌡️ بروزرسانیِ سگمنتِ لیدها
          </Button>
          <Button size="sm" variant="primary" onClick={() => api('/api/pool/auto-distribute', {method:'POST'}).then(d => { if(d.success) toast.success(`⚡ ${d.data.assigned||d.data.planned} لید توزیع شد`); })}>
            <Icon name="send" size={14} /> توزیع خودکار
          </Button>

          {/* ─── فیلترِ آمار/جدول بر اساسِ تاریخ + فروشنده — قانونِ کاربر (۲۰۲۶-۰۸-۰۱):
              قبلاً یه ردیفِ همیشه‌بازِ جدا بود؛ حالا پشتِ یه دکمه‌ی تک، جفتِ «توزیع خودکار». */}
          <div style={{ position:'relative' }}>
            <Button size="sm" variant="ghost" onClick={() => setShowStatsFilter(v => !v)}>
              <Icon name="calendar" size={14} /> آمار برایِ{(dashDateFrom || dashDateTo || dashSellerId) ? ' ●' : ''}
            </Button>
            {showStatsFilter && (
              <>
                <div onClick={() => setShowStatsFilter(false)} style={{ position:'fixed', inset:0, zIndex:998 }} />
                <div style={{
                  position:'absolute', top:'calc(100% + 6px)', left:0, zIndex:999, width:220,
                  background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8,
                  padding:10, display:'flex', flexDirection:'column', gap:8, boxShadow:'0 8px 24px rgba(0,0,0,0.35)',
                }}>
                  <ShamsiDateFilterMini value={dashDateFrom} onChange={setDashDateFrom} placeholder='از تاریخ' />
                  <ShamsiDateFilterMini value={dashDateTo} onChange={setDashDateTo} placeholder='تا تاریخ' />
                  {dash?.canFilterBySeller && (
                    <select style={selStyle} value={dashSellerId} onChange={e => setDashSellerId(e.target.value)}>
                      <option value=''>همه فروشندگان</option>
                      {sellers.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
                    </select>
                  )}
                  {(dashDateFrom || dashDateTo || dashSellerId) && (
                    <button onClick={() => { setDashDateFrom(''); setDashDateTo(''); setDashSellerId(''); }}
                      style={{ background:'transparent', border:'1px solid var(--border)', borderRadius:6, color:'var(--text-muted)', fontSize:11, cursor:'pointer', padding:'5px' }}>
                      پاک‌کردنِ فیلتر
                    </button>
                  )}
                </div>
              </>
            )}
          </div>
        </div>

        {/* Stats Row */}
        {dash && (
          <div style={{ display:'grid', gridTemplateColumns:'repeat(6,1fr)', gap:8, marginBottom:12 }}>
            {statCards.map(c => (
              <div key={c.label} style={{ background:'var(--bg)', border:'1px solid var(--border)', borderRadius:8, padding:'8px 10px' }}>
                <div style={{ fontSize:12, color:'var(--text-muted)', marginBottom:3 }}>{c.label}</div>
                <div style={{ fontSize:22, fontWeight:700, color:c.color }}>{fa(c.val)}</div>
                <div style={{ fontSize:12, color:'var(--text-muted)', marginTop:2 }}>{c.sub}</div>
              </div>
            ))}
          </div>
        )}

        {/* Tabs */}
        <div style={{ display:'flex', gap:4 }}>
          {TABS.map(t => (
            <button key={t.id} onClick={() => setTab(t.id)}
              style={{ padding:'6px 14px', borderRadius:'6px 6px 0 0', border:'none', cursor:'pointer', fontSize:13,
                background: tab===t.id ? 'var(--bg)' : 'transparent',
                color: tab===t.id ? 'var(--primary)' : 'var(--text-muted)',
                borderBottom: tab===t.id ? '2px solid var(--primary)' : '2px solid transparent' }}>
              {t.label}
            </button>
          ))}
        </div>
      </div>

      {/* ─── Content ─── */}
      {/* کشفِ زنده: flex:1 بدونِ minHeight:0 باعث می‌شد این کانتینر به‌جایِ کلیپ‌شدن،
          به‌اندازه‌ی محتوایِ داخلیش (مثلاً لیستِ قبرستان) رشد کنه — نتیجه: اسکرولِ
          داخلیِ خودِ تب کار نمی‌کرد و لیست از پایینِ صفحه می‌زد بیرون بدونِ اسکرول‌بار. */}
      <div style={{ flex:1, minHeight:0, overflow:'hidden' }}>
        {tab === 'pool'          && <PoolTab dash={dash} onRefresh={loadDash}
          externalDateFrom={dashDateFrom} externalDateTo={dashDateTo} externalSellerId={dashSellerId} />}
        {tab === 'segments'      && <SegmentsTab />}
        {tab === 'graveyard'     && <GraveyardTab />}
        {tab === 'analytics'     && <AnalyticsTab />}
        {tab === 'returns'       && <ReturnReportTab />}
        {tab === 'followup'      && <FollowupTab />}
      </div>
    </div>
  );
};

// ═══════════════════════════════════════════════════════════
//  بوردِ کانبانی «لیدهایِ من» — قانونِ کاربر (۲۰۲۶-۰۷-۲۶): جایِ جدول، ستون‌به‌ستون
//  (طبقِ وضعیت) با کارتِ لیدها زیرِ هر ستون، همه در یک نگاه — الهام از یه بوردِ کانبانیِ
//  مشابه که کاربر نشون داد. فقط برایِ نمایِ «فروش/لیدهایِ من» (unit=sales) جایگزینِ
//  جدول می‌شه؛ تبِ «استخر» (unit=market) همچنان جدولِ قبلی رو داره.
const KANBAN_COLUMNS = [
  { status: 'new',         label: '✨ جدید',          color: '#60a5fa' },
  { status: 're_request',  label: '🔁 درخواست مجدد',  color: '#f59e0b' },
  { status: 'follow_up',   label: '🔄 پیگیری',        color: '#94a3b8' },
  { status: 'interested',  label: '👀 علاقه‌مند',      color: '#fb923c' },
  { status: 'scheduled',   label: '📅 وقت‌دارها',      color: '#a78bfa' },
  { status: 'consultation',label: '🗣️ مشاوره',        color: '#c084fc' },
  { status: 'buyer',       label: '💰 خریدار',         color: '#34d399' },
  { status: 'lost',        label: '❌ از دست رفته',    color: '#475569' },
  { status: 'cancelled',   label: '🚫 کنسلی',          color: '#374151' },
  { status: 'bad_number',  label: '☎️ شماره اشتباه',   color: '#1f2937' },
];

const KanbanLeadCard = ({ lead, onSelect }) => {
  const { fa } = window.SB_DATA;
  const silenceHours = lead.conv_updated_at
    ? Math.round((Date.now() - new Date(lead.conv_updated_at).getTime()) / 3600000)
    : null;
  const whenLabel = silenceHours == null ? toShamsiTimeUTC(lead.created_at)
    : silenceHours < 1 ? 'همین الان'
    : silenceHours < 24 ? `${fa(silenceHours)} ساعت پیش`
    : `${fa(Math.round(silenceHours / 24))} روز پیش`;
  return (
    <div onClick={() => onSelect(lead)} style={{
      background: 'var(--surface-2, #1a1d29)', border: '1px solid var(--border-soft)', borderRadius: 10,
      padding: '10px 12px', marginBottom: 8, cursor: 'pointer', transition: 'background .12s',
    }}
      onMouseEnter={e => e.currentTarget.style.background = 'rgba(255,255,255,0.04)'}
      onMouseLeave={e => e.currentTarget.style.background = 'var(--surface-2, #1a1d29)'}>
      <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--text-1)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
        {lead.full_name || 'بدونِ نام'}
      </div>
      <div style={{ fontSize: 13, color: 'var(--text-3)', marginTop: 4, display: 'flex', alignItems: 'center', gap: 6 }}>
        <span>{lead.phone || '—'}</span>
      </div>
      <div style={{ fontSize: 12, color: 'var(--text-3)', marginTop: 6, display: 'flex', justifyContent: 'space-between' }}>
        <span>{lead.platform || ''}</span>
        <span>{whenLabel}</span>
      </div>
    </div>
  );
};

const KanbanBoard = ({ leads, onSelect, statCounts, labelOverrides }) => {
  const { fa } = window.SB_DATA;
  // قانونِ کاربر (۲۰۲۶-۰۸-۰۸): وقتی فیلترِ فروشنده فعاله، ستون‌ها باید برچسبِ سفارشیِ همون
  // فروشنده رو بگیرن و اگه اون فروشنده ستونی رو مخفی کرده، اینجا هم مخفی بمونه.
  const cols = KANBAN_COLUMNS
    .filter(col => !labelOverrides?.[col.status]?.hidden)
    .map(col => ({ ...col, label: labelOverrides?.[col.status]?.custom_label || col.label }));
  return (
    <div style={{ display: 'flex', gap: 12, overflowX: 'auto', padding: '4px 2px 12px', alignItems: 'flex-start', height: '100%' }}>
      {cols.map(col => {
        const items = leads.filter(l => l.status === col.status);
        // قانونِ کاربر (۲۰۲۶-۰۸-۰۳): items.length فقط تویِ همون صفحه‌ی لودشده (حداکثر ۵۰ تا)
        // می‌شمرد، نه کلِ واقعیِ اون وضعیت — با پیل‌هایِ بالایِ صفحه (که از آمارِ واقعیِ
        // سرور میان) نمی‌خوند. وقتی statCounts موجوده (از /api/leads/stats/overview)،
        // همون عددِ واقعی نشون داده می‌شه؛ وگرنه (نبودِ آمار) به شمارشِ محلی فال‌بک می‌کنه.
        const realCount = statCounts && statCounts[col.status] != null ? statCounts[col.status] : items.length;
        return (
          <div key={col.status} style={{ flex: '0 0 220px', minWidth: 220, display: 'flex', flexDirection: 'column' }}>
            <div style={{
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              padding: '8px 10px', borderRadius: 8, background: col.color + '18',
              color: col.color, fontSize: 14, fontWeight: 700, marginBottom: 8, position: 'sticky', top: 0,
            }}>
              <span>{col.label}</span>
              <span style={{ fontSize: 12, opacity: 0.85 }}>({fa(realCount)})</span>
            </div>
            <div style={{ overflowY: 'auto', flex: 1 }}>
              {items.length === 0
                ? <div style={{ fontSize: 13, color: 'var(--text-3)', textAlign: 'center', padding: '10px 0' }}>—</div>
                : items.map(lead => <KanbanLeadCard key={lead.id} lead={lead} onSelect={onSelect} />)}
            </div>
          </div>
        );
      })}
    </div>
  );
};

// قانونِ کاربر (۲۰۲۶-۰۸-۰۴): کلیک روی برچسبِ ستونِ «وضعیت» — تایم‌لاینِ دقیقِ اینکه لید
// کِی دستِ فروشنده رفت/برگشت، کِی زیرِ پیگیریِ محتوا افتاد، و اگه خرید کرده چه محصولی.
const STATUS_TIMELINE_ICON = { created:'🟢', assigned:'👤', return:'↩️', content:'💬', purchase:'💰', history:'📌',
  call:'📞', status_change:'🔀', score_change:'📊', note:'📝', sms:'📱', collected:'🧠', phone:'☎️', activity:'📌' };
const StatusTimelineModal = ({ lead, token, onClose }) => {
  const { useState, useEffect } = React;
  const { Modal } = window.SB_UI;
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);
  const [err, setErr] = useState('');

  useEffect(() => {
    fetch(`/api/market/leads/${lead.id}/status-timeline`, { headers: { Authorization: `Bearer ${token}` } })
      .then(r => r.json().then(d => ({ status: r.status, d })))
      .then(({ status, d }) => {
        // قانونِ کاربر (۲۰۲۶-۰۸-۰۴): وقتی داده نمیاد، به‌جایِ سکوتِ کامل، خطایِ واقعی
        // (کدِ HTTP + پیامِ سرور) رو نشون بده تا علتش (۴۰۳/۴۰۴/خطایِ کوئری) معلوم بشه.
        if (!d.success) { setErr(`خطا (${status}): ${d.message || 'نامشخص'}`); console.error('[status-timeline]', status, d); return; }
        setItems(d.data.timeline || []);
      })
      .catch(e => { setErr('خطایِ شبکه: ' + e.message); console.error('[status-timeline]', e); })
      .finally(() => setLoading(false));
  }, [lead.id]);

  return (
    <Modal open={true} onClose={onClose} title={`تاریخچه‌ی کاملِ ${lead.full_name || lead.username || 'لید'}`} width={520}>
      {loading && <div style={{ fontSize:13, color:'var(--text-muted)', padding:'10px 0' }}>در حال بارگذاری...</div>}
      {!loading && err && <div style={{ fontSize:13, color:'#f87171', padding:'10px 0' }}>{err}</div>}
      {!loading && !err && items.length === 0 && <div style={{ fontSize:13, color:'var(--text-muted)', padding:'10px 0' }}>هیچ رویدادی ثبت نشده.</div>}
      <div style={{ display:'flex', flexDirection:'column', gap:8, maxHeight:460, overflowY:'auto' }}>
        {items.map((it, i) => (
          <div key={i} style={{ display:'flex', gap:10, alignItems:'flex-start', padding:'8px 10px', borderRadius:8, background:'var(--bg-2)' }}>
            <div style={{ fontSize:18, lineHeight:1, flexShrink:0 }}>{STATUS_TIMELINE_ICON[it.type] || '•'}</div>
            <div style={{ flex:1, minWidth:0 }}>
              <div style={{ fontSize:13, fontWeight:600, color:'var(--text-1)' }}>
                {it.label}
                {it.seller_name && <span style={{ fontWeight:400, color:'var(--text-muted)' }}> — {it.seller_name}</span>}
                {it.product_name && <span style={{ fontWeight:400, color:'var(--text-muted)' }}> — {it.product_name}</span>}
              </div>
              {it.reason && <div style={{ fontSize:12, color:'var(--text-muted)', marginTop:2 }}>{it.reason}</div>}
              {it.sale_amount ? <div style={{ fontSize:12, color:'#34d399', marginTop:2 }}>{Number(it.sale_amount).toLocaleString('fa-IR')} تومان</div> : null}
            </div>
            <div style={{ fontSize:11, color:'var(--text-muted)', whiteSpace:'nowrap', flexShrink:0 }}>{toShamsiTimeUTC(it.created_at)}</div>
          </div>
        ))}
      </div>
    </Modal>
  );
};

// ═══════════════════════════════════════════════════════════
//  TAB: استخر
// ═══════════════════════════════════════════════════════════
const PoolTab = ({ dash, onRefresh, externalDateFrom, externalDateTo, externalSellerId }) => {
  const { Icon, Button, SlidePanel, useToast } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const { useState, useEffect, useCallback } = React;
  const toast = useToast();
  const token = localStorage.getItem(window.TOKEN_KEY);
  const h = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };
  const api = (url, opts = {}) => fetch(url, { headers: h, ...opts }).then(r => r.json());

  const [leads, setLeads] = useState([]);
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(false);
  const [tags, setTags] = useState([]);
  const [segments, setSegments] = useState([]);
  const [sellers, setSellers] = useState([]);
  const [sideFilter, setSideFilter] = useState({});
  // قانونِ کاربر (۲۰۲۶-۰۸-۰۸): وقتی ادمین رویِ یه فروشنده‌یِ خاص فیلتر می‌کنه، بوردِ کانبان
  // باید همون برچسب‌هایِ سفارشی‌ای رو نشون بده که خودِ اون فروشنده تویِ CRMِ خودش گذاشته.
  const [sellerLabelOverrides, setSellerLabelOverrides] = useState({});
  useEffect(() => {
    if (!sideFilter.seller_id) { setSellerLabelOverrides({}); return; }
    api(`/api/pool/seller-status-prefs/${sideFilter.seller_id}`).then(d => {
      if (d.success) {
        const m = {};
        (d.data.prefs || []).forEach(p => { m[p.status_key] = { custom_label: p.custom_label, hidden: !!p.hidden }; });
        setSellerLabelOverrides(m);
      }
    }).catch(() => {});
  }, [sideFilter.seller_id]);
  const [statusPill, setStatusPill] = useState('all');
  const [callFilter, setCallFilter] = useState('');
  const [search, setSearch] = useState('');
  const [page, setPage] = useState(1);
  const [selected, setSelected] = useState(null);
  const [editLead, setEditLead] = useState(null);
  const [quickCallLead, setQuickCallLead] = useState(null);
  const [statusTimelineLead, setStatusTimelineLead] = useState(null);
  const [poolStats, setPoolStats] = useState({});
  const [convMode, setConvMode] = useState(false);
  const [showCreate, setShowCreate] = useState(false);
  const [showImport, setShowImport] = useState(false);
  const [showNovinHub, setShowNovinHub] = useState(false);
  // قانونِ کاربر (۲۰۲۶-۰۸-۰۱): «خروجی» دیگه مستقیم دانلود نمی‌کنه — یه پنجره باز می‌شه که
  // بشه شیت‌ها (وضعیت‌ها) و بازه‌ی تاریخ رو قبل از گرفتنِ فایل انتخاب/تأیید کرد.
  const [showExportModal, setShowExportModal] = useState(false);
  const [exportSheets, setExportSheets] = useState(new Set(['new','re_request','follow_up','interested','scheduled','consultation','buyer','lost','cancelled,bad_number','duplicate']));
  // قانونِ کاربر (۲۰۲۶-۰۸-۱۱): شیتِ اضافیِ «ارسالی به فروش‌یار» — بر اساسِ تاریخِ تخصیص،
  // نه statusِ فعلی (که ممکنه بعدِ ارسال عوض شده باشه).
  const [exportIncludeAssigned, setExportIncludeAssigned] = useState(true);
  const [exportDateFrom, setExportDateFrom] = useState('');
  const [exportDateTo, setExportDateTo] = useState('');
  const [exportPlatform, setExportPlatform] = useState('');
  const [exportUnit, setExportUnit] = useState('');
  const [exportSellerId, setExportSellerId] = useState('');
  const [exportSegmentId, setExportSegmentId] = useState('');
  const [exportSearch, setExportSearch] = useState('');
  const [exportingFile, setExportingFile] = useState(false);
  const [checkedIds, setCheckedIds] = useState(new Set());
  const [deleting, setDeleting] = useState(false);
  const [confirmingDelete, setConfirmingDelete] = useState(false);
  const [deleteReason, setDeleteReason] = useState(''); // قانونِ کاربر (۲۰۲۶-۰۸-۱۰): دلیلِ حذفِ دسته‌جمعی الزامی است
  // قانونِ کاربر (۲۰۲۶-۰۸-۱۱): لیستِ قانونیِ واحدِ دلایلِ کنسلی/انصراف — همون ۵ گزینه‌ای که
  // سمتِ CRMِ فروش‌یار (leaddetail.jsx/leads.jsx) پیشنهاد می‌شه، تا دلایلِ ثبت‌شده (چه از
  // ادمین چه از فروش‌یار) توی یه دسته‌بندیِ یکسان بیفتن، نه پراکنده‌یِ آزاد.
  const CANCEL_REASON_SUGGESTIONS = [
    'قیمت/بودجه براش زیاد بود', 'دیگه علاقه‌مند نبود', 'جایِ دیگه ثبت‌نام کرد',
    'شرایطش عوض شد (وقت/شغل/...)', 'خودش صراحتاً درخواستِ کنسلی داد',
    'رایگان می‌خواست', 'درخواست نداده بود', 'قطع کرد تا فهمید ازکجا تماس می‌گیریم',
    'کلاسِ حضوری می‌خواست', 'مشکلِ لایسنس داشت / پروژه می‌خواست',
  ];
  const [assignSellerId, setAssignSellerId] = useState('');
  const [assigningBulk, setAssigningBulk] = useState(false);

  const toggleChecked = (id) => setCheckedIds(s => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });
  const toggleCheckedAll = () => setCheckedIds(s => s.size === leads.length ? new Set() : new Set(leads.map(l => l.id)));

  const runDelete = () => {
    if (!checkedIds.size) return;
    if (!deleteReason.trim()) { toast.error('دلیلِ حذف الزامی است'); return; }
    setConfirmingDelete(false);
    setDeleting(true);
    api('/api/pool/leads/bulk-delete', { method:'POST', body: JSON.stringify({ lead_ids:[...checkedIds], reason: deleteReason.trim() }) })
      .then(d => {
        if (d.success) {
          const skipped = d.data.skipped_assigned_to_seller || 0;
          toast.success(`🗑️ ${d.data.deleted} لید حذف شد` + (skipped ? ` — ${skipped} تا چون دستِ فروشنده بودن ردّ شدن` : ''));
          setCheckedIds(new Set()); setDeleteReason(''); loadLeads(); onRefresh && onRefresh();
        }
        else toast.error(d.message || 'خطا در حذف');
      })
      .finally(() => setDeleting(false));
  };

  const runBulkAssign = async () => {
    if (!checkedIds.size || !assignSellerId) return;
    setAssigningBulk(true);
    let ok = 0, fail = 0;
    let firstErr = '';
    for (const id of checkedIds) {
      try {
        const r = await api('/api/market/pool/assign', { method:'POST', body: JSON.stringify({ lead_id: id, seller_id: assignSellerId }) });
        if (r.success) ok++; else { fail++; if (!firstErr) firstErr = r.message || ''; }
      } catch { fail++; if (!firstErr) firstErr = 'خطای شبکه'; }
    }
    setAssigningBulk(false);
    setCheckedIds(new Set());
    setAssignSellerId('');
    if (ok) toast.success(`✅ ${ok} لید به فروشنده توزیع شد${fail ? ` (${fail} ناموفق: ${firstErr})` : ''}`);
    else toast.error(`توزیع انجام نشد: ${firstErr || 'خطای نامشخص'}`);
    loadLeads(); onRefresh && onRefresh();
  };

  const STATUS_OPTS = [
    { v:'', label:'همه وضعیت‌ها' },
    { v:'new', label:'جدید' }, { v:'follow_up', label:'پیگیری' },
    /* قانونِ کاربر (۲۰۲۶-۰۸-۱۱): status='consultation' توی هیچ مسیرِ CRMِ فروش‌یار ست
       نمی‌شه (فقط لایه‌ی AI/اسکریپت ازش استفاده می‌کنه) — تأییدشد صفر لید توی کلِ سیستم
       این status رو داره. عملاً فروش‌یار برایِ «مشاوره انجام شد» از scheduled (برچسبِ
       سفارشیِ «انجام شده») استفاده می‌کنه، پس این گزینه به همون status وصل شد. */
    { v:'scheduled', label:'مشاوره' },
    { v:'buyer', label:'خریدار ✅' }, { v:'lost', label:'از دست رفته' },
    { v:'cancelled', label:'انصراف' }, { v:'bad_number', label:'شماره اشتباه' },
  ];

  const POOL_STATUS_COLOR = { new:'#60a5fa', follow_up:'#94a3b8', interested:'#fb923c', scheduled:'#a78bfa', consultation:'#c084fc', buyer:'#34d399', lost:'#475569', cancelled:'#374151', bad_number:'#1f2937' };
  // قانونِ کاربر (۲۰۲۶-۰۸-۰۲): ستونِ وضعیت قبلاً کدِ خامِ انگلیسی (مثلاً «follow_up») رو
  // مستقیم نشون می‌داد؛ کاربر خواست «نحوه‌ی نوشتار»یِ نسخه‌ی قدیمی‌تر (برچسبِ فارسیِ ترجمه‌شده،
  // نه کدِ خام) بیاد — پس یه نگاشتِ کامل (هم‌راستا با تمامِ کلیدهایِ POOL_STATUS_COLOR) اضافه شد.
  const POOL_STATUS_LABEL = { new:'جدید', follow_up:'پیگیری', interested:'علاقه‌مند', scheduled:'زمان‌بندی‌شده', consultation:'مشاوره', buyer:'خریدار', lost:'از دست رفته', cancelled:'کنسل شده', bad_number:'شماره اشتباه' };

  // قانونِ کاربر (۲۰۲۶-۰۸-۰۴): ستونِ «وضعیت» باید نمایانگرِ اینکه لید دستِ کیه/چه مرحله‌ایه
  // باشه، نه صرفاً status خام — با این اولویت: خریدار > دست فروشنده > پیگیری محتوا > برگشت > جدید.
  const poolRowStatus = (lead) => {
    if (lead.status === 'buyer') return { label:'خریدار', color:'#34d399' };
    if (lead.unit === 'sales') return { label:'دست فروشنده', color:'#a78bfa' };
    if (lead.has_content_note) return { label:'پیگیری محتوا', color:'#6366f1' };
    if (lead.was_returned) return { label:'برگشت', color:'#f97316' };
    if (lead.unit === 'market' && lead.status === 'new') return { label:'وضعیت جدید', color:'#60a5fa' };
    return { label: POOL_STATUS_LABEL[lead.status] || lead.status, color: POOL_STATUS_COLOR[lead.status] || '#94a3b8' };
  };

  const POOL_OUTCOME_COLOR = { answered:'#34D399', no_answer:'#F87171', call_later:'#818CF8', follow_up:'#818CF8', scheduled:'#A78BFA', sold:'#34D399', not_interested:'#6B7280', cancelled:'#EF4444', bad_number:'#DC2626', re_request:'#60A5FA' };
  const POOL_OUTCOME_ICON  = { answered:'✅', no_answer:'📵', call_later:'⏰', follow_up:'🔄', scheduled:'📅', sold:'💰', not_interested:'❌', cancelled:'🚫', bad_number:'☎️', re_request:'🔁' };
  const POOL_OUTCOME_LABEL = { answered:'جواب داد', no_answer:'بی‌پاسخ', call_later:'بعداً', follow_up:'پیگیری', scheduled:'زمان داد', sold:'فروش', not_interested:'علاقه نداشت', cancelled:'کنسل', bad_number:'شماره اشتباه', re_request:'درخواست مجدد' };

  const statusPills = [
    { id:'all',       label:'همه',             count: poolStats.total     || 0 },
    { id:'new',         label:'✨ جدید',          count: poolStats.new        || 0 },
    { id:'follow_up',   label:'🔄 پیگیری',        count: poolStats.follow_up  || 0 },
    { id:'buyer',       label:'💰 خریدار',         count: poolStats.buyer      || 0 },
    { id:'lost',        label:'❌ از دست رفته',    count: poolStats.lost       || 0 },
    // قانونِ کاربر (۲۰۲۶-۰۸-۱۱): «درخواستِ مجدد» به‌عنوانِ پیلِ جدا حذف شد، کاملاً با
    // «تکراری» یکی شد؛ برچسبِ نمایشی روی «درخواستِ مجدد» گذاشته شد (۲۰۲۶-۰۸-۱۱).
    { id:'duplicate',   label:'📑 درخواستِ مجدد',  count: poolStats.duplicate  || 0 },
  ];

  const callFilterOpts = [
    { id:'',           label:'همه تماس‌ها',    icon:'📋' },
    { id:'called',     label:'تماس گرفته',      icon:'📞', color:'#34D399' },
    { id:'not_called', label:'تماس نگرفته',     icon:'📵', color:'#F87171' },
  ];

  const loadLeads = useCallback((silent) => {
    if (!silent) setLoading(true);
    const body = {
      ...sideFilter,
      unit: sideFilter.unit || 'pool',
      status: statusPill !== 'all' ? statusPill : (sideFilter.status || undefined),
      call_filter: sideFilter.no_activity ? 'not_called' : (callFilter || undefined),
      search: search || undefined,
      has_conversation: convMode || undefined,
      tags: sideFilter.tag ? [sideFilter.tag] : undefined,
      no_tag: sideFilter.no_tag || undefined,
      include_dead: sideFilter.include_dead || undefined,
      // قانونِ کاربر (۲۰۲۶-۰۸-۰۳): صفحه‌بندی نمی‌خواد — همه‌ی لیدهایِ مطابق با فیلتر یک‌جا لود بشن.
      page: 1, limit: 2000,
      sort: sideFilter.sort || 'created_desc',
    };
    api('/api/pool/filter', { method:'POST', body: JSON.stringify(body) })
      .then(d => { if (d.success) { setLeads(d.data.leads); setTotal(d.data.total); } })
      .finally(() => { if (!silent) setLoading(false); });
  }, [sideFilter, statusPill, callFilter, search, convMode, page]);

  // قانونِ کاربر (۲۰۲۶-۰۷-۲۶): آمارِ بالایِ ستون‌ها قبلاً همیشه `unit=pool` رو هاردکد
  // می‌کرد — یعنی تویِ تبِ «لیدهایِ من» (فروش‌یار، unit=sales + seller_id خودِ فروشنده)
  // همچنان آمارِ کلِ استخر نشون داده می‌شد، نه آمارِ واقعیِ همون فروشنده. حالا از رویِ
  // همون فیلترِ فعلی (sideFilter) ساخته می‌شه تا با چیزی که واقعاً دیده می‌شه یکی باشه.
  const loadPoolStats = useCallback(() => {
    const qs = new URLSearchParams();
    const unit = sideFilter.unit || 'pool';
    qs.set('unit', unit);
    if (sideFilter.seller_id) qs.set('seller_id', sideFilter.seller_id);
    // قانونِ کاربر (۲۰۲۶-۰۸-۰۱): پیل‌هایِ بالایِ جدول باید همون بازه‌ی تاریخِ فیلترِ
    // کنارِ «توزیع خودکار» رو ببینن — وگرنه با هر بازه‌ای همون عددِ کلِ بدونِ فیلتر می‌موند.
    if (sideFilter.date_from) qs.set('date_from', sideFilter.date_from);
    if (sideFilter.date_to) qs.set('date_to', sideFilter.date_to);
    api(`/api/leads/stats/overview?${qs.toString()}`).then(d => { if (d.success) setPoolStats(d.data.stats || {}); });
  }, [sideFilter.unit, sideFilter.seller_id, sideFilter.date_from, sideFilter.date_to]);

  useEffect(() => { loadLeads(); setCheckedIds(new Set()); setConfirmingDelete(false); }, [loadLeads]);

  useEffect(() => {
    loadPoolStats();
    api('/api/pool/tags/all').then(d => { if (d.success) setTags(d.data.tags); });
    api('/api/pool/segments').then(d => { if (d.success) setSegments(d.data.segments); });
    api('/api/leads/sellers/list').then(d => { if (d.success) setSellers(d.data.sellers); });
  }, [loadPoolStats]);

  // قانونِ کاربر (۲۰۲۶-۰۷-۲۳): این صفحه هم مثلِ «لیدهای من» فروش‌یار نباید نیازمندِ
  // رفرشِ دستی باشه — هر ۲۰ ثانیه بی‌سروصدا (بدونِ اسپینر) لیست + آمار + کارت‌های
  // بالایِ صفحه رو تازه می‌کنه.
  useEffect(() => {
    const timer = setInterval(() => {
      loadLeads(true);
      loadPoolStats();
      onRefresh && onRefresh();
    }, 20000);
    return () => clearInterval(timer);
  }, [loadLeads, loadPoolStats, onRefresh]);

  const setF = (k, v) => { setSideFilter(f => ({ ...f, [k]: v || undefined })); setPage(1); };

  // قانونِ کاربر (۲۰۲۶-۰۸-۰۱): فیلترِ تاریخ/فروشنده‌ای که بالایِ صفحه (کنارِ «توزیع خودکار»)
  // انتخاب می‌شه، باید جدولِ همینجا رو هم مثلِ کارت‌هایِ آمار فیلتر کنه — پس هر بار عوض
  // شد، توی سایدفیلترِ خودِ همین تب هم منعکس می‌شه (کاربر بازم می‌تونه از سایدبار دستی تغییرش بده).
  useEffect(() => {
    setSideFilter(f => ({ ...f, date_from: externalDateFrom || undefined, date_to: externalDateTo || undefined }));
    setPage(1);
  }, [externalDateFrom, externalDateTo]);
  useEffect(() => {
    setSideFilter(f => ({ ...f, seller_id: externalSellerId || undefined }));
    setPage(1);
  }, [externalSellerId]);

  const selectedIndex = selected ? leads.findIndex(l => l.id === selected.id) : -1;

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

      {/* ─── Status Pills ─── */}
      <div style={{ padding:'8px 12px 0', borderBottom:'1px solid var(--border)', background:'var(--surface)', flexShrink:0 }}>
        <div style={{ display:'flex', gap:4, overflowX:'auto', flexWrap:'nowrap', paddingBottom:8 }}>
          {statusPills.map(f => (
            <button key={f.id} onClick={() => {
              // قانونِ کاربر (۲۰۲۶-۰۸-۱۱): پیل و دراپ‌داونِ «همه وضعیت‌ها» قبلاً هم‌زمان
              // می‌تونستن مقدارِ متفاوت نشون بدن درحالی‌که فقط پیل واقعاً اعمال می‌شد
              // (خطِ status در loadLeads). انتخابِ پیل باید دراپ‌داون رو خالی کنه تا UI
              // همیشه با فیلترِ واقعاً اعمال‌شده هماهنگ بمونه.
              setStatusPill(f.id); setF('status', ''); setPage(1);
            }} style={{
              padding:'4px 12px', borderRadius:20, border:'none', cursor:'pointer',
              fontSize:13, whiteSpace:'nowrap',
              background: statusPill === f.id ? 'var(--primary)' : 'rgba(255,255,255,0.05)',
              color: statusPill === f.id ? '#fff' : 'var(--text-muted)',
              fontWeight: statusPill === f.id ? 600 : 400,
            }}>
              {f.label} <span style={{ fontSize:12, fontFamily:'JetBrains Mono', opacity:0.75 }}>{fa(f.count)}</span>
            </button>
          ))}
        </div>
      </div>

      <div style={{ display:'flex', flex:1, minHeight:0, overflow:'hidden' }}>

        {/* ─── Filters Sidebar ─── */}
        <div style={{ width:196, borderLeft:'1px solid var(--border)', padding:12, overflowY:'auto', background:'var(--surface)', display:'flex', flexDirection:'column', gap:10, flexShrink:0 }}>
          <div style={{ fontSize:11, fontWeight:600, color:'var(--text-muted)' }}>فیلترها</div>

          <input value={search} onChange={e => { setSearch(e.target.value); setPage(1); }}
            placeholder='🔍  جستجو نام، شماره...' style={{ ...selStyle, width:'100%' }} />

          <select style={selStyle} value={sideFilter.status||''} onChange={e => { setStatusPill('all'); setF('status', e.target.value); }}>
            {STATUS_OPTS.map(o => <option key={o.v} value={o.v}>{o.label}</option>)}
          </select>

          <select style={selStyle} value={sideFilter.platform||''} onChange={e => setF('platform', e.target.value)}>
            <option value=''>همه پلتفرم‌ها</option>
            <option value='telegram'>تلگرام</option>
            <option value='bale'>بله</option>
            <option value='rubika'>روبیکا</option>
            <option value='manual'>دستی</option>
            <option value='novinhub'>نوین‌هاب</option>
          </select>

          <select style={selStyle} value={sideFilter.unit||''} onChange={e => setF('unit', e.target.value)}>
            <option value=''>همه یونیت‌ها</option>
            <option value='market_only'>توزیع‌نشده ({fa(dash?.pool_complete ?? dash?.pool ?? 0)})</option>
            <option value='market_incomplete'>اطلاعاتِ ناقص ({fa(dash?.pool_incomplete||0)})</option>
            <option value='sales'>دست فروشنده</option>
          </select>

          <select style={selStyle} value={sideFilter.seller_id||''} onChange={e => setF('seller_id', e.target.value)}>
            <option value=''>همه فروشندگان</option>
            {sellers.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
          </select>

          <select style={selStyle} value={sideFilter.segment_id||''} onChange={e => setF('segment_id', e.target.value)}>
            <option value=''>همه سگمنت‌ها</option>
            {segments.map(s => <option key={s.id} value={s.id}>{s.icon} {s.name}</option>)}
          </select>

          <div style={{ fontSize:10, color:'var(--text-muted)', marginTop:4 }}>بازه‌ی تاریخِ ثبت (شمسی)</div>
          <ShamsiDateFilterMini value={sideFilter.date_from} onChange={v => setF('date_from', v)} placeholder='از تاریخ: 1405/04/01' />
          <ShamsiDateFilterMini value={sideFilter.date_to} onChange={v => setF('date_to', v)} placeholder='تا تاریخ: 1405/04/29' />
          <button onClick={() => { const t = todayLocalStr(); setF('date_from', t); setF('date_to', t); }}
            style={{ ...selStyle, cursor:'pointer', textAlign:'center', fontWeight:600 }}>
            📅 امروز
          </button>

          <button onClick={() => { setSideFilter({}); setSearch(''); setStatusPill('all'); setCallFilter(''); setPage(1); }}
            style={{ marginTop:'auto', padding:'6px', borderRadius:6, border:'1px solid var(--border)', background:'transparent', color:'var(--text-muted)', fontSize:11, cursor:'pointer' }}>
            پاک کردن فیلتر
          </button>
        </div>

        {/* ─── Main ─── */}
        <div style={{ flex:1, minHeight:0, display:'flex', flexDirection:'column', overflow:'hidden' }}>

          {/* toolbar: count + export */}
          <div style={{ padding:'8px 12px', borderBottom:'1px solid var(--border)', display:'flex', gap:8, alignItems:'center', flexShrink:0, flexWrap:'wrap' }}>
            <div style={{ flex:1 }} />
            <button onClick={() => { setConvMode(v => !v); setPage(1); }} style={{
              padding:'4px 10px', borderRadius:7, fontSize:11, cursor:'pointer',
              border: `1px solid ${convMode ? '#818CF8' : 'rgba(255,255,255,0.07)'}`,
              background: convMode ? 'rgba(129,140,248,0.15)' : 'transparent',
              color: convMode ? '#818CF8' : 'var(--text-muted)',
              whiteSpace:'nowrap',
            }}>💬 مکالمه‌دار</button>
            {checkedIds.size > 0 && (
              <div style={{ display:'flex', alignItems:'center', gap:6, whiteSpace:'nowrap' }}>
                <select value={assignSellerId} onChange={e => setAssignSellerId(e.target.value)} style={{ ...selStyle, width:150 }}>
                  <option value=''>— انتخاب فروشنده —</option>
                  {sellers.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
                </select>
                <button onClick={runBulkAssign} disabled={assigningBulk || !assignSellerId} style={{
                  padding:'4px 10px', borderRadius:7, fontSize:11, cursor: (assigningBulk || !assignSellerId) ? 'default' : 'pointer',
                  border:'1px solid rgba(52,211,153,0.4)', background:'rgba(52,211,153,0.12)',
                  color:'#34D399', fontWeight:600, opacity: assignSellerId ? 1 : 0.5,
                }}>{assigningBulk ? '⏳ در حال توزیع...' : `👤 توزیع به فروشنده (${fa(checkedIds.size)})`}</button>
              </div>
            )}
            {checkedIds.size > 0 && !confirmingDelete && (
              <button onClick={() => setConfirmingDelete(true)} disabled={deleting} style={{
                padding:'4px 10px', borderRadius:7, fontSize:11, cursor: deleting ? 'default' : 'pointer',
                border:'1px solid rgba(248,113,113,0.4)', background:'rgba(248,113,113,0.12)',
                color:'#F87171', whiteSpace:'nowrap', fontWeight:600,
              }}>{deleting ? '⏳ در حال حذف...' : `🗑️ حذف (${fa(checkedIds.size)})`}</button>
            )}
            {checkedIds.size > 0 && confirmingDelete && (
              <div style={{ display:'flex', alignItems:'center', gap:6, whiteSpace:'nowrap' }}>
                <span style={{ fontSize:11, color:'#F87171' }}>{fa(checkedIds.size)} لید حذف بشه؟</span>
                <input value={deleteReason} onChange={e=>setDeleteReason(e.target.value)} placeholder="دلیلِ حذف (الزامی)…" autoFocus
                  list="cancel-reason-suggestions"
                  style={{ fontSize:11, padding:'4px 8px', borderRadius:7, border:'1px solid rgba(248,113,113,0.4)', background:'var(--surface)', color:'var(--text-1)', width:160 }}/>
                {/* قانونِ کاربر (۲۰۲۶-۰۸-۱۱): لیستِ قانونیِ واحدِ دلایل — همون‌جوری که سمتِ
                    فروش‌یار (leaddetail.jsx/leads.jsx) استفاده می‌شه، تا دلایلِ ثبت‌شده تکه‌تکه
                    و پراکنده نشن (مثلِ «منصرف» vs «انصراف مشتری» که قبلاً دو دسته‌ی جدا بودن). */}
                <datalist id="cancel-reason-suggestions">
                  {CANCEL_REASON_SUGGESTIONS.map(r => <option key={r} value={r} />)}
                </datalist>
                <button onClick={runDelete} disabled={deleting || !deleteReason.trim()} style={{
                  padding:'4px 10px', borderRadius:7, fontSize:11, cursor: (deleting || !deleteReason.trim()) ? 'default' : 'pointer',
                  border:'none', background:'#F87171', color:'#111827', fontWeight:700, opacity: !deleteReason.trim() ? 0.5 : 1,
                }}>{deleting ? '⏳...' : 'بله، حذف کن'}</button>
                <button onClick={() => { setConfirmingDelete(false); setDeleteReason(''); }} disabled={deleting} style={{
                  padding:'4px 10px', borderRadius:7, fontSize:11, cursor:'pointer',
                  border:'1px solid rgba(255,255,255,0.15)', background:'transparent', color:'var(--text-muted)',
                }}>انصراف</button>
              </div>
            )}
            <span style={{ fontSize:11, color:'var(--text-muted)', whiteSpace:'nowrap' }}>{fa(total)} لید</span>
            <Button size='sm' variant='ghost' icon='download' onClick={() => {
              // قانونِ کاربر (۲۰۲۶-۰۸-۰۱): اگه لیدی تیک خورده، همون‌جا مستقیم دانلود می‌شه
              // (نیازی به انتخاب نیست، خودِ کاربر صریحاً انتخاب کرده)؛ وگرنه پنجره‌ی انتخابِ
              // شیت‌ها/بازه‌ی تاریخ باز می‌شه.
              if (checkedIds.size > 0) {
                fetch('/api/pool/leads/export-filtered', { method:'POST', headers: h, body: JSON.stringify({ lead_ids:[...checkedIds] }) })
                  .then(res => res.blob()).then(blob => {
                    const a = document.createElement('a');
                    a.href = URL.createObjectURL(blob);
                    a.download = `leads_filtered_${todayLocalStr()}.xlsx`;
                    a.click();
                  });
                return;
              }
              setExportDateFrom(sideFilter.date_from || '');
              setExportDateTo(sideFilter.date_to || '');
              setExportPlatform(sideFilter.platform || '');
              setExportUnit(sideFilter.unit || '');
              setExportSellerId(sideFilter.seller_id || '');
              setExportSegmentId(sideFilter.segment_id || '');
              setExportSearch(search || '');
              setShowExportModal(true);
            }}>خروجی</Button>
            <Button size='sm' variant='ghost' icon='upload' onClick={() => setShowImport(true)}>ایمپورت</Button>
            <Button size='sm' variant='ghost' icon='upload' onClick={() => setShowNovinHub(true)}>ایمپورت اکسل نوین‌هاب</Button>
            <Button size='sm' variant='primary' icon='plus' onClick={() => setShowCreate(true)}>ثبت دستی</Button>
          </div>

          {/* Table — قانونِ کاربر (۲۰۲۶-۰۷-۲۶): همه‌ی ستون‌ها باید در یک نگاه دیده بشن؛
              overflowX تضمین می‌کنه هیچ ستونی هیچ‌وقت کاملاً غیرِقابلِ‌دسترسی نشه، و
              کلاسِ table-compact پدینگ/فونتِ کوچیک‌تری داره تا رویِ صفحه‌نمایش‌هایِ معمولی
              همه‌ی ستون‌ها بدونِ اسکرول جا بشن. */}
          <div style={{ flex:1, minHeight:340, overflowY:'auto', overflowX:'auto' }}>
            {loading && <div style={{ padding:20, textAlign:'center', color:'var(--text-muted)', fontSize:12 }}>در حال بارگذاری...</div>}
            {!loading && leads.length === 0 && (
              <div style={{ padding:20, textAlign:'center', color:'var(--text-muted)', fontSize:12, display:'flex', flexDirection:'column', alignItems:'center', gap:10 }}>
                <div>لیدی پیدا نشد</div>
                <button onClick={async () => {
                  const tk = localStorage.getItem(window.TOKEN_KEY);
                  const r = await fetch('/api/pool/leads/export-segmented', { headers: { Authorization: `Bearer ${tk}` } });
                  if (!r.ok) return;
                  const blob = await r.blob();
                  const url = URL.createObjectURL(blob);
                  const a = document.createElement('a');
                  a.href = url;
                  a.download = `segmented_leads_${new Date().toISOString().slice(0,10)}.xlsx`;
                  a.click();
                  URL.revokeObjectURL(url);
                }} style={{
                  padding:'6px 14px', borderRadius:7, fontSize:11, cursor:'pointer',
                  border:'1px solid rgba(99,102,241,0.35)', background:'rgba(99,102,241,0.1)', color:'#818CF8',
                }}>📥 دانلود اکسل سگمنت‌بندی‌شده همه لیدها</button>
              </div>
            )}
            {/* قانونِ کاربر (۲۰۲۶-۰۸-۰۸): بوردِ کانبان فقط وقتی معنی داره که رویِ یه فروشنده‌یِ
                مشخص فیلتر شده باشیم (برچسب‌هایِ سفارشیِ ستون‌ها مالِ یه فروشنده‌ی خاصن) — رویِ
                «همه فروشندگان» باید جدولِ معمولی دیده بشه، نه کانبان. */}
            {!loading && leads.length > 0 && (sideFilter.unit === 'sales' && sideFilter.seller_id) && (
              // قانونِ کاربر (۲۰۲۶-۰۸-۰۳): statCounts (آمارِ کلیِ poolStats) فقط وقتی معتبره که
              // پیلِ «همه» انتخاب شده — وگرنه هدرها عددِ کلی نشون می‌دن درحالی‌که لیستِ زیرش
              // فقط همون یه وضعیتِ فیلترشده‌ست (خالی به‌نظر می‌رسید چون هدر با بدنه نمی‌خوند).
              <KanbanBoard leads={leads} onSelect={setSelected} statCounts={statusPill === 'all' ? poolStats : null} labelOverrides={sellerLabelOverrides} />
            )}
            {!loading && leads.length > 0 && !(sideFilter.unit === 'sales' && sideFilter.seller_id) && (
              <table className='table table-compact'>
                <thead>
                  <tr>
                    <th style={{ width:30 }}>
                      <input type='checkbox' checked={leads.length>0 && checkedIds.size===leads.length} onChange={toggleCheckedAll} style={{ cursor:'pointer' }} />
                    </th>
                    <th>اسم</th>
                    {convMode ? (
                      <>
                        <th>آخرین پیام</th>
                        <th>تعداد پیام</th>
                        <th>آخرین فعالیت</th>
                      </>
                    ) : (
                      <>
                        <th>شماره</th>
                        <th>پلتفرم</th>
                        <th>سیستم</th>
                        <th>بودجه</th>
                        <th>سن</th>
                        <th>لید</th>
                        <th>نوع محصول</th>
                        <th>اطلاعاتِ مکالمه</th>
                        <th>امتیاز</th>
                        <th>تماس</th>
                        <th>آخرین نتیجه</th>
                      </>
                    )}
                    <th>وضعیت</th>
                    <th style={{ width:36 }}></th>
                  </tr>
                </thead>
                <tbody>
                  {leads.map(lead => {
                    let lastOutcome = null;
                    try { const d = JSON.parse(lead.last_call_json||'null'); if (d?.outcome) lastOutcome = d.outcome; } catch {}
                    const leadTags = (lead.tags||'').split(',').filter(Boolean);
                    const silenceHours = lead.conv_updated_at
                      ? Math.round((Date.now() - new Date(lead.conv_updated_at).getTime()) / 3600000)
                      : null;
                    const silenceLabel = silenceHours == null ? '—'
                      : silenceHours < 1 ? 'همین الان'
                      : silenceHours < 24 ? `${fa(silenceHours)} ساعت پیش`
                      : `${fa(Math.round(silenceHours/24))} روز پیش`;
                    const silenceColor = silenceHours == null ? '#475569'
                      : silenceHours < 1 ? '#34D399'
                      : silenceHours < 24 ? '#FBBF24'
                      : silenceHours < 72 ? '#F97316' : '#F87171';
                    return (
                      <tr key={lead.id} onClick={() => setSelected(lead)} style={{ cursor:'pointer' }}>
                        <td onClick={e => e.stopPropagation()}>
                          <input type='checkbox' checked={checkedIds.has(lead.id)} onChange={() => toggleChecked(lead.id)} style={{ cursor:'pointer' }} />
                        </td>
                        <td>
                          <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                            <div style={{ width:30, height:30, borderRadius:'50%', background:'#4f46e522', display:'flex', alignItems:'center', justifyContent:'center', fontSize:13, fontWeight:700, color:'#a78bfa', flexShrink:0 }}>
                              {(lead.full_name||lead.username||'?')[0]}
                            </div>
                            <div>
                              <div style={{ fontSize:13, fontWeight:500 }}>{lead.full_name||lead.username||'ناشناس'}</div>
                              {lead.username && lead.full_name && <div style={{ fontSize:12, color:'var(--text-muted)' }}>@{lead.username}</div>}
                            </div>
                          </div>
                        </td>
                        {convMode ? (
                          <>
                            <td style={{ fontSize:13, color:'var(--text-muted)', maxWidth:280 }}>
                              <div style={{ overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                                {lead.conv_last_msg || '—'}
                              </div>
                            </td>
                            <td style={{ fontSize:13, fontFamily:'JetBrains Mono', color:'#818CF8' }}>
                              {fa(lead.conv_msg_count||0)}
                            </td>
                            <td>
                              <span style={{ fontSize:13, fontWeight:600, color:silenceColor }}>{silenceLabel}</span>
                            </td>
                          </>
                        ) : (
                          <>
                            <td style={{ fontSize:13, fontFamily:'JetBrains Mono', color:'var(--text-muted)' }}>{lead.phone||'—'}</td>
                            <td>
                              <span style={{ fontSize:13, padding:'2px 8px', borderRadius:6,
                                background: lead.platform?.startsWith('telegram') ? 'rgba(41,182,246,0.15)' : lead.platform==='novinhub' ? 'rgba(52,211,153,0.15)' : 'rgba(99,102,241,0.15)',
                                color: lead.platform?.startsWith('telegram') ? '#29B6F6' : lead.platform==='novinhub' ? '#34D399' : '#818CF8' }}>
                                {lead.platform?.startsWith('telegram') ? 'تلگرام' : lead.platform?.startsWith('bale') ? 'بله' : lead.platform==='novinhub' ? 'نوین‌هاب' : (lead.platform||'—')}
                              </span>
                            </td>
                            <td style={{ fontSize:13, color:'var(--text-muted)' }}>
                              {/* قانونِ کاربر ۲۰۲۶-۰۷-۲۶: اگه novinhub_has_system خالی بود، فیلدِ
                                  «سیستم/دستگاه/لپ»یِ جمع‌شده از خودِ مکالمه (هر اسکریپتی) رو نشون بده */}
                              {lead.novinhub_has_system!=null && lead.novinhub_has_system!==''
                                ? (lead.novinhub_has_system>0 ? 'دارد' : 'موبایل')
                                : (lead.chat_system || '—')}
                            </td>
                            <td style={{ fontSize:13, color:'var(--text-muted)' }}>{lead.novinhub_budget ? `${fa(lead.novinhub_budget)} میلیون` : '—'}</td>
                            <td style={{ fontSize:13, color:'var(--text-muted)' }}>
                              {lead.novinhub_age ? fa(lead.novinhub_age) : (lead.chat_age || '—')}
                            </td>
                            <td>
                              {lead.novinhub_segment ? (() => {
                                const segColor = { 'گرم':'#F87171', 'ولرم':'#FBBF24', 'سرد':'#60A5FA' }[lead.novinhub_segment] || '#818CF8';
                                return (
                                  <span style={{ fontSize:13, padding:'2px 8px', borderRadius:6, background:segColor+'22', color:segColor }}>
                                    {lead.novinhub_segment}
                                  </span>
                                );
                              })() : <span style={{ color:'#374151', fontSize:13 }}>—</span>}
                            </td>
                            <td style={{ fontSize:13, color:'var(--text-muted)' }}>{lead.novinhub_product_name || '—'}</td>
                            <td style={{ fontSize:12, color:'var(--text-muted)', maxWidth:220 }}>
                              {/* قانونِ کاربر (۲۰۲۶-۰۷-۲۹، به‌روزشده ۲۰۲۶-۰۸-۰۳): لیدهایی که خودِ فروش‌یار دستی ثبت کرده
                                  (created_via='seller_manual') باید برچسبِ «فروش‌یار: اسم» رو کنارِ همینجا
                                  ببینن — اسمِ همون فروشنده‌ای که *اولین‌بار* ثبتش کرده (created_by_seller_id،
                                  از lead_history که هیچ‌وقت پاک نمی‌شه)، نه seller_id فعلی که با برگشت‌به‌مارکت
                                  خالی می‌شه. اگه به هر دلیلی created_by_seller_id نبود، seller_id فعلی فال‌بکه. */}
                              {lead.platform==='manual' && lead.created_via==='seller_manual' && (
                                <div style={{ marginBottom:3 }}>
                                  <span style={{ fontSize:12, padding:'1px 6px', borderRadius:5, background:'rgba(52,211,153,0.15)', color:'#34D399', fontWeight:700 }}>
                                    🧑‍💼 فروش‌یار{(lead.created_by_seller_id || lead.seller_id) ? `: ${(sellers.find(s=>s.id===(lead.created_by_seller_id || lead.seller_id))||{}).name || ''}` : ''}
                                  </span>
                                </div>
                              )}
                              {/* قانونِ کاربر ۲۰۲۶-۰۷-۲۶: خلاصه‌ی داده‌هایی که ربات از مکالمه (بله/تلگرام/...)
                                  جمع کرده — قبلاً فقط توی جزئیاتِ لید دیده می‌شد. */}
                              {(lead.collected_preview || []).length === 0
                                ? <span style={{ color:'#374151' }}>—</span>
                                : (lead.collected_preview || []).map((c, i) => (
                                    <div key={i} style={{ overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                                      <span style={{ color:'#818CF8' }}>{c.field}:</span> {c.value}
                                    </div>
                                  ))
                              }
                            </td>
                            <td>
                              <span style={{ fontSize:13, fontFamily:'JetBrains Mono', fontWeight:700,
                                color: (lead.score||0)>=7?'#34D399':(lead.score||0)>=4?'#fbbf24':'#94a3b8' }}>
                                {lead.score||0}
                              </span>
                            </td>
                            <td onClick={e => { e.stopPropagation(); setQuickCallLead(lead); }} title='کلیک برای ثبت تماس'>
                              {(lead.call_count||0) > 0 ? (
                                <span style={{ fontSize:13, padding:'3px 9px', borderRadius:6, background:'rgba(52,211,153,0.15)', color:'#34D399', cursor:'pointer', display:'inline-flex', alignItems:'center', gap:4 }}>
                                  📞 {fa(lead.call_count)}
                                </span>
                              ) : (
                                <span style={{ fontSize:13, padding:'3px 9px', borderRadius:6, background:'rgba(99,102,241,0.12)', color:'#818CF8', cursor:'pointer', border:'1px dashed rgba(99,102,241,0.3)' }}>
                                  + ثبت
                                </span>
                              )}
                            </td>
                            <td>
                              {lastOutcome ? (
                                <span style={{ fontSize:13, padding:'2px 8px', borderRadius:6, background:(POOL_OUTCOME_COLOR[lastOutcome]||'#6B7280')+'18', color:POOL_OUTCOME_COLOR[lastOutcome]||'#6B7280' }}>
                                  {POOL_OUTCOME_ICON[lastOutcome]} {POOL_OUTCOME_LABEL[lastOutcome]||lastOutcome}
                                </span>
                              ) : <span style={{ color:'#374151', fontSize:13 }}>—</span>}
                            </td>
                          </>
                        )}
                        <td onClick={e => e.stopPropagation()}>
                          {(() => { const rs = poolRowStatus(lead); return (
                            <span onClick={() => setStatusTimelineLead(lead)} title='مشاهده‌ی جزئیاتِ وضعیت' style={{ cursor:'pointer', fontSize:13, padding:'3px 8px', borderRadius:6, background:rs.color+'22', color:rs.color }}>
                              {rs.label}
                            </span>
                          ); })()}
                        </td>
                        <td onClick={e => e.stopPropagation()}>
                          <button className='icon-btn' title='ویرایش' style={{ width:28, height:28 }} onClick={() => setEditLead(lead)}>
                            <Icon name='edit' size={13} />
                          </button>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            )}
          </div>

          {/* قانونِ کاربر (۲۰۲۶-۰۸-۰۳): صفحه‌بندی حذف شد — همه‌ی لیدها یک‌جا لود می‌شن. */}
        </div>
      </div>

      {/* ─── ConvPopup ─── */}
      {selected && <ConvPopup lead={selected} token={token} onClose={() => setSelected(null)} />}

      {/* ─── StatusTimelineModal ─── */}
      {statusTimelineLead && <StatusTimelineModal lead={statusTimelineLead} token={token} onClose={() => setStatusTimelineLead(null)} />}

      {/* ─── LeadDetailModal (ویرایش) ─── */}
      {editLead && <LeadDetailModal lead={editLead} onClose={() => setEditLead(null)} onRefresh={() => { loadLeads(); onRefresh && onRefresh(); }} />}

      {/* ─── CallModal ─── */}
      {quickCallLead && React.createElement(CallModal, {
        lead: quickCallLead,
        token: token,
        onClose: () => setQuickCallLead(null),
        onDone: () => { setQuickCallLead(null); loadLeads(); onRefresh && onRefresh(); },
      })}

      {/* ─── Modal: ثبت دستی ─── */}
      {showCreate && ReactDOM.createPortal(
        <div onClick={e => { if (e.target === e.currentTarget) setShowCreate(false); }} style={{
          position:'fixed', inset:0, background:'rgba(0,0,0,0.75)', zIndex:9000,
          display:'flex', alignItems:'center', justifyContent:'center',
        }}>
          <div style={{ background:'#111827', border:'1px solid rgba(255,255,255,0.12)', borderRadius:14, padding:'20px 24px 24px', width:540, maxHeight:'85vh', overflowY:'auto', position:'relative', boxShadow:'0 25px 60px rgba(0,0,0,0.6)' }}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:16 }}>
              <div style={{ fontSize:14, fontWeight:700, color:'#e2e8f0' }}>➕ ثبت دستی لید جدید</div>
              <button onClick={() => setShowCreate(false)} style={{ background:'transparent', border:'none', color:'#64748b', fontSize:20, cursor:'pointer', lineHeight:1, padding:'0 4px' }}>✕</button>
            </div>
            {React.createElement(CreateTab, { api, headers: h, toast, fa, hideTitle: true, onCreated: () => { loadLeads(); onRefresh && onRefresh(); },
              onOpenExisting: (id, name) => { setShowCreate(false); setEditLead({ id, full_name: name }); } })}
          </div>
        </div>,
        document.body
      )}

      {/* ─── Modal: ایمپورت ─── */}
      {showImport && ReactDOM.createPortal(
        <div onClick={e => { if (e.target === e.currentTarget) setShowImport(false); }} style={{
          position:'fixed', inset:0, background:'rgba(0,0,0,0.75)', zIndex:9000,
          display:'flex', alignItems:'center', justifyContent:'center',
        }}>
          <div style={{ background:'#111827', border:'1px solid rgba(255,255,255,0.12)', borderRadius:14, padding:'20px 24px 24px', width:680, maxHeight:'85vh', overflowY:'auto', position:'relative', boxShadow:'0 25px 60px rgba(0,0,0,0.6)' }}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:16 }}>
              <div style={{ fontSize:14, fontWeight:700, color:'#e2e8f0' }}>📥 ایمپورت گروهی لیدها</div>
              <button onClick={() => setShowImport(false)} style={{ background:'transparent', border:'none', color:'#64748b', fontSize:20, cursor:'pointer', lineHeight:1, padding:'0 4px' }}>✕</button>
            </div>
            {React.createElement(LeadImportTab, { hideTitle: true, onDone: () => { setShowImport(false); loadLeads(); onRefresh && onRefresh(); } })}
          </div>
        </div>,
        document.body
      )}

      {/* ─── Modal: ایمپورت اکسل نوین‌هاب ─── */}
      {showNovinHub && ReactDOM.createPortal(
        <div onClick={e => { if (e.target === e.currentTarget) setShowNovinHub(false); }} style={{
          position:'fixed', inset:0, background:'rgba(0,0,0,0.75)', zIndex:9000,
          display:'flex', alignItems:'center', justifyContent:'center',
        }}>
          <div style={{ background:'#111827', border:'1px solid rgba(255,255,255,0.12)', borderRadius:14, padding:'20px 24px 24px', width:820, maxHeight:'85vh', overflowY:'auto', position:'relative', boxShadow:'0 25px 60px rgba(0,0,0,0.6)' }}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:16 }}>
              <div style={{ fontSize:14, fontWeight:700, color:'#e2e8f0' }}>📊 ایمپورت اکسل نوین‌هاب</div>
              <button onClick={() => setShowNovinHub(false)} style={{ background:'transparent', border:'none', color:'#64748b', fontSize:20, cursor:'pointer', lineHeight:1, padding:'0 4px' }}>✕</button>
            </div>
            {React.createElement(NovinHubImportTab, { hideTitle: true, onDone: () => { loadLeads(); onRefresh && onRefresh(); } })}
          </div>
        </div>,
        document.body
      )}

      {/* ─── Modal: خروجیِ اکسل — انتخابِ شیت‌ها + بازه‌ی تاریخ قبل از دانلود ─── */}
      {showExportModal && ReactDOM.createPortal(
        <div onClick={e => { if (e.target === e.currentTarget) setShowExportModal(false); }} style={{
          position:'fixed', inset:0, background:'rgba(0,0,0,0.75)', zIndex:9000,
          display:'flex', alignItems:'center', justifyContent:'center',
        }}>
          <div style={{ background:'#111827', border:'1px solid rgba(255,255,255,0.12)', borderRadius:14, padding:'20px 24px 24px', width:420, maxHeight:'85vh', overflowY:'auto', position:'relative', boxShadow:'0 25px 60px rgba(0,0,0,0.6)' }}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:16 }}>
              <div style={{ fontSize:14, fontWeight:700, color:'#e2e8f0' }}>📥 خروجیِ اکسل</div>
              <button onClick={() => setShowExportModal(false)} style={{ background:'transparent', border:'none', color:'#64748b', fontSize:20, cursor:'pointer', lineHeight:1, padding:'0 4px' }}>✕</button>
            </div>

            <div style={{ fontSize:11, color:'var(--text-muted)', marginBottom:8 }}>فیلترها</div>
            <div style={{ display:'flex', flexDirection:'column', gap:8, marginBottom:16 }}>
              <input value={exportSearch} onChange={e => setExportSearch(e.target.value)}
                placeholder='🔍  جستجو نام، شماره...' style={{ ...selStyle, width:'100%' }} />
              <select style={selStyle} value={exportPlatform} onChange={e => setExportPlatform(e.target.value)}>
                <option value=''>همه پلتفرم‌ها</option>
                <option value='telegram'>تلگرام</option>
                <option value='bale'>بله</option>
                <option value='rubika'>روبیکا</option>
                <option value='manual'>دستی</option>
                <option value='novinhub'>نوین‌هاب</option>
              </select>
              <select style={selStyle} value={exportUnit} onChange={e => setExportUnit(e.target.value)}>
                <option value=''>همه یونیت‌ها</option>
                <option value='market_only'>توزیع‌نشده</option>
                <option value='market_incomplete'>اطلاعاتِ ناقص</option>
                <option value='sales'>دست فروشنده</option>
              </select>
              <select style={selStyle} value={exportSellerId} onChange={e => setExportSellerId(e.target.value)}>
                <option value=''>همه فروشندگان</option>
                {sellers.map(s => <option key={s.id} value={s.id}>{s.name}</option>)}
              </select>
              <select style={selStyle} value={exportSegmentId} onChange={e => setExportSegmentId(e.target.value)}>
                <option value=''>همه سگمنت‌ها</option>
                {segments.map(s => <option key={s.id} value={s.id}>{s.icon} {s.name}</option>)}
              </select>
            </div>

            <div style={{ fontSize:11, color:'var(--text-muted)', marginBottom:8 }}>شیت‌هایی که می‌خواید توی فایل باشن</div>
            <div style={{ display:'flex', flexDirection:'column', gap:6, marginBottom:16 }}>
              {[
                { key:'new',          label:'✨ لید جدید' },
                { key:'re_request',   label:'🔁 درخواستِ مجدد' },
                { key:'follow_up',    label:'🔄 پیگیری' },
                { key:'interested',   label:'🧡 علاقه‌مند' },
                { key:'scheduled',    label:'📌 ست شده' },
                { key:'consultation', label:'🗣 مشاوره' },
                { key:'buyer',        label:'💰 خریدار' },
                { key:'lost',         label:'❌ از دست رفته' },
                { key:'cancelled,bad_number', label:'🪦 قبرستان' },
                { key:'duplicate',    label:'📑 تکراری' },
              ].map(s => (
                <label key={s.key} style={{ display:'flex', alignItems:'center', gap:8, fontSize:12.5, color:'#e2e8f0', cursor:'pointer' }}>
                  <input type='checkbox' checked={exportSheets.has(s.key)}
                    onChange={e => setExportSheets(prev => { const n = new Set(prev); e.target.checked ? n.add(s.key) : n.delete(s.key); return n; })}/>
                  {s.label}
                </label>
              ))}
              <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:12.5, color:'#a78bfa', cursor:'pointer', paddingTop:6, borderTop:'1px solid rgba(255,255,255,0.08)', marginTop:4 }}>
                <input type='checkbox' checked={exportIncludeAssigned} onChange={e => setExportIncludeAssigned(e.target.checked)} />
                📤 ارسالی به فروش‌یار (بر اساسِ تاریخِ تخصیص، نه statusِ فعلی)
              </label>
            </div>

            <div style={{ fontSize:11, color:'var(--text-muted)', marginBottom:8 }}>بازه‌ی تاریخِ ثبت (اختیاری — خالی یعنی همه)</div>
            <div style={{ display:'flex', flexDirection:'column', gap:8, marginBottom:20 }}>
              <ShamsiDateFilterMini value={exportDateFrom} onChange={setExportDateFrom} placeholder='از تاریخ: 1405/04/01' />
              <ShamsiDateFilterMini value={exportDateTo} onChange={setExportDateTo} placeholder='تا تاریخ: 1405/04/29' />
              <button onClick={() => { const t = todayLocalStr(); setExportDateFrom(t); setExportDateTo(t); }}
                style={{ ...selStyle, cursor:'pointer', textAlign:'center', fontWeight:600 }}>
                📅 فقط امروز
              </button>
              {(exportDateFrom || exportDateTo) && (
                <button onClick={() => { setExportDateFrom(''); setExportDateTo(''); }}
                  style={{ background:'transparent', border:'none', color:'var(--text-muted)', fontSize:11, cursor:'pointer', padding:0, textAlign:'right' }}>
                  پاک‌کردنِ بازه
                </button>
              )}
            </div>

            <Button kind='primary' disabled={exportingFile || (exportSheets.size===0 && !exportIncludeAssigned)} onClick={async () => {
              setExportingFile(true);
              try {
                const body = {
                  unit: exportUnit || 'pool',
                  platform: exportPlatform || undefined,
                  seller_id: exportSellerId || undefined,
                  segment_id: exportSegmentId || undefined,
                  date_from: exportDateFrom || undefined,
                  date_to: exportDateTo || undefined,
                  search: exportSearch || undefined,
                  include_assigned_sheet: exportIncludeAssigned || undefined,
                  sort: 'created_desc',
                  sheets: [...exportSheets],
                };
                const res = await fetch('/api/pool/leads/export-filtered', { method:'POST', headers: h, body: JSON.stringify(body) });
                if (!res.ok) { toast.error('خطا در گرفتنِ خروجی'); return; }
                const blob = await res.blob();
                const a = document.createElement('a');
                a.href = URL.createObjectURL(blob);
                a.download = `leads_filtered_${todayLocalStr()}.xlsx`;
                a.click();
                setShowExportModal(false);
              } catch { toast.error('خطای شبکه'); }
              finally { setExportingFile(false); }
            }} style={{ width:'100%' }}>
              {exportingFile ? '⏳ در حال آماده‌سازی...' : '⬇️ دریافتِ فایلِ اکسل'}
            </Button>
          </div>
        </div>,
        document.body
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════
//  TAB: سگمنت‌ها
// ═══════════════════════════════════════════════════════════
const SegmentsTab = ({ onApplyRules }) => {
  const { Icon, Button, Modal, useToast } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const { useState, useEffect } = React;
  const toast = useToast();
  const token = localStorage.getItem(window.TOKEN_KEY);
  const h = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };
  const api = (url, opts = {}) => fetch(url, { headers: h, ...opts }).then(r => r.json());

  const EMPTY_FORM = { name:'', description:'', color:'#6366F1', icon:'🎯', conditions:[], actions:[], is_active:1 };
  const [segments, setSegments] = useState([]);
  const [editing, setEditing] = useState(null);
  const [form, setForm] = useState(EMPTY_FORM);
  const [showForm, setShowForm] = useState(false);
  const [segLeads, setSegLeads] = useState(null);
  const [fieldGroups, setFieldGroups] = useState([]);
  const [campaigns, setCampaigns] = useState([]);
  const [segProducts, setSegProducts] = useState([]);
  const [followupRules, setFollowupRules] = useState([]);
  const [refreshing, setRefreshing] = useState({});
  const [batchModal, setBatchModal] = useState(null); // { seg } | null
  const [batchAction, setBatchAction] = useState('campaign');
  const [batchCampaign, setBatchCampaign] = useState('');
  const [batchRule, setBatchRule] = useState('');
  const [batchLoading, setBatchLoading] = useState(false);
  const [availTags, setAvailTags] = useState([]);
  const [segMode, setSegMode] = useState('simple');
  const [condTemplates, setCondTemplates] = useState([]);
  const [tplSearch, setTplSearch] = useState('');
  const [openCats, setOpenCats] = useState({});
  const [newTplLabel, setNewTplLabel] = useState('');
  const [newTplField, setNewTplField] = useState('');
  const [newTplOp, setNewTplOp] = useState('eq');
  const [newTplVal, setNewTplVal] = useState('');
  const [newTplSaving, setNewTplSaving] = useState(false);
  const [collField, setCollField] = useState('');
  const [collOp, setCollOp] = useState('eq');
  const [collVal, setCollVal] = useState('');
  const [panelSelCamp, setPanelSelCamp] = useState('');
  const [panelSelScript, setPanelSelScript] = useState('');
  const [showAddTpl, setShowAddTpl] = useState(false);
  const [addTplField, setAddTplField] = useState('status');
  const [addTplOp, setAddTplOp] = useState('eq');
  const [addTplVal, setAddTplVal] = useState('');
  const [addTplLabel, setAddTplLabel] = useState('');

  const load = () => api('/api/pool/segments').then(d => { if (d.success) setSegments(d.data.segments); });
  useEffect(() => {
    load();
    api('/api/pool/segments/fields').then(d => { if (d.success) setFieldGroups(d.data.groups); });
    api('/api/campaigns/campaigns').then(d => { const list = Array.isArray(d) ? d : (d.data?.campaigns || d.campaigns || []); setCampaigns(list); }).catch(() => {});
    api('/api/market/products').then(d => { if (d.success) setSegProducts(d.data.products || []); }).catch(() => {});
    api('/api/followup/rules').then(d => { setFollowupRules(Array.isArray(d.data) ? d.data : (Array.isArray(d) ? d : [])); }).catch(() => {});
    api('/api/pool/tags/all').then(d => { if (d.success) setAvailTags((d.data||[]).map(t=>t.tag)); }).catch(() => {});
    api('/api/pool/segment-templates').then(d => { if (d.success) setCondTemplates(d.data.templates); }).catch(() => {});
  }, []);

  const refreshSeg = async (seg) => {
    setRefreshing(p => ({ ...p, [seg.id]: true }));
    const r = await api(`/api/pool/segments/${seg.id}/refresh`, { method:'POST' });
    setRefreshing(p => ({ ...p, [seg.id]: false }));
    if (r.success) {
      toast.success(`✅ ${r.data.entered} ورود، ${r.data.exited} خروج — ${r.data.member_count} عضو`);
      setSegments(prev => prev.map(s => s.id === seg.id ? { ...s, member_count: r.data.member_count } : s));
    } else toast.error('خطا');
  };

  const exportCsv = async (seg) => {
    const token = localStorage.getItem(window.TOKEN_KEY);
    const res = await fetch(`/api/pool/segments/${seg.id}/leads/export`, { headers: { Authorization: `Bearer ${token}` } });
    if (!res.ok) return toast.error('خطا در دریافت فایل');
    const blob = await res.blob();
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `segment_${seg.name}_${new Date().toISOString().slice(0,10)}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  };

  const save = async () => {
    if (!form.name.trim()) return toast.error('نام الزامی است');
    const url = editing ? `/api/pool/segments/${editing}` : '/api/pool/segments';
    const method = editing ? 'PUT' : 'POST';
    const res = await api(url, { method, body: JSON.stringify(form) });
    if (res.success) { toast.success('ذخیره شد'); load(); setShowForm(false); setEditing(null); setForm(EMPTY_FORM); }
    else toast.error(res.message || 'خطا');
  };

  const del = async (id) => {
    if (!confirm('حذف شود؟')) return;
    await api(`/api/pool/segments/${id}`, { method:'DELETE' });
    load();
  };

  const viewLeads = async (seg) => {
    const res = await api(`/api/pool/segments/${seg.id}/leads`);
    if (res.success) setSegLeads({ seg, leads: res.data.leads, total: res.data.total });
  };

  const openBatch = (seg) => {
    setBatchModal({ seg });
    setBatchAction('campaign');
    setBatchCampaign(campaigns[0]?.id || '');
    setBatchRule(followupRules[0]?.id || '');
  };

  const doBatchAction = async () => {
    if (!batchModal) return;
    setBatchLoading(true);
    const body = { action: batchAction };
    if (batchAction === 'campaign') body.campaign_id = batchCampaign;
    if (batchAction === 'followup') body.rule_id = batchRule;
    const r = await api(`/api/pool/segments/${batchModal.seg.id}/batch-action`, {
      method: 'POST', body: JSON.stringify(body),
    });
    setBatchLoading(false);
    if (r.success) {
      const d = r.data;
      if (batchAction === 'campaign') toast.success(`✅ ${d.added} لید به کمپین اضافه شد`);
      else if (batchAction === 'followup') toast.success(`✅ ${d.triggered} فالوآپ اجرا شد`);
      else toast.success(`✅ توزیع خودکار انجام شد`);
      setBatchModal(null);
    } else toast.error(r.message || r.error || 'خطا');
  };

  const allFields = fieldGroups.flatMap(g => g.fields);
  const fieldDef = (v) => allFields.find(f => f.v === v);

  const condToLabel = (cond) => {
    if (cond._label) return cond._label;
    const SFA = { new:'جدید', follow_up:'پیگیری', interested:'علاقمند', scheduled:'وقت گرفته', consultation:'مشاوره شده', buyer:'خریدار', lost:'از دست رفته', cancelled:'کنسل', bad_number:'شماره اشتباه' };
    const OFA = { eq:'=', neq:'≠', gte:'≥', lte:'≤', gt:'>', lt:'<', contains:'شامل', ncontains:'شامل نیست', empty:'خالی است', nempty:'پر است', has:'دارد', in:'یکی از' };
    const fl = cond.field?.startsWith('collected.') ? '«'+cond.field.replace('collected.','')+'»' : (fieldDef(cond.field)?.label || cond.field);
    if (['empty','nempty'].includes(cond.op)) return `${fl} ${OFA[cond.op]}`;
    return `${fl} ${OFA[cond.op]||cond.op} ${SFA[cond.value]||cond.value}`;
  };

  const addFromTemplate = (tpl) => {
    const newConds = tpl.conditions.map((c, i) => ({
      ...c, logic:'AND',
      _label: tpl.conditions.length === 1 ? tpl.label : undefined,
    }));
    for (const nc of newConds) {
      const fl = fieldDef(nc.field)?.label || nc.field;
      // تکراری
      if (form.conditions.some(ec => ec.field===nc.field && ec.op===nc.op && ec.value===nc.value)) {
        return toast.error('این شرط قبلاً اضافه شده');
      }
      // متناقض: eq با مقدار دیگر روی همان فیلد
      if (nc.op==='eq' && form.conditions.some(ec => ec.field===nc.field && ec.op==='eq' && ec.value!==nc.value)) {
        return toast.error(`شرط متناقض: «${fl}» قبلاً با مقدار دیگری تنظیم شده`);
      }
      // متناقض: empty vs nempty
      if (['empty','nempty'].includes(nc.op)) {
        const opp = nc.op==='empty' ? 'nempty' : 'empty';
        if (form.conditions.some(ec => ec.field===nc.field && ec.op===opp)) {
          return toast.error(`شرط متناقض: «${fl}» قبلاً با شرط مخالف تنظیم شده`);
        }
      }
      // متناقض عددی: gte/gt با lte/lt که بازه منطقی نداره
      if (['gte','gt'].includes(nc.op) && nc.value) {
        const conflict = form.conditions.find(ec => ec.field===nc.field && ['lte','lt'].includes(ec.op) && ec.value && parseFloat(ec.value) < parseFloat(nc.value));
        if (conflict) return toast.error(`شرط متناقض: حد پایین از حد بالای موجود بیشتر است`);
      }
      if (['lte','lt'].includes(nc.op) && nc.value) {
        const conflict = form.conditions.find(ec => ec.field===nc.field && ['gte','gt'].includes(ec.op) && ec.value && parseFloat(ec.value) > parseFloat(nc.value));
        if (conflict) return toast.error(`شرط متناقض: حد بالا از حد پایین موجود کمتر است`);
      }
    }
    setForm(f => ({ ...f, conditions: [...f.conditions, ...newConds] }));
  };

  const delSegTemplate = async (id) => {
    const res = await api(`/api/pool/segment-templates/${id}`, { method:'DELETE' });
    if (res.success) setCondTemplates(p => p.filter(t => t.id !== id));
    else toast.error(res.message || 'خطا');
  };

  const saveSegTemplate = async () => {
    if (!newTplLabel.trim()) return toast.error('متن جمله الزامی است');
    if (!newTplField.trim()) return toast.error('نام فیلد الزامی است');
    setNewTplSaving(true);
    const conditions = [{ field:'collected.'+newTplField.trim(), op:newTplOp, value:newTplVal, logic:'AND' }];
    const res = await api('/api/pool/segment-templates', { method:'POST', body:JSON.stringify({ label:newTplLabel, category:'سفارشی', conditions }) });
    setNewTplSaving(false);
    if (res.success) {
      api('/api/pool/segment-templates').then(d => { if (d.success) setCondTemplates(d.data.templates); });
      setNewTplLabel(''); setNewTplField(''); setNewTplOp('eq'); setNewTplVal('');
      toast.success('الگو ذخیره شد');
    } else toast.error(res.message || 'خطا');
  };

  const getSegTplOps = (field) => {
    const t = fieldDef(field)?.type || 'text';
    if (t==='enum')   return [['eq','باشد'],['neq','نباشد'],['in','یکی از']];
    if (t==='number') return [['gte','بیشتر از'],['lte','کمتر از'],['eq','برابر'],['empty','پر نشده'],['nempty','پر شده']];
    if (t==='tag')    return [['has','داشته باشد'],['ncontains','نداشته باشد']];
    return [['eq','برابر'],['contains','شامل'],['nempty','پر شده'],['empty','خالی است']];
  };

  const autoSegLabel = (field, op, value) => {
    const SFA = { new:'جدید', follow_up:'پیگیری', interested:'علاقمند', scheduled:'وقت گرفته', consultation:'مشاوره شده', buyer:'خریدار', lost:'از دست رفته', cancelled:'کنسل', bad_number:'شماره اشتباه' };
    const fl = field.startsWith('collected.') ? '«'+field.replace('collected.','')+'»' : (fieldDef(field)?.label || field);
    const vFa = SFA[value] || value;
    if (field==='status') {
      if (op==='eq')  return `وضعیت «${vFa}» است`;
      if (op==='neq') return `وضعیت «${vFa}» نیست`;
      if (op==='in')  return `وضعیت یکی از: ${value}`;
    }
    if (field==='call_count') {
      if (op==='eq' && value==='0') return 'هرگز تماس نگرفته';
      if (op==='gte') return `بیش از ${value} بار تماس گرفته`;
      if (op==='lte') return `کمتر از ${value} بار تماس گرفته`;
    }
    if (field==='no_answer_count' && op==='gte') return `${value} بار یا بیشتر جواب نداده`;
    if (field==='last_call_days') {
      if (op==='gte') return `بیش از ${value} روز تماس نگرفته`;
      if (op==='lte') return `کمتر از ${value} روز از آخرین تماس گذشته`;
    }
    if (field==='lead_age_days') {
      if (op==='gte') return `بیش از ${value} روز پیش وارد شده`;
      if (op==='lte') return `کمتر از ${value} روز پیش وارد شده`;
    }
    if (field==='days_since_update'             && op==='gte') return `بیش از ${value} روز بی‌تحرک است`;
    if (field==='days_since_last_status_change' && op==='gte') return `بیش از ${value} روز وضعیتش تغییر نکرده`;
    if (field==='score') {
      if (op==='gte') return `امتیاز بالای ${value} دارد`;
      if (op==='lte') return `امتیاز زیر ${value} دارد`;
      if (op==='eq')  return `امتیاز دقیقاً ${value} دارد`;
    }
    if (field==='sale_amount') {
      if (op==='nempty') return 'خرید ثبت شده دارد';
      if (op==='empty')  return 'خرید ثبت نشده';
      if (op==='gte')    return `مبلغ خرید بالای ${value} تومان`;
    }
    if (field==='free_courses_count') {
      if (op==='gte' && value==='1') return 'دوره رایگان دیده';
      if (op==='eq'  && value==='0') return 'دوره رایگان ندیده';
      if (op==='gte') return `${value} دوره رایگان یا بیشتر دیده`;
    }
    if (field==='platform' && op==='eq') return `از ${value} آمده`;
    if (field==='tag') {
      if (op==='has')       return `تگ «${value}» دارد`;
      if (op==='ncontains') return `تگ «${value}» ندارد`;
    }
    if (field==='unpaid_installments_count'  && op==='gte') return `${value} قسط نپرداخته دارد`;
    if (field==='overdue_installments_count' && op==='gte') return `${value} قسط معوق دارد`;
    const OFA = { eq:'برابر', neq:'برابر نیست با', gte:'بیشتر از', lte:'کمتر از', contains:'شامل', ncontains:'شامل نیست', empty:'خالی است', nempty:'پر است', has:'دارد' };
    if (['empty','nempty'].includes(op)) return `${fl} ${OFA[op]}`;
    return `${fl} ${OFA[op]||op} ${vFa}`;
  };

  const renderCondPanel = () => {
    const sysCats = [...new Set(condTemplates.filter(t=>t.is_system).map(t=>t.category))];
    const customTpls = condTemplates.filter(t=>!t.is_system);
    const collectedFields = fieldGroups[2]?.fields || [];
    const filtered = tplSearch ? condTemplates.filter(t => t.label.includes(tplSearch)) : null;
    const chipSt = { padding:'5px 10px', borderRadius:20, border:'1px solid rgba(99,102,241,0.25)', background:'rgba(99,102,241,0.07)', color:'var(--text)', fontSize:11, cursor:'pointer', textAlign:'right', display:'block', width:'100%', marginBottom:3 };
    return (
      <div style={{ width:300, flexShrink:0, borderLeft:'1px solid var(--border)', paddingLeft:14, display:'flex', flexDirection:'column', gap:0, overflowY:'auto', height:'100%' }}>
        <div style={{ fontSize:12, fontWeight:700, marginBottom:8, paddingBottom:6, borderBottom:'1px solid var(--border)', display:'flex', justifyContent:'space-between', alignItems:'center' }}>
          <span>📚 کتابخانه شرط‌ها</span>
          <button onClick={() => { setShowAddTpl(p=>!p); setAddTplField('status'); setAddTplOp('eq'); setAddTplVal(''); setAddTplLabel(autoSegLabel('status','eq','')); }}
            title='شرط جدید بساز' style={{ background:'rgba(99,102,241,0.15)', border:'1px solid #6366f1', borderRadius:6, color:'#818cf8', fontSize:18, cursor:'pointer', width:28, height:26, lineHeight:'24px', textAlign:'center', padding:0 }}>+</button>
        </div>

        {showAddTpl && (
          <div style={{ marginBottom:10, padding:'10px', border:'1px solid rgba(99,102,241,0.35)', borderRadius:8, background:'rgba(99,102,241,0.05)' }}>
            <div style={{ fontSize:11, fontWeight:600, color:'#818cf8', marginBottom:8 }}>ساخت شرط جدید</div>

            <select value={addTplField} onChange={e => {
              const f = e.target.value;
              const newOp = getSegTplOps(f)[0][0];
              setAddTplField(f); setAddTplOp(newOp); setAddTplVal('');
              setAddTplLabel(autoSegLabel(f, newOp, ''));
            }} style={{ ...selStyle, fontSize:11, marginBottom:4 }}>
              {fieldGroups.map(g => (
                <optgroup key={g.label} label={g.label}>
                  {g.fields.map(f => <option key={f.v} value={f.v}>{f.label}</option>)}
                </optgroup>
              ))}
            </select>

            <select value={addTplOp} onChange={e => {
              setAddTplOp(e.target.value); setAddTplVal('');
              setAddTplLabel(autoSegLabel(addTplField, e.target.value, ''));
            }} style={{ ...selStyle, fontSize:11, marginBottom:4 }}>
              {getSegTplOps(addTplField).map(([v,l]) => <option key={v} value={v}>{l}</option>)}
            </select>

            {!['empty','nempty'].includes(addTplOp) && (() => {
              const fd = fieldDef(addTplField);
              if (fd?.type === 'enum') return (
                <select value={addTplVal} onChange={e => { setAddTplVal(e.target.value); setAddTplLabel(autoSegLabel(addTplField, addTplOp, e.target.value)); }} style={{ ...selStyle, fontSize:11, marginBottom:4 }}>
                  <option value=''>— انتخاب —</option>
                  {(fd.options||[]).map(o => <option key={o} value={o}>{STATUS_FA[o]||o}</option>)}
                </select>
              );
              if (fd?.type === 'tag') return (
                <select value={addTplVal} onChange={e => { setAddTplVal(e.target.value); setAddTplLabel(autoSegLabel(addTplField, addTplOp, e.target.value)); }} style={{ ...selStyle, fontSize:11, marginBottom:4 }}>
                  <option value=''>— انتخاب تگ —</option>
                  {availTags.map(t => <option key={t} value={t}>{t}</option>)}
                </select>
              );
              return (
                <input value={addTplVal} onChange={e => { setAddTplVal(e.target.value); setAddTplLabel(autoSegLabel(addTplField, addTplOp, e.target.value)); }}
                  placeholder='مقدار...' style={{ ...selStyle, fontSize:11, marginBottom:4 }} />
              );
            })()}

            <div style={{ fontSize:10, color:'var(--text-muted)', marginBottom:3 }}>جمله ساخته‌شده (قابل ویرایش):</div>
            <input value={addTplLabel} onChange={e => setAddTplLabel(e.target.value)}
              placeholder='جمله فارسی...' style={{ ...selStyle, fontSize:12, marginBottom:8, fontWeight:500, color:'#a5b4fc' }} />

            <button onClick={async () => {
              if (!addTplLabel.trim()) return toast.error('جمله خالی است');
              const conditions = [{ field:addTplField, op:addTplOp, value:addTplVal, logic:'AND' }];
              const res = await api('/api/pool/segment-templates', { method:'POST', body:JSON.stringify({ label:addTplLabel, category:'سفارشی', conditions }) });
              if (res.success) {
                api('/api/pool/segment-templates').then(d => { if (d.success) setCondTemplates(d.data.templates); });
                toast.success('الگو ذخیره شد');
                setShowAddTpl(false);
              } else toast.error(res.message||'خطا');
            }} style={{ ...smBtn('#6366f1'), padding:'5px', width:'100%', textAlign:'center', fontSize:11, display:'block' }}>
              💾 ذخیره در پنل
            </button>
          </div>
        )}

        <input value={tplSearch} onChange={e=>setTplSearch(e.target.value)} placeholder='جستجو...' style={{ ...selStyle, marginBottom:10, fontSize:11 }} />
        {filtered ? (
          <div>
            {filtered.length === 0
              ? <div style={{ fontSize:11, color:'var(--text-muted)', textAlign:'center', padding:12 }}>نتیجه‌ای یافت نشد</div>
              : filtered.map(t => <button key={t.id} onClick={() => addFromTemplate(t)} style={chipSt}>{t.label}</button>)
            }
          </div>
        ) : (
          <>
            {sysCats.map(cat => (
              <div key={cat} style={{ marginBottom:6 }}>
                <button onClick={() => setOpenCats(p=>({...p,[cat]:p[cat]===false?true:false}))} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--text-muted)', fontSize:11, fontWeight:600, padding:'3px 0', display:'flex', alignItems:'center', gap:4, width:'100%' }}>
                  <span style={{ fontSize:9 }}>{openCats[cat]===false ? '▶' : '▼'}</span> {cat}
                </button>
                {openCats[cat] !== false && (
                  <div style={{ paddingRight:8 }}>
                    {condTemplates.filter(t=>t.is_system && t.category===cat).map(t => (
                      <button key={t.id} onClick={() => addFromTemplate(t)} style={chipSt}>{t.label}</button>
                    ))}
                  </div>
                )}
              </div>
            ))}
            {(() => {
              const flowGroup = fieldGroups[3];
              if (!flowGroup) return null;
              const scriptStates = flowGroup.fields.find(f=>f.v==='script_state.name')?.scriptStates || [];
              const campGroups   = flowGroup.fields.find(f=>f.v==='campaign_node')?.campGroups || [];
              if (!scriptStates.length && !campGroups.length) return null;
              const selBtnSt = active => ({ ...chipSt, marginBottom:2, background: active ? 'rgba(99,102,241,0.2)' : 'rgba(99,102,241,0.07)', borderColor: active ? '#6366f1' : 'rgba(99,102,241,0.25)', fontWeight: active ? 600 : 400 });
              return (
                <div style={{ borderTop:'1px solid var(--border)', paddingTop:10, marginTop:4 }}>
                  {scriptStates.length > 0 && (
                    <>
                      <div style={{ fontSize:11, fontWeight:600, marginBottom:5 }}>📜 اسکریپت</div>
                      {scriptStates.map(s => (
                        <React.Fragment key={s.scriptId}>
                          <button onClick={() => setPanelSelScript(p => p===s.scriptId ? '' : s.scriptId)}
                            style={selBtnSt(panelSelScript===s.scriptId)}>
                            {panelSelScript===s.scriptId ? '▾' : '▸'} {s.scriptName}
                          </button>
                          {panelSelScript===s.scriptId && (
                            <div style={{ paddingRight:10, marginBottom:4 }}>
                              <button onClick={() => addFromTemplate({ label:`اسکریپت «${s.scriptName}» فعال است`, conditions:[{ field:'script_state.script', op:'eq', value:s.scriptId, logic:'AND' }] })}
                                style={{ ...chipSt, marginBottom:4, fontSize:10, color:'var(--text-muted)' }}>+ فعال بودن این اسکریپت</button>
                              <div style={{ fontSize:10, color:'var(--text-muted)', marginBottom:3 }}>استپ (اسم):</div>
                              {s.states.map(st => (
                                <button key={st.id} onClick={() => addFromTemplate({ label:`در استپ «${st.name}» (${s.scriptName}) است`, conditions:[{ field:'script_state.script', op:'eq', value:s.scriptId, logic:'AND' }, { field:'script_state.name', op:'eq', value:st.name, logic:'AND' }] })}
                                  style={{ ...chipSt, fontSize:10 }}>{st.order}. {st.name}</button>
                              ))}
                              <div style={{ fontSize:10, color:'var(--text-muted)', margin:'5px 0 3px' }}>استپ (عدد):</div>
                              <div style={{ display:'flex', gap:4, alignItems:'center' }}>
                                <select id={`stepOp_${s.scriptId}`} style={{ ...selStyle, flex:1, fontSize:10, marginBottom:0 }}>
                                  <option value='eq'>برابر</option><option value='gte'>≥</option><option value='lte'>≤</option><option value='gt'>></option><option value='lt'>&lt;</option>
                                </select>
                                <input type='number' min='1' id={`stepVal_${s.scriptId}`} placeholder='شماره' style={{ ...selStyle, width:60, fontSize:10, marginBottom:0 }} />
                                <button onClick={() => {
                                  const op = document.getElementById(`stepOp_${s.scriptId}`)?.value||'eq';
                                  const val = document.getElementById(`stepVal_${s.scriptId}`)?.value||'';
                                  if (!val) return;
                                  const OL={eq:'=',gte:'≥',lte:'≤',gt:'>',lt:'<'};
                                  addFromTemplate({ label:`استپ ${OL[op]}${val} اسکریپت «${s.scriptName}»`, conditions:[{ field:'script_state.script', op:'eq', value:s.scriptId, logic:'AND' }, { field:'script_state.step', op, value:val, logic:'AND' }] });
                                }} style={{ ...smBtn('#6366f1'), fontSize:10, padding:'3px 7px' }}>+</button>
                              </div>
                            </div>
                          )}
                        </React.Fragment>
                      ))}
                    </>
                  )}
                  {campGroups.length > 0 && (
                    <div style={{ marginTop: scriptStates.length ? 8 : 0 }}>
                      <div style={{ fontSize:11, fontWeight:600, marginBottom:5 }}>🎯 کمپین</div>
                      {campGroups.map(c => (
                        <React.Fragment key={c.campId}>
                          <button onClick={() => setPanelSelCamp(p => p===c.campId ? '' : c.campId)}
                            style={selBtnSt(panelSelCamp===c.campId)}>
                            {panelSelCamp===c.campId ? '▾' : '▸'} {c.campName}
                          </button>
                          {panelSelCamp===c.campId && (
                            <div style={{ paddingRight:10, marginBottom:4 }}>
                              {c.nodes.map(n => (
                                <button key={n.v} onClick={() => addFromTemplate({ label:`نود «${n.label}» کمپین «${c.campName}»`, conditions:[{ field:'campaign_node', op:'eq', value:n.v, logic:'AND' }] })}
                                  style={{ ...chipSt, fontSize:10 }}>{n.label}</button>
                              ))}
                            </div>
                          )}
                        </React.Fragment>
                      ))}
                    </div>
                  )}
                </div>
              );
            })()}

            <div style={{ borderTop:'1px solid var(--border)', paddingTop:10, marginTop:4 }}>
              <div style={{ fontSize:11, fontWeight:600, marginBottom:6 }}>📊 داده‌های مکالمه</div>
              {collectedFields.length > 0 && (
                <div style={{ display:'flex', flexWrap:'wrap', gap:3, marginBottom:6 }}>
                  {collectedFields.map(f => (
                    <button key={f.v} onClick={() => addFromTemplate({ label:`«${f.label}» پر شده`, conditions:[{ field:f.v, op:'nempty', value:'', logic:'AND' }] })}
                      style={{ padding:'2px 7px', borderRadius:10, border:`1px solid ${f.collected?'rgba(34,197,94,0.4)':'rgba(99,102,241,0.2)'}`, background:'transparent', color:'var(--text-muted)', fontSize:10, cursor:'pointer' }}
                      title={f.collected ? 'داده واقعی در DB موجود است' : 'تعریف‌شده، هنوز جمع‌آوری نشده'}>
                      {f.collected ? '✓ ' : ''}{f.label}
                    </button>
                  ))}
                </div>
              )}
              <datalist id="coll-fields-list">
                {collectedFields.map(f => <option key={f.v} value={f.label} />)}
              </datalist>
              <input list="coll-fields-list" value={collField} onChange={e=>setCollField(e.target.value)} placeholder='نام فیلد — انتخاب یا تایپ کنید' style={{ ...selStyle, fontSize:11, marginBottom:4 }} />
              <select value={collOp} onChange={e=>setCollOp(e.target.value)} style={{ ...selStyle, fontSize:11, marginBottom:4 }}>
                <option value='eq'>برابر است</option>
                <option value='contains'>شامل است</option>
                <option value='nempty'>پر شده</option>
                <option value='empty'>خالی است</option>
              </select>
              {!['empty','nempty'].includes(collOp) && (
                <input value={collVal} onChange={e=>setCollVal(e.target.value)} placeholder='مقدار...' style={{ ...selStyle, fontSize:11, marginBottom:4 }} />
              )}
              <button onClick={() => {
                if (!collField.trim()) return;
                setForm(f => ({ ...f, conditions: [...f.conditions, { field:'collected.'+collField.trim(), op:collOp, value:collVal, logic:'AND' }] }));
                setCollVal('');
              }} style={{ ...smBtn('#6366f1'), padding:'5px', width:'100%', textAlign:'center', fontSize:11, display:'block' }}>+ اضافه کردن شرط</button>
            </div>
            {customTpls.length > 0 && (
              <div style={{ borderTop:'1px solid var(--border)', paddingTop:10, marginTop:8 }}>
                <div style={{ fontSize:11, fontWeight:600, marginBottom:6 }}>⚙️ الگوهای سفارشی</div>
                {customTpls.map(t => (
                  <div key={t.id} style={{ display:'flex', gap:4, alignItems:'center', marginBottom:3 }}>
                    <button onClick={() => addFromTemplate(t)} style={{ ...chipSt, flex:1, marginBottom:0 }}>{t.label}</button>
                    <button onClick={() => delSegTemplate(t.id)} style={{ background:'none', border:'none', cursor:'pointer', color:'#ef4444', fontSize:15, flexShrink:0 }}>×</button>
                  </div>
                ))}
              </div>
            )}
          </>
        )}
      </div>
    );
  };

  /* ── ترجمه فارسی وضعیت‌ها ── */
  const STATUS_FA = {
    new:'جدید', follow_up:'پیگیری', interested:'علاقمند',
    scheduled:'وقت گرفته', consultation:'مشاوره شده',
    buyer:'خریدار', lost:'از دست رفته', cancelled:'کنسل', bad_number:'شماره اشتباه',
  };
  const STATUS_OPTS = Object.keys(STATUS_FA);

  const ACTION_TYPES = [
    { v:'set_status',   label:'تغییر وضعیت به' },
    { v:'add_tag',      label:'زدن تگ' },
    { v:'join_campaign',label:'ورود به کمپین' },
    { v:'to_graveyard', label:'انتقال به قبرستان' },
    { v:'set_product',  label:'انتخابِ نوعِ محصول' },
  ];

  /* ── فیلدهای ساده (قابل نمایش بدون پیشرفته) ── */
  const SIMPLE_FIELDS = ['status','platform','score','source','sale_amount','call_count','no_answer_count','last_call_days','lead_age_days','days_since_update','tag','phone','free_courses_count'];

  /* ── تمپلیت‌های آماده ── */
  const TEMPLATES = [
    { icon:'❄️', name:'لیدهای سرد', conditions:[{ field:'last_call_days', op:'gte', value:'14', logic:'AND' },{ field:'status', op:'neq', value:'buyer', logic:'AND' }], actions:[] },
    { icon:'🔥', name:'علاقمندان داغ', conditions:[{ field:'status', op:'in', value:'interested,scheduled', logic:'AND' },{ field:'score', op:'gte', value:'7', logic:'AND' }], actions:[] },
    { icon:'💰', name:'خریداران', conditions:[{ field:'status', op:'eq', value:'buyer', logic:'AND' }], actions:[] },
    { icon:'📞', name:'هرگز تماس نگرفته', conditions:[{ field:'call_count', op:'eq', value:'0', logic:'AND' }], actions:[] },
    { icon:'⏰', name:'بی‌تحرک ۷ روز', conditions:[{ field:'days_since_update', op:'gte', value:'7', logic:'AND' }], actions:[] },
    { icon:'🆕', name:'لیدهای جدید', conditions:[{ field:'status', op:'eq', value:'new', logic:'AND' }], actions:[] },
  ];

  const addCond = () => setForm(f => ({ ...f, conditions: [...f.conditions, { field:'status', op:'eq', value:'', logic:'AND' }] }));
  const updCond = (i, k, v) => setForm(f => { const c=[...f.conditions]; c[i]={...c[i],[k]:v}; return {...f,conditions:c}; });
  const delCond = (i) => setForm(f => { const c=[...f.conditions]; c.splice(i,1); return {...f,conditions:c}; });

  const addAction = () => setForm(f => ({ ...f, actions: [...(f.actions||[]), { type:'set_status', value:'' }] }));
  const updAction = (i, k, v) => setForm(f => { const a=[...(f.actions||[])]; a[i]={...a[i],[k]:v}; if (k==='type') a[i].value=''; return {...f,actions:a}; });
  const delAction = (i) => setForm(f => { const a=[...(f.actions||[])]; a.splice(i,1); return {...f,actions:a}; });

  /* ──────────────────────────────────────────────
     renderCondRow — یک شرط با UI هوشمند (تابع، نه کامپوننت — جلوگیری از remount)
  ────────────────────────────────────────────── */
  const renderCondRow = (cond, index) => {
    const fd = fieldDef(cond.field);
    const ftype = fd?.type || 'text';
    const inpStyle = { ...selStyle, minWidth:0 };

    /* بر اساس نوع فیلد، UI متفاوت */
    let mainUI;

    if (ftype === 'tag') {
      /* تگ: [فیلد] [داشته/نداشته ▼] [لیست تگ ▼] */
      mainUI = <>
        <select value={cond.op} onChange={e => { updCond(index,'op',e.target.value); }} style={{ ...inpStyle, width:130 }}>
          <option value='has'>داشته باشد</option>
          <option value='ncontains'>نداشته باشد</option>
        </select>
        <select value={cond.value} onChange={e => updCond(index,'value',e.target.value)} style={{ ...inpStyle, flex:1 }}>
          <option value=''>— انتخاب تگ —</option>
          {availTags.map(t => <option key={t} value={t}>{t}</option>)}
        </select>
      </>;

    } else if (ftype === 'enum') {
      /* enum: [باشد/نباشد ▼] [مقادیر فارسی ▼] */
      const rawOpts = fd?.options || [];
      /* هر آپشن یا string ساده‌ست یا {v, label} */
      const opts = rawOpts.map(o => typeof o === 'string' ? { v: o, label: STATUS_FA[o] || o } : o);
      mainUI = <>
        <select value={cond.op} onChange={e => updCond(index,'op',e.target.value)} style={{ ...inpStyle, width:100 }}>
          <option value='eq'>باشد</option>
          <option value='neq'>نباشد</option>
          <option value='empty'>خالی است</option>
          <option value='nempty'>پر است</option>
          <option value='in'>یکی از</option>
        </select>
        {['empty','nempty'].includes(cond.op) ? null
          : cond.op === 'in'
          ? <input value={cond.value} onChange={e => updCond(index,'value',e.target.value)} placeholder='با کاما جدا کن' style={{ ...inpStyle, flex:1 }} />
          : <select value={cond.value} onChange={e => updCond(index,'value',e.target.value)} style={{ ...inpStyle, flex:1 }}>
              <option value=''>— انتخاب —</option>
              {opts.map(o => <option key={o.v} value={o.v}>{o.label}</option>)}
            </select>}
      </>;

    } else if (ftype === 'number') {
      /* عددی: [بیشتر از/کمتر از/برابر ▼] [عدد] */
      const unit = {
        score:'امتیاز', call_count:'تماس', no_answer_count:'بار',
        last_call_days:'روز', lead_age_days:'روز', days_since_update:'روز',
        days_since_last_status_change:'روز', free_courses_count:'دوره',
        sale_amount:'تومان', unpaid_installments_count:'قسط', overdue_installments_count:'قسط',
      }[cond.field] || '';
      mainUI = <>
        <select value={cond.op} onChange={e => updCond(index,'op',e.target.value)} style={{ ...inpStyle, width:110 }}>
          <option value='gte'>بیشتر از</option>
          <option value='lte'>کمتر از</option>
          <option value='eq'>برابر</option>
          <option value='gt'>بیشتر از (خالص)</option>
          <option value='lt'>کمتر از (خالص)</option>
          <option value='empty'>پر نشده</option>
          <option value='nempty'>پر شده</option>
        </select>
        {!['empty','nempty'].includes(cond.op) && <>
          <input type='number' value={cond.value} onChange={e => updCond(index,'value',e.target.value)}
            style={{ ...inpStyle, width:80 }} placeholder='عدد' />
          {unit && <span style={{ fontSize:11, color:'var(--text-muted)', whiteSpace:'nowrap' }}>{unit}</span>}
        </>}
      </>;

    } else {
      /* متنی: [پر است/خالی است/شامل/شامل نیست ▼] [متن] */
      mainUI = <>
        <select value={cond.op} onChange={e => updCond(index,'op',e.target.value)} style={{ ...inpStyle, width:130 }}>
          <option value='nempty'>پر است</option>
          <option value='empty'>خالی است</option>
          <option value='contains'>شامل</option>
          <option value='ncontains'>شامل نیست</option>
          <option value='eq'>برابر</option>
        </select>
        {!['empty','nempty'].includes(cond.op) &&
          <input value={cond.value} onChange={e => updCond(index,'value',e.target.value)}
            placeholder='متن...' style={{ ...inpStyle, flex:1 }} />}
      </>;
    }

    return (
      <div style={{ display:'flex', gap:6, alignItems:'center', background:'rgba(99,102,241,0.04)', borderRadius:8, padding:'8px 10px', border:'1px solid rgba(99,102,241,0.12)' }}>
        {/* AND/OR یا «اگر» */}
        {index > 0
          ? <select value={cond.logic||'AND'} onChange={e => updCond(index,'logic',e.target.value)} style={{ ...selStyle, width:62, flexShrink:0, fontSize:11 }}>
              <option value='AND'>و</option>
              <option value='OR'>یا</option>
            </select>
          : <span style={{ width:62, fontSize:11, color:'var(--text-muted)', textAlign:'center', flexShrink:0 }}>اگر</span>}

        {/* انتخاب فیلد */}
        <select value={cond.field} onChange={e => {
          const newFd = fieldDef(e.target.value);
          const defOp = newFd?.type==='enum' ? 'eq' : newFd?.type==='number' ? 'gte' : newFd?.type==='tag' ? 'has' : 'nempty';
          updCond(index,'field',e.target.value);
          updCond(index,'op',defOp);
          updCond(index,'value','');
        }} style={{ ...selStyle, width:150, flexShrink:0 }}>
          {fieldGroups.map(g => (
            <optgroup key={g.label} label={g.label}>
              {g.fields.filter(f => SIMPLE_FIELDS.includes(f.v) || f.v.startsWith('collected.') || f.v.startsWith('script_state.') || f.v === 'campaign_node').map(o =>
                <option key={o.v} value={o.v}>{o.label}</option>
              )}
            </optgroup>
          ))}
        </select>

        {/* UI مخصوص هر نوع فیلد */}
        {mainUI}

        <button onClick={() => delCond(index)} style={{ background:'none', border:'none', cursor:'pointer', color:'#ef4444', fontSize:18, lineHeight:1, flexShrink:0, padding:'0 2px' }}>×</button>
      </div>
    );
  };

  return (
    <div style={{ display:'flex', flexDirection:'column', height:'100%' }}>
      <div style={{ padding:16, overflowY:'auto', flex:1 }}>
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:12 }}>
        <div style={{ fontSize:13, fontWeight:600 }}>سگمنت‌بندی</div>
        <Button size='sm' variant='primary' onClick={() => { setEditing(null); setForm(EMPTY_FORM); setShowForm(true); api('/api/pool/segments/fields').then(d => { if (d.success) setFieldGroups(d.data.groups); }); }}>
          + سگمنت جدید
        </Button>
      </div>

      <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(260px,1fr))', gap:10 }}>
        {segments.map(seg => (
          <div key={seg.id} style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:10, padding:12, borderRight:`3px solid ${seg.color}` }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:6 }}>
              <span style={{ fontSize:18 }}>{seg.icon}</span>
              <span style={{ fontSize:13, fontWeight:600, color:seg.color }}>{seg.name}</span>
              {!seg.is_active && <span style={{ fontSize:9, padding:'1px 6px', borderRadius:8, background:'#374151', color:'#9ca3af', marginRight:'auto' }}>غیرفعال</span>}
            </div>
            {seg.description && <div style={{ fontSize:11, color:'var(--text-muted)', marginBottom:8 }}>{seg.description}</div>}
            <div style={{ fontSize:10, color:'var(--text-muted)', marginBottom:6, display:'flex', gap:10, alignItems:'center' }}>
              <span>{fa(seg.conditions.length)} شرط</span>
              <span style={{ color: seg.color, fontWeight:700, fontSize:13 }}>{fa(seg.member_count ?? 0)} عضو</span>
              {seg.is_system && <span style={{ marginRight:'auto', fontSize:9, padding:'1px 6px', borderRadius:8, background:'rgba(99,102,241,0.1)', color:'#818cf8' }}>🔒 سیستمی</span>}
            </div>
            {(seg.actions||[]).length > 0 && (
              <div style={{ display:'flex', flexWrap:'wrap', gap:4, marginBottom:8 }}>
                {(seg.actions||[]).map((a,i) => (
                  <span key={i} style={{ fontSize:9, padding:'2px 7px', borderRadius:8,
                    background: a.type==='add_tag'      ? 'rgba(129,140,248,0.12)' :
                                a.type==='set_status'   ? 'rgba(52,211,153,0.1)'   :
                                a.type==='to_graveyard' ? 'rgba(248,113,113,0.1)'  :
                                                          'rgba(251,146,60,0.1)',
                    color:      a.type==='add_tag'      ? '#818cf8' :
                                a.type==='set_status'   ? '#34d399' :
                                a.type==='to_graveyard' ? '#f87171' : '#fb923c' }}>
                    {a.type==='add_tag'       ? `🏷️ ${a.value}`   :
                     a.type==='set_status'    ? `→ ${a.value}`    :
                     a.type==='join_campaign' ? '📣 کمپین'         :
                     a.type==='to_graveyard'  ? '🪦 قبرستان'       :
                     a.type==='set_product'   ? `📦 ${(segProducts.find(p=>p.id===a.value)||{}).name || 'محصول'}` : a.type}
                  </span>
                ))}
              </div>
            )}
            <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
              <button onClick={() => refreshSeg(seg)} disabled={refreshing[seg.id]} style={smBtn('#34d399')}>{refreshing[seg.id] ? '...' : '🔄 بروزرسانی'}</button>
              <button onClick={() => viewLeads(seg)} style={smBtn('#3b82f6')}>لیدها</button>
              <button onClick={() => exportCsv(seg)} style={smBtn('#f59e0b')}>📥 اکسل</button>
              <button onClick={() => openBatch(seg)} style={smBtn('#a855f7')}>⚡ اقدام گروهی</button>
              {!seg.is_system && <button onClick={() => { setEditing(seg.id); setForm({...seg}); setShowForm(true); api('/api/pool/segments/fields').then(d => { if (d.success) setFieldGroups(d.data.groups); }); }} style={smBtn('#6366f1')}>ویرایش</button>}
              {!seg.is_system && <button onClick={() => del(seg.id)} style={smBtn('#ef4444')}>حذف</button>}
            </div>
          </div>
        ))}
      </div>

      {/* Form Modal */}
      {showForm && (
        <Modal open={true} onClose={() => setShowForm(false)} title={editing ? 'ویرایش سگمنت' : 'سگمنت جدید'} width={segMode==='simple' ? 'min(94vw, 1100px)' : 560}>
          <div style={{ display:'flex', flexDirection:'column', gap:0 }}>

            {/* ── toggle حالت ── */}
            <div style={{ display:'flex', gap:6, marginBottom:12, borderBottom:'1px solid var(--border)', paddingBottom:10 }}>
              {[['simple','🎯 حالت ساده'],['advanced','⚙️ حالت پیشرفته']].map(([m,label]) => (
                <button key={m} onClick={() => setSegMode(m)} style={{
                  padding:'5px 14px', borderRadius:8, border:'1px solid', fontSize:12, cursor:'pointer',
                  borderColor: segMode===m ? '#6366f1' : 'var(--border)',
                  background: segMode===m ? 'rgba(99,102,241,0.15)' : 'transparent',
                  color: segMode===m ? '#818cf8' : 'var(--text-muted)',
                }}>{label}</button>
              ))}
            </div>

            <div style={{ display:'flex', gap:20, height:'calc(82vh - 80px)', overflow:'hidden' }}>

              {/* ── پنل راست (اول در DOM = راست در RTL) ── */}
              {segMode === 'simple' && renderCondPanel()}

              {/* ── فرم چپ ── */}
              <div style={{ display:'flex', flexDirection:'column', gap:12, flex:1, overflowY:'auto' }}>

                {/* نام و رنگ */}
                <div style={{ display:'flex', gap:8 }}>
                  <input value={form.icon} onChange={e => setForm(f=>({...f,icon:e.target.value}))} style={{ ...selStyle, width:52, textAlign:'center', fontSize:20 }} />
                  <input value={form.name} onChange={e => setForm(f=>({...f,name:e.target.value}))} placeholder='نام سگمنت' style={{ ...selStyle, flex:1 }} />
                  <input type='color' value={form.color} onChange={e => setForm(f=>({...f,color:e.target.value}))} style={{ width:40, height:34, border:'none', cursor:'pointer', borderRadius:6 }} />
                </div>

                {segMode === 'simple' ? (
                  /* حالت ساده: chips */
                  <div>
                    <div style={{ fontSize:12, fontWeight:600, marginBottom:6, display:'flex', alignItems:'center', gap:6 }}>
                      <span>شرط‌های ورود</span>
                      <span style={{ fontSize:10, color:'var(--text-muted)', fontWeight:400 }}>— از پنل راست انتخاب کنید</span>
                    </div>
                    <div style={{ display:'flex', flexWrap:'wrap', gap:6, minHeight:48, padding:'8px 10px', border:'1px dashed rgba(99,102,241,0.2)', borderRadius:8, alignContent:'flex-start' }}>
                      {form.conditions.length === 0
                        ? <span style={{ fontSize:11, color:'var(--text-muted)', margin:'auto' }}>هیچ شرطی انتخاب نشده — همه لیدها عضو می‌شوند</span>
                        : form.conditions.map((c,i) => (
                            <span key={i} style={{ display:'inline-flex', alignItems:'center', gap:4, padding:'4px 10px', borderRadius:20, background:'rgba(99,102,241,0.12)', border:'1px solid rgba(99,102,241,0.3)', fontSize:11, color:'#818cf8' }}>
                              {i>0 && <span style={{ fontSize:9, color:'#6b7280', marginLeft:2 }}>{c.logic==='OR'?'یا':'و'}</span>}
                              {condToLabel(c)}
                              <button onClick={() => delCond(i)} style={{ background:'none', border:'none', cursor:'pointer', color:'#ef4444', fontSize:14, padding:'0 0 0 4px', lineHeight:1 }}>×</button>
                            </span>
                          ))
                      }
                    </div>
                  </div>
                ) : (
                  /* حالت پیشرفته: builder کامل */
                  <div>
                    {!editing && (
                      <div style={{ marginBottom:10 }}>
                        <div style={{ fontSize:11, color:'var(--text-muted)', marginBottom:6 }}>الگوی آماده:</div>
                        <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
                          {TEMPLATES.map(t => (
                            <button key={t.name} onClick={() => setForm(f => ({ ...f, name: f.name||t.name, icon: f.icon||t.icon, conditions: t.conditions, actions: t.actions }))}
                              style={{ display:'flex', alignItems:'center', gap:5, padding:'5px 11px', borderRadius:8, border:'1px solid rgba(99,102,241,0.3)', background:'rgba(99,102,241,0.07)', color:'var(--text)', fontSize:12, cursor:'pointer' }}>
                              {t.icon} {t.name}
                            </button>
                          ))}
                        </div>
                      </div>
                    )}
                    <div style={{ fontSize:12, fontWeight:600, marginBottom:8, display:'flex', alignItems:'center', gap:6 }}>
                      <span>شرط‌های ورود</span>
                      <span style={{ fontSize:10, color:'var(--text-muted)', fontWeight:400 }}>— لیدی که همه شرط‌ها رو داشته باشه وارد می‌شه</span>
                    </div>
                    <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
                      {form.conditions.length === 0 && (
                        <div style={{ fontSize:12, color:'var(--text-muted)', padding:'12px 16px', border:'1px dashed rgba(99,102,241,0.2)', borderRadius:8, textAlign:'center' }}>
                          هیچ شرطی تعریف نشده — همه لیدها عضو می‌شوند
                        </div>
                      )}
                      {form.conditions.map((c,i) => (
                        <React.Fragment key={i}>{renderCondRow(c, i)}</React.Fragment>
                      ))}
                    </div>
                    <button onClick={addCond} style={{ ...smBtn('#6366f1'), marginTop:8 }}>+ شرط جدید</button>
                  </div>
                )}

                {/* اقدام‌ها */}
                <div>
                  <div style={{ fontSize:12, fontWeight:600, marginBottom:4 }}>⚡ اقدام موقع ورود</div>
                  <div style={{ fontSize:10, color:'var(--text-muted)', marginBottom:8 }}>هر اکشن برای هر لید فقط یک بار (اولین باری که وارد سگمنت می‌شود) اجرا می‌شود</div>
                  <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
                    {(form.actions||[]).map((a,i) => (
                      <div key={i} style={{ display:'flex', gap:6, alignItems:'center', background:'rgba(167,139,250,0.05)', borderRadius:8, padding:'8px 10px', border:'1px solid rgba(167,139,250,0.15)' }}>
                        <select value={a.type} onChange={e => updAction(i,'type',e.target.value)} style={{ ...selStyle, flex:1 }}>
                          {ACTION_TYPES.map(o => <option key={o.v} value={o.v}>{o.label}</option>)}
                        </select>
                        {a.type === 'set_status' && (
                          <select value={a.value} onChange={e => updAction(i,'value',e.target.value)} style={{ ...selStyle, width:150 }}>
                            <option value=''>— انتخاب وضعیت —</option>
                            {STATUS_OPTS.map(s => <option key={s} value={s}>{STATUS_FA[s]||s}</option>)}
                          </select>
                        )}
                        {a.type === 'add_tag' && (
                          <input value={a.value} onChange={e => updAction(i,'value',e.target.value)} placeholder='نام تگ' style={{ ...selStyle, width:150 }} />
                        )}
                        {a.type === 'join_campaign' && (
                          <select value={a.value} onChange={e => updAction(i,'value',e.target.value)} style={{ ...selStyle, width:150 }}>
                            <option value=''>— انتخاب کمپین —</option>
                            {campaigns.map(c => <option key={c.id} value={c.id}>{c.name||c.title||c.id}</option>)}
                          </select>
                        )}
                        {a.type === 'to_graveyard' && (
                          <span style={{ fontSize:11, color:'#f87171', flex:1 }}>لید به قبرستان منتقل می‌شود</span>
                        )}
                        {a.type === 'set_product' && (
                          <select value={a.value} onChange={e => updAction(i,'value',e.target.value)} style={{ ...selStyle, width:150 }}>
                            <option value=''>— انتخاب محصول —</option>
                            {segProducts.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
                          </select>
                        )}
                        <button onClick={() => delAction(i)} style={{ background:'none', border:'none', cursor:'pointer', color:'#ef4444', fontSize:18, lineHeight:1, padding:'0 2px' }}>×</button>
                      </div>
                    ))}
                  </div>
                  <button onClick={addAction} style={{ ...smBtn('#a78bfa'), marginTop:8 }}>+ اقدام جدید</button>
                </div>

                <div style={{ display:'flex', gap:8, justifyContent:'flex-end', marginTop:4, paddingTop:8, borderTop:'1px solid var(--border)' }}>
                  <Button variant='ghost' onClick={() => setShowForm(false)}>انصراف</Button>
                  <Button variant='primary' onClick={save}>ذخیره</Button>
                </div>
              </div>

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

      {/* Leads Modal */}
      {segLeads && (
        <Modal open={true} onClose={() => setSegLeads(null)} title={`لیدهای سگمنت: ${segLeads.seg.name} (${segLeads.total})`}>
          <div style={{ maxHeight:400, overflowY:'auto', minWidth:400 }}>
            {segLeads.leads.length === 0 && <div style={{ padding:20, textAlign:'center', color:'var(--text-muted)', fontSize:12 }}>لیدی در این سگمنت نیست</div>}
            {segLeads.leads.map(l => (
              <div key={l.id} style={{ padding:'8px 12px', borderBottom:'1px solid var(--border)', display:'flex', gap:8, alignItems:'center' }}>
                <div style={{ flex:1, fontSize:12 }}>{l.full_name||l.username||l.id}</div>
                <span style={{ fontSize:10, color:'var(--text-muted)' }}>{l.platform}</span>
                <span style={{ fontSize:10, padding:'1px 6px', borderRadius:8, background:'#1e2536', color:'#94a3b8' }}>{l.status}</span>
              </div>
            ))}
          </div>
        </Modal>
      )}

      {/* Batch Action Modal */}
      {batchModal && (
        <Modal open={true} onClose={() => setBatchModal(null)} title={`اقدام گروهی — ${batchModal.seg.icon} ${batchModal.seg.name}`}>
          <div style={{ display:'flex', flexDirection:'column', gap:14, minWidth:360 }}>
            <div style={{ display:'flex', gap:8 }}>
              {[['campaign','📣 کمپین'],['followup','🔔 فالوآپ'],['distribute','🎯 توزیع خودکار']].map(([v,label]) => (
                <button key={v} onClick={() => setBatchAction(v)} style={{
                  flex:1, padding:'8px 4px', borderRadius:8, border:'1px solid',
                  borderColor: batchAction===v ? '#6366f1' : 'var(--border)',
                  background: batchAction===v ? 'rgba(99,102,241,0.15)' : 'transparent',
                  color: batchAction===v ? '#818cf8' : 'var(--text-muted)',
                  cursor:'pointer', fontSize:12, fontWeight:600,
                }}>{label}</button>
              ))}
            </div>

            {batchAction === 'campaign' && (
              <div>
                <div style={{ fontSize:11, color:'var(--text-muted)', marginBottom:4 }}>انتخاب کمپین:</div>
                <select value={batchCampaign} onChange={e => setBatchCampaign(e.target.value)} style={{ ...selStyle, width:'100%' }}>
                  {campaigns.length === 0 && <option value=''>کمپینی یافت نشد</option>}
                  {campaigns.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                </select>
              </div>
            )}

            {batchAction === 'followup' && (
              <div>
                <div style={{ fontSize:11, color:'var(--text-muted)', marginBottom:4 }}>انتخاب قانون فالوآپ:</div>
                <select value={batchRule} onChange={e => setBatchRule(e.target.value)} style={{ ...selStyle, width:'100%' }}>
                  {followupRules.length === 0 && <option value=''>قانونی یافت نشد</option>}
                  {followupRules.map(r => <option key={r.id} value={r.id}>{r.name}</option>)}
                </select>
              </div>
            )}

            {batchAction === 'distribute' && (
              <div style={{ fontSize:12, color:'var(--text-muted)', padding:'8px 12px', borderRadius:8, background:'rgba(99,102,241,0.05)', border:'1px solid var(--border)' }}>
                لیدهای این سگمنت بین فروشندگان فعال توزیع خواهند شد.
              </div>
            )}

            <div style={{ display:'flex', gap:8, justifyContent:'flex-end', marginTop:4 }}>
              <Button variant='ghost' onClick={() => setBatchModal(null)}>انصراف</Button>
              <Button variant='primary' onClick={doBatchAction} disabled={batchLoading}>
                {batchLoading ? 'در حال اجرا...' : 'اجرا'}
              </Button>
            </div>
          </div>
        </Modal>
      )}
      </div>
    </div>
  );
};

// ═══════════════════════════════════════════════════════════
//  TAB: ایمپورت گروهی
// ═══════════════════════════════════════════════════════════

/* نگاشتِ هوشمندِ ستون‌ها — نسخه‌ی سمتِ فرانت. برای aliasها هماهنگ با
   IMPORT_FIELD_ALIASES در server/modules/leadPool/leadPoolModule.js بمونه. */
const IMPORT_FIELD_ALIASES = {
  full_name: ['نام و نام خانوادگی', 'نام ونام خانوادگی', 'اسم و فامیل', 'نام و فامیل', 'نام کامل', 'نام', 'اسم', 'name', 'full_name', 'fullname'],
  phone:     ['شماره تماس', 'شماره موبایل', 'تلفن تماس', 'شماره', 'موبایل', 'تلفن', 'phone', 'mobile', 'tel', 'شماره‌تماس'],
  username:  ['یوزرنیم', 'نام کاربری', 'آیدی تلگرام', 'آیدی', 'username', 'user', 'telegram id'],
  email:     ['ایمیل', 'پست الکترونیک', 'email', 'e-mail', 'mail'],
  lead_type: ['نوع لید', 'نوع', 'lead_type', 'lead type', 'type'],
  source:    ['منبع', 'منشا', 'source'],
  interest:  ['علاقه‌مندی', 'علاقمندی', 'علاقه', 'interest'],
  product:   ['محصول مورد نظر', 'محصول', 'دوره مورد علاقه', 'دوره', 'product', 'course'],
  seller:    ['ارجاع به فروشنده', 'فروشنده', 'seller'],
  notes:     ['یادداشت', 'یادداشت‌ها', 'توضیحات', 'notes', 'note', 'comment'],
};

function normalizeHeaderText(s) {
  return String(s || '')
    .replace(/‌/g, '')          // نیم‌فاصله
    .replace(/[يى]/g, 'ی').replace(/ك/g, 'ک') // یکسان‌سازی عربی/فارسی
    .replace(/[\s_\-]+/g, '')        // فاصله/آندرلاین/خط‌تیره
    .trim().toLowerCase();
}

const _IMPORT_ALIAS_LOOKUP = (() => {
  const map = {};
  Object.entries(IMPORT_FIELD_ALIASES).forEach(([field, aliases]) => {
    aliases.forEach(a => { map[normalizeHeaderText(a)] = field; });
  });
  return map;
})();

function resolveImportField(rawHeader) {
  const h = normalizeHeaderText(rawHeader);
  if (!h) return null;
  if (_IMPORT_ALIAS_LOOKUP[h]) return _IMPORT_ALIAS_LOOKUP[h]; // تطابق دقیق
  // fallback: تطابقِ جزئی (شامل‌بودن) — طولانی‌ترین alias برنده است
  let best = null, bestLen = 0;
  Object.entries(_IMPORT_ALIAS_LOOKUP).forEach(([alias, field]) => {
    if (alias.length >= 2 && (h.includes(alias) || alias.includes(h)) && alias.length > bestLen) {
      best = field; bestLen = alias.length;
    }
  });
  return best;
}

const LeadImportTab = ({ hideTitle, onDone } = {}) => {
  const { useToast } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const { useState, useRef } = React;
  const toast   = useToast();
  const token   = localStorage.getItem(window.TOKEN_KEY);
  const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };

  const [rawText,  setRawText]  = useState('');
  const [source,   setSource]   = useState('');
  const [preview,  setPreview]  = useState(null);   // آرایه ردیف‌های parse شده
  const [result,   setResult]   = useState(null);   // نتیجه import
  const [loading,  setLoading]  = useState(false);
  const fileRef = useRef();

  /* ── parse CSV/TSV ── */
  function parseText(text) {
    const lines = text.trim().split('\n').filter(l => l.trim());
    if (!lines.length) return [];

    /* تشخیص جداکننده */
    const sep = lines[0].includes('\t') ? '\t' : ',';
    const headers_row = lines[0].split(sep).map(h => h.trim().replace(/^"|"$/g, '').toLowerCase());

    const colIdx = {};
    headers_row.forEach((h, i) => { const f = resolveImportField(h); if (f) colIdx[f] = i; });

    /* اگه header نداشت، فرض: ستون اول=نام، دوم=موبایل، سوم=یوزرنیم */
    const hasHeader = Object.keys(colIdx).length > 0;
    const dataLines = hasHeader ? lines.slice(1) : lines;
    if (!hasHeader) { colIdx.full_name = 0; colIdx.phone = 1; colIdx.username = 2; }

    return dataLines.map(line => {
      const cells = line.split(sep).map(c => c.trim().replace(/^"|"$/g, ''));
      const get = (k) => cells[colIdx[k]] || '';
      return {
        full_name:  get('full_name'),
        phone:      get('phone').replace(/\D/g,''),
        username:   get('username'),
        email:      get('email'),
        lead_type:  get('lead_type'),
        source:     get('source'),
        interest:   get('interest'),
        product:    get('product'),
        seller:     get('seller'),
        notes:      get('notes'),
      };
    }).filter(r => r.full_name || r.phone || r.username);
  }

  function handleParse() {
    const rows = parseText(rawText);
    setPreview(rows);
    setResult(null);
    if (!rows.length) toast('هیچ ردیف معتبری پیدا نشد', 'warn');
  }

  /* یک فایل رو parse می‌کنه و آرایه‌ی ردیف‌ها رو برمی‌گردونه (اکسل از سرور، CSV/TSV محلی) */
  function parseOneFile(file) {
    const isExcel = /\.(xlsx|xls)$/i.test(file.name);
    if (isExcel) {
      const fd = new FormData();
      fd.append('file', file);
      return fetch('/api/pool/import/parse-excel', {
        method: 'POST',
        headers: { Authorization: `Bearer ${token}` },
        body: fd,
      }).then(r => r.json()).then(d => {
        if (d.success) return d.data.leads;
        toast(`${file.name}: ${d.message || 'خطا در خواندن فایل اکسل'}`, 'error');
        return [];
      }).catch(() => { toast(`${file.name}: خطای شبکه`, 'error'); return []; });
    }
    return new Promise(resolve => {
      const reader = new FileReader();
      reader.onload = ev => resolve(parseText(ev.target.result));
      reader.onerror = () => { toast(`${file.name}: خطا در خواندن فایل`, 'error'); resolve([]); };
      reader.readAsText(file, 'UTF-8');
    });
  }

  /* آپلود یک یا چند فایل — نتیجه‌ی همه ادغام می‌شود (ستون‌های هم‌معنی روی یک فیلد یکتا نگاشت می‌شوند) */
  async function handleFile(e) {
    const files = Array.from(e.target.files || []);
    if (!files.length) return;
    setRawText('');
    setPreview(null);
    setResult(null);
    setLoading(true);
    try {
      const rowsPerFile = await Promise.all(files.map(parseOneFile));
      const merged = rowsPerFile.flat();
      setPreview(merged);
      if (!merged.length) toast('هیچ ردیف معتبری در فایل(ها) پیدا نشد', 'warn');
      else if (files.length > 1) toast(`✅ ${files.length} فایل ادغام شد — ${merged.length} ردیف`, 'success');
    } finally {
      setLoading(false);
      e.target.value = '';
    }
  }

  async function handleImport() {
    if (!preview?.length) return;
    setLoading(true);
    try {
      const r = await fetch('/api/pool/import', {
        method: 'POST', headers,
        body: JSON.stringify({ leads: preview, source }),
      }).then(r => r.json());
      if (r.success) {
        setResult(r.data);
        setPreview(null);
        setRawText('');
        toast(`✅ ${r.data.inserted} لید وارد شد`, 'success');
        onDone && onDone();
      } else {
        toast(r.message || 'خطا در ایمپورت', 'error');
      }
    } catch { toast('خطای شبکه', 'error'); }
    setLoading(false);
  }

  const inputStyle = { width:'100%', padding:'8px 12px', borderRadius:8, background:'rgba(255,255,255,0.06)', border:'1px solid rgba(255,255,255,0.1)', color:'#e2e8f0', fontSize:12, outline:'none', boxSizing:'border-box', fontFamily:'Vazirmatn,sans-serif', direction:'rtl' };

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
      {!hideTitle && <div>
        <div style={{ fontSize:16, fontWeight:700, color:'#e2e8f0', marginBottom:4 }}>📥 ایمپورت گروهی لیدها</div>
      </div>}
      <div>
        <div style={{ fontSize:11, color:'#475569', lineHeight:1.7 }}>
          فرمت CSV یا TSV — همون ستون‌های فرم «ثبت دستی»: <span style={{color:'#818CF8'}}>نام کامل، شماره تماس، ایمیل، نوع لید، منبع، علاقه‌مندی، محصول، فروشنده، یادداشت</span> (یوزرنیم هم پشتیبانی می‌شود)<br/>
          فقط ستون‌هایی که لازم دارید را بگذارید — بقیه اختیاری‌اند. ردیف اول می‌تواند header باشد یا نباشد. لیدهای تکراری (موبایل/یوزرنیم یکسان) نادیده گرفته می‌شوند.
        </div>
      </div>

      {/* نمونه فرمت */}
      <div style={{ padding:'10px 14px', borderRadius:8, background:'rgba(255,255,255,0.03)', border:'1px solid rgba(255,255,255,0.07)', fontSize:11, color:'#64748b', fontFamily:'monospace', direction:'ltr', lineHeight:1.8 }}>
        نام کامل,شماره تماس,ایمیل,نوع لید,منبع,علاقه‌مندی,محصول,فروشنده,یادداشت<br/>
        علی رضایی,09123456789,ali@x.com,مشتری دستی,اینستاگرام,دوره پیشرفته,,,علاقه‌مند به تخفیف<br/>
        سارا احمدی,09351234567,,,,,,,
      </div>

      {/* ورودی منبع */}
      <div>
        <div style={{ fontSize:11, color:'#64748b', marginBottom:5 }}>منبع (اختیاری)</div>
        <input value={source} onChange={e => setSource(e.target.value)} placeholder="مثلاً: نمایشگاه خرداد ۱۴۰۵" style={{ ...inputStyle, width:'auto', minWidth:260 }} />
      </div>

      {/* textarea + آپلود */}
      <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
        <div style={{ display:'flex', alignItems:'center', gap:10 }}>
          <div style={{ fontSize:11, color:'#64748b' }}>داده‌ها را paste کنید یا یک یا چند فایل اکسل/CSV آپلود کنید (فایل‌های متعدد با هم ادغام می‌شوند)</div>
          <button onClick={() => fileRef.current?.click()} disabled={loading} style={{ padding:'4px 12px', borderRadius:7, fontSize:11, cursor: loading ? 'default' : 'pointer', border:'1px solid rgba(99,102,241,0.3)', background:'rgba(99,102,241,0.08)', color:'#818CF8' }}>
            {loading ? '⏳ در حال خواندن فایل...' : '📂 آپلود فایل (Excel/CSV) — چند فایل مجاز'}
          </button>
          <input ref={fileRef} type="file" accept=".xlsx,.xls,.csv,.tsv,.txt" multiple onChange={handleFile} style={{ display:'none' }} />
        </div>
        <textarea
          value={rawText}
          onChange={e => { setRawText(e.target.value); setPreview(null); setResult(null); }}
          placeholder="نام کامل,شماره تماس,ایمیل,نوع لید,منبع,علاقه‌مندی,محصول,فروشنده,یادداشت&#10;علی رضایی,09123456789,,,,,,,"
          rows={7}
          style={{ ...inputStyle, resize:'vertical', lineHeight:1.7 }}
        />
      </div>

      {/* دکمه parse */}
      <button
        onClick={handleParse}
        disabled={!rawText.trim()}
        style={{ padding:'9px 20px', borderRadius:9, fontSize:12, fontWeight:700, cursor:'pointer', border:'none', background: rawText.trim() ? '#6366F1' : 'rgba(99,102,241,0.2)', color: rawText.trim() ? '#fff' : '#475569', alignSelf:'flex-start' }}
      >
        🔍 پیش‌نمایش
      </button>

      {/* پیش‌نمایش */}
      {preview && (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          <div style={{ display:'flex', alignItems:'center', gap:10 }}>
            <div style={{ fontSize:12, fontWeight:700, color:'#e2e8f0' }}>{fa(preview.length)} ردیف آماده ایمپورت</div>
            <button
              onClick={handleImport}
              disabled={loading || !preview.length}
              style={{ padding:'7px 18px', borderRadius:8, fontSize:12, fontWeight:700, cursor:'pointer', border:'none', background:'#22C55E', color:'#fff' }}
            >
              {loading ? 'در حال وارد کردن...' : '✅ تأیید و ایمپورت'}
            </button>
            <button onClick={() => setPreview(null)} style={{ padding:'7px 12px', borderRadius:8, fontSize:11, cursor:'pointer', border:'1px solid rgba(255,255,255,0.1)', background:'transparent', color:'#64748b' }}>انصراف</button>
          </div>

          <div style={{ maxHeight:280, overflowY:'auto', borderRadius:10, border:'1px solid rgba(255,255,255,0.08)' }}>
            <table style={{ width:'100%', borderCollapse:'collapse', fontSize:11 }}>
              <thead>
                <tr style={{ background:'rgba(255,255,255,0.05)' }}>
                  {['#','نام','موبایل','یوزرنیم','ایمیل','نوع لید','منبع','علاقه‌مندی','محصول','فروشنده','یادداشت'].map(h => (
                    <th key={h} style={{ padding:'7px 12px', textAlign:'right', color:'#64748b', fontWeight:600, borderBottom:'1px solid rgba(255,255,255,0.07)', whiteSpace:'nowrap' }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {preview.slice(0,100).map((r,i) => (
                  <tr key={i} style={{ borderBottom:'1px solid rgba(255,255,255,0.04)' }}>
                    <td style={{ padding:'6px 12px', color:'#334155' }}>{i+1}</td>
                    <td style={{ padding:'6px 12px', color:'#e2e8f0' }}>{r.full_name || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8', fontFamily:'monospace' }}>{r.phone || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.username || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.email || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.lead_type || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.source || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.interest || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.product || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.seller || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.notes || '—'}</td>
                  </tr>
                ))}
                {preview.length > 100 && (
                  <tr><td colSpan={11} style={{ padding:'8px 12px', textAlign:'center', color:'#475569', fontSize:10 }}>و {fa(preview.length-100)} ردیف دیگر...</td></tr>
                )}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {/* نتیجه */}
      {result && (
        <div style={{ display:'flex', gap:12, flexWrap:'wrap' }}>
          {[
            { label:'وارد شد',    value: result.inserted,  color:'#4ADE80', bg:'rgba(74,222,128,0.1)'  },
            { label:'تکراری',     value: result.duplicates,color:'#F59E0B', bg:'rgba(245,158,11,0.1)'  },
            { label:'خطا',        value: result.errors,    color:'#F87171', bg:'rgba(248,113,113,0.1)' },
            { label:'کل پردازش', value: result.total,     color:'#818CF8', bg:'rgba(129,140,248,0.1)' },
          ].map(s => (
            <div key={s.label} style={{ padding:'12px 20px', borderRadius:12, background:s.bg, border:`1px solid ${s.color}30`, textAlign:'center', minWidth:90 }}>
              <div style={{ fontSize:22, fontWeight:800, color:s.color }}>{s.value}</div>
              <div style={{ fontSize:10, color:'#64748b', marginTop:3 }}>{s.label}</div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════
//  TAB: ایمپورت اکسل نوین‌هاب (ادغام ۲ فایل + سگمنت‌بندی گرم/ولرم/سرد + ۹ نوع محصول)
// ═══════════════════════════════════════════════════════════
const NovinHubImportTab = ({ hideTitle, onDone } = {}) => {
  const { useToast } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const { useState, useRef, useEffect } = React;
  const toast  = useToast();
  const token  = localStorage.getItem(window.TOKEN_KEY);
  const h = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };

  const [file1, setFile1] = useState(null);
  const [file2, setFile2] = useState(null);
  const [source, setSource] = useState('');
  const [preview, setPreview] = useState(null); // { preview, withoutPhoneRows, total, withPhone, withoutPhone }
  const [result, setResult] = useState(null);
  const [loading, setLoading] = useState(false);
  const [showProductTypes, setShowProductTypes] = useState(false);
  const [productTypes, setProductTypes] = useState(null);
  const [savingTypes, setSavingTypes] = useState(false);
  const [showSegmentThresholds, setShowSegmentThresholds] = useState(false);
  const [segmentThresholds, setSegmentThresholds] = useState(null);
  const [savingThresholds, setSavingThresholds] = useState(false);
  const ref1 = useRef(); const ref2 = useRef();

  const SEG_COLOR = { 'گرم': '#F87171', 'ولرم': '#FBBF24', 'سرد': '#60A5FA' };

  function loadProductTypes() {
    fetch('/api/pool/novinhub/product-types', { headers: h }).then(r => r.json()).then(d => { if (d.success) setProductTypes(d.data.productTypes); });
  }
  function loadSegmentThresholds() {
    fetch('/api/pool/novinhub/segment-thresholds', { headers: h }).then(r => r.json()).then(d => { if (d.success) setSegmentThresholds(d.data.thresholds); });
  }
  useEffect(() => { loadProductTypes(); loadSegmentThresholds(); }, []);

  async function saveProductTypes() {
    setSavingTypes(true);
    try {
      const r = await fetch('/api/pool/novinhub/product-types', { method: 'PUT', headers: h, body: JSON.stringify({ productTypes }) }).then(r => r.json());
      if (r.success) { setProductTypes(r.data.productTypes); toast('✅ تنظیمات نوع محصول ذخیره شد', 'success'); setShowProductTypes(false); }
      else toast(r.message || 'خطا در ذخیره', 'error');
    } catch { toast('خطای شبکه', 'error'); }
    setSavingTypes(false);
  }

  function updateProductType(idx, field, value) {
    setProductTypes(list => list.map((pt, i) => i === idx ? { ...pt, [field]: value } : pt));
  }
  function toggleProductTypeSeg(idx, seg) {
    setProductTypes(list => list.map((pt, i) => {
      if (i !== idx) return pt;
      const has = pt.segs.includes(seg);
      return { ...pt, segs: has ? pt.segs.filter(s => s !== seg) : [...pt.segs, seg] };
    }));
  }
  function addProductType() {
    setProductTypes(list => [...list, { code: `X${list.length+1}`, name: 'محصول جدید', sys: null, budMin: null, budMax: null, ageMin: null, ageMax: null, isBusiness: false, canObtain: null, reqSkill: null, segs: [segmentThresholds?.[0]?.segment || 'گرم'] }]);
  }
  function removeProductType(idx) {
    setProductTypes(list => list.length > 1 ? list.filter((_, i) => i !== idx) : list);
  }
  function moveProductType(idx, dir) {
    setProductTypes(list => {
      const j = idx + dir;
      if (j < 0 || j >= list.length) return list;
      const copy = [...list];
      [copy[idx], copy[j]] = [copy[j], copy[idx]];
      return copy;
    });
  }

  async function saveSegmentThresholds() {
    setSavingThresholds(true);
    try {
      const r = await fetch('/api/pool/novinhub/segment-thresholds', { method: 'PUT', headers: h, body: JSON.stringify({ thresholds: segmentThresholds }) }).then(r => r.json());
      if (r.success) { setSegmentThresholds(r.data.thresholds); toast('✅ تنظیمات سگمنت‌بندی ذخیره شد', 'success'); setShowSegmentThresholds(false); }
      else toast(r.message || 'خطا در ذخیره', 'error');
    } catch { toast('خطای شبکه', 'error'); }
    setSavingThresholds(false);
  }

  function updateSegmentThreshold(idx, field, value) {
    setSegmentThresholds(list => list.map((t, i) => i === idx ? { ...t, [field]: field === 'segment' ? value : (value === '' ? null : Number(value)) } : t));
  }
  function addSegmentThreshold() {
    setSegmentThresholds(list => [...list, { segment: 'سگمنت جدید', sys: null, budMin: null, budMax: null, ageMin: null, ageMax: null }]);
  }
  function removeSegmentThreshold(idx) {
    setSegmentThresholds(list => list.length > 1 ? list.filter((_, i) => i !== idx) : list);
  }
  function moveSegmentThreshold(idx, dir) {
    setSegmentThresholds(list => {
      const j = idx + dir;
      if (j < 0 || j >= list.length) return list;
      const copy = [...list];
      [copy[idx], copy[j]] = [copy[j], copy[idx]];
      return copy;
    });
  }

  async function handlePreview() {
    if (!file1 && !file2) return toast('حداقل یک فایل اکسل انتخاب کنید', 'warn');
    setLoading(true); setResult(null); setPreview(null);
    try {
      const fd = new FormData();
      if (file1) fd.append('file1', file1);
      if (file2) fd.append('file2', file2);
      const r = await fetch('/api/pool/import/novinhub/preview', {
        method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: fd,
      }).then(r => r.json());
      if (r.success) {
        setPreview(r.data);
        if (!r.data.preview.length && !r.data.withoutPhoneRows.length) toast('هیچ ردیف قابل‌استفاده‌ای در فایل(ها) پیدا نشد', 'warn');
        else toast(`✅ ${r.data.preview.length} لید سگمنت‌بندی شد (از ${r.data.total} ردیف — ${r.data.withoutPhone} بدون شماره)`, 'success');
      } else toast(r.message || 'خطا در پردازش فایل‌ها', 'error');
    } catch { toast('خطای شبکه', 'error'); }
    setLoading(false);
  }

  async function handleCommit() {
    if (!preview?.preview?.length && !preview?.withoutPhoneRows?.length) return;
    setLoading(true);
    try {
      const r = await fetch('/api/pool/import/novinhub/commit', {
        method: 'POST',
        headers: h,
        body: JSON.stringify({ leads: preview.preview, withoutPhoneLeads: preview.withoutPhoneRows, source }),
      }).then(r => r.json());
      if (r.success) {
        setResult(r.data);
        setPreview(null);
        toast(`✅ ${r.data.inserted} لید وارد استخر شد`, 'success');
        onDone && onDone();
      } else toast(r.message || 'خطا در ایمپورت', 'error');
    } catch { toast('خطای شبکه', 'error'); }
    setLoading(false);
  }

  const inputStyle = { width:'100%', padding:'8px 12px', borderRadius:8, background:'rgba(255,255,255,0.06)', border:'1px solid rgba(255,255,255,0.1)', color:'#e2e8f0', fontSize:12, outline:'none', boxSizing:'border-box', fontFamily:'Vazirmatn,sans-serif', direction:'rtl' };
  const fileBtnStyle = { padding:'8px 14px', borderRadius:8, fontSize:11, cursor:'pointer', border:'1px solid rgba(99,102,241,0.3)', background:'rgba(99,102,241,0.08)', color:'#818CF8', whiteSpace:'nowrap' };
  const iconBtnStyle = { padding:'2px 6px', borderRadius:5, fontSize:10, cursor:'pointer', border:'1px solid rgba(255,255,255,0.1)', background:'transparent', color:'#94a3b8' };

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
      {!hideTitle && <div style={{ fontSize:16, fontWeight:700, color:'#e2e8f0' }}>📊 ایمپورت اکسل نوین‌هاب</div>}
      <div style={{ fontSize:11, color:'#475569', lineHeight:1.7 }}>
        دو فایل اکسل (مثلاً از دو منبع/کمپین) را انتخاب کنید — با هم ادغام می‌شوند، بعد بر اساس ستون‌های
        <span style={{color:'#818CF8'}}> سیستم / سن / بودجه </span>
        هر لید <span style={{color:'#F87171'}}>گرم</span>، <span style={{color:'#FBBF24'}}>ولرم</span> یا <span style={{color:'#60A5FA'}}>سرد</span> می‌شود و یکی از ۹ نوع محصول (A تا I، قابل تنظیم) به آن تخصیص می‌یابد. ردیف‌های بدون شماره هم به‌جای حذف‌شدن با تگ «بدون-شماره» جداگانه ذخیره می‌شوند تا برای پیگیری دستی در دسترس باشند (تکراری‌ها بر اساس شماره/نام نادیده گرفته می‌شوند).
      </div>

      <div style={{ display:'flex', gap:12, flexWrap:'wrap', alignItems:'center' }}>
        <div style={{ display:'flex', alignItems:'center', gap:8 }}>
          <button onClick={() => ref1.current?.click()} style={fileBtnStyle}>📂 فایل اول {file1 ? `— ${file1.name}` : ''}</button>
          <input ref={ref1} type="file" accept=".xlsx,.xls" onChange={e => setFile1(e.target.files?.[0] || null)} style={{ display:'none' }} />
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:8 }}>
          <button onClick={() => ref2.current?.click()} style={fileBtnStyle}>📂 فایل دوم {file2 ? `— ${file2.name}` : ''}</button>
          <input ref={ref2} type="file" accept=".xlsx,.xls" onChange={e => setFile2(e.target.files?.[0] || null)} style={{ display:'none' }} />
        </div>
        <button onClick={() => setShowProductTypes(s => !s)} style={{ ...fileBtnStyle, border:'1px solid rgba(255,255,255,0.12)', background:'rgba(255,255,255,0.04)', color:'#94a3b8' }}>
          ⚙️ تنظیم ۹ نوع محصول
        </button>
        <button onClick={() => setShowSegmentThresholds(s => !s)} style={{ ...fileBtnStyle, border:'1px solid rgba(255,255,255,0.12)', background:'rgba(255,255,255,0.04)', color:'#94a3b8' }}>
          ⚙️ تنظیم گرم/ولرم/سرد
        </button>
      </div>

      {showSegmentThresholds && segmentThresholds && (
        <div style={{ padding:12, borderRadius:10, border:'1px solid rgba(255,255,255,0.08)', background:'rgba(255,255,255,0.02)', display:'flex', flexDirection:'column', gap:8 }}>
          <div style={{ fontSize:11, color:'#64748b' }}>هر سگمنت مستقیماً با بازه‌ی بودجه/سیستم/سن تعریف می‌شود — ردیف‌ها به‌ترتیب از بالا چک می‌شوند (اولین ردیفی که شرایطش جور شد انتخاب می‌شود)؛ آخرین ردیف عملاً fallback است، یعنی هر لیدی که به هیچ ردیف قبلی نخورد به آن می‌رسد. می‌توانید سگمنت اضافه/حذف/جابه‌جا کنید — چون قوانین ممکن است هر روز عوض شود.</div>
          <div style={{ overflowX:'auto' }}>
            <table style={{ width:'100%', borderCollapse:'collapse', fontSize:11 }}>
              <thead>
                <tr style={{ background:'rgba(255,255,255,0.05)' }}>
                  {['ترتیب','سگمنت','سیستم','حداقل بودجه','حداکثر بودجه','حداقل سن','حداکثر سن',''].map(hh => (
                    <th key={hh} style={{ padding:'6px 8px', textAlign:'right', color:'#64748b', fontWeight:600 }}>{hh}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {segmentThresholds.map((t, idx) => (
                  <tr key={idx} style={{ borderBottom:'1px solid rgba(255,255,255,0.04)' }}>
                    <td style={{ padding:'5px 8px', whiteSpace:'nowrap' }}>
                      <button onClick={() => moveSegmentThreshold(idx, -1)} disabled={idx===0} style={{ ...iconBtnStyle, opacity: idx===0?0.3:1 }}>▲</button>
                      <button onClick={() => moveSegmentThreshold(idx, 1)} disabled={idx===segmentThresholds.length-1} style={{ ...iconBtnStyle, opacity: idx===segmentThresholds.length-1?0.3:1 }}>▼</button>
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input value={t.segment} onChange={e => updateSegmentThreshold(idx, 'segment', e.target.value)} style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:90, color:SEG_COLOR[t.segment] || '#818CF8', fontWeight:700 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <select value={t.sys === null || t.sys === undefined ? '' : t.sys} onChange={e => updateSegmentThreshold(idx, 'sys', e.target.value)} style={{ ...inputStyle, padding:'4px 6px', fontSize:11, width:'auto' }}>
                        <option value="">هر حالت</option>
                        <option value="1">دارد</option>
                        <option value="0">موبایل</option>
                        <option value="-1">ندارد</option>
                      </select>
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input type="number" value={t.budMin ?? ''} onChange={e => updateSegmentThreshold(idx, 'budMin', e.target.value)} placeholder="—" style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:80 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input type="number" value={t.budMax ?? ''} onChange={e => updateSegmentThreshold(idx, 'budMax', e.target.value)} placeholder="∞" style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:80 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input type="number" value={t.ageMin ?? ''} onChange={e => updateSegmentThreshold(idx, 'ageMin', e.target.value)} placeholder="—" style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:70 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input type="number" value={t.ageMax ?? ''} onChange={e => updateSegmentThreshold(idx, 'ageMax', e.target.value)} placeholder="∞" style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:70 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <button onClick={() => removeSegmentThreshold(idx)} disabled={segmentThresholds.length<=1} title="حذف سگمنت" style={{ ...iconBtnStyle, color:'#F87171', opacity: segmentThresholds.length<=1?0.3:1 }}>✕</button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          <div style={{ display:'flex', gap:8 }}>
            <button onClick={addSegmentThreshold} style={{ padding:'6px 14px', borderRadius:7, fontSize:11, cursor:'pointer', border:'1px dashed rgba(99,102,241,0.4)', background:'transparent', color:'#818CF8' }}>+ افزودن سگمنت</button>
            <div style={{ flex:1 }} />
            <button onClick={saveSegmentThresholds} disabled={savingThresholds} style={{ padding:'6px 16px', borderRadius:7, fontSize:11, fontWeight:700, cursor:'pointer', border:'none', background:'#22C55E', color:'#fff' }}>
              {savingThresholds ? 'در حال ذخیره...' : '✅ ذخیره تنظیمات'}
            </button>
            <button onClick={() => { loadSegmentThresholds(); setShowSegmentThresholds(false); }} style={{ padding:'6px 12px', borderRadius:7, fontSize:11, cursor:'pointer', border:'1px solid rgba(255,255,255,0.1)', background:'transparent', color:'#64748b' }}>انصراف</button>
          </div>
        </div>
      )}

      {showProductTypes && productTypes && (
        <div style={{ padding:12, borderRadius:10, border:'1px solid rgba(255,255,255,0.08)', background:'rgba(255,255,255,0.02)', display:'flex', flexDirection:'column', gap:8 }}>
          <div style={{ fontSize:11, color:'#64748b' }}>کد، نام، وضعیت سیستم (۱=دارد / ۰=موبایل / خالی=هرحالت / ۱-=ندارد)، بازه بودجه و سگمنت‌های هدفِ هر نوع محصول قابل ویرایش‌اند — ردیف‌ها به‌ترتیب از بالا چک می‌شوند. «می‌تواند تهیه کند» فقط وقتی سیستم=ندارد فعال است؛ «مهارت دارد» فقط برایِ محصولاتِ بیزینسی فعال است. می‌توانید نوع محصول اضافه/حذف/جابه‌جا کنید چون قوانین ممکن است هر روز عوض شود.</div>
          <div style={{ overflowX:'auto' }}>
            <table style={{ width:'100%', borderCollapse:'collapse', fontSize:11 }}>
              <thead>
                <tr style={{ background:'rgba(255,255,255,0.05)' }}>
                  {['ترتیب','کد','نام محصول','سیستم','می‌تواند تهیه کند؟','بیزینس؟','مهارت دارد؟','حداقل بودجه','حداکثر بودجه','حداقل سن','حداکثر سن','سگمنت‌های هدف',''].map(hh => (
                    <th key={hh} style={{ padding:'6px 8px', textAlign:'right', color:'#64748b', fontWeight:600 }}>{hh}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {productTypes.map((pt, idx) => (
                  <tr key={idx} style={{ borderBottom:'1px solid rgba(255,255,255,0.04)' }}>
                    <td style={{ padding:'5px 8px', whiteSpace:'nowrap' }}>
                      <button onClick={() => moveProductType(idx, -1)} disabled={idx===0} style={{ ...iconBtnStyle, opacity: idx===0?0.3:1 }}>▲</button>
                      <button onClick={() => moveProductType(idx, 1)} disabled={idx===productTypes.length-1} style={{ ...iconBtnStyle, opacity: idx===productTypes.length-1?0.3:1 }}>▼</button>
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input value={pt.code} onChange={e => updateProductType(idx, 'code', e.target.value)} style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:50, color:'#818CF8', fontWeight:700 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input value={pt.name} onChange={e => updateProductType(idx, 'name', e.target.value)} title={pt.name} style={{ ...inputStyle, padding:'4px 8px', fontSize:11, minWidth:140 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <select value={pt.sys === null || pt.sys === undefined ? '' : pt.sys} onChange={e => updateProductType(idx, 'sys', e.target.value === '' ? null : Number(e.target.value))} style={{ ...inputStyle, padding:'4px 6px', fontSize:11, width:'auto' }}>
                        <option value="">هر حالت</option>
                        <option value="1">دارد</option>
                        <option value="0">موبایل</option>
                        <option value="-1">ندارد</option>
                      </select>
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <select disabled={pt.sys !== -1} value={pt.canObtain === null || pt.canObtain === undefined ? '' : pt.canObtain} onChange={e => updateProductType(idx, 'canObtain', e.target.value === '' ? null : Number(e.target.value))} style={{ ...inputStyle, padding:'4px 6px', fontSize:11, width:'auto', opacity: pt.sys !== -1 ? 0.4 : 1 }}>
                        <option value="">هر حالت</option>
                        <option value="1">می‌تواند</option>
                        <option value="0">نمی‌تواند</option>
                      </select>
                    </td>
                    <td style={{ padding:'5px 8px', textAlign:'center' }}>
                      <input type="checkbox" checked={!!pt.isBusiness} onChange={e => updateProductType(idx, 'isBusiness', e.target.checked)} style={{ cursor:'pointer' }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <select disabled={!pt.isBusiness} value={pt.reqSkill === null || pt.reqSkill === undefined ? '' : pt.reqSkill} onChange={e => updateProductType(idx, 'reqSkill', e.target.value === '' ? null : Number(e.target.value))} style={{ ...inputStyle, padding:'4px 6px', fontSize:11, width:'auto', opacity: !pt.isBusiness ? 0.4 : 1 }}>
                        <option value="">هر حالت</option>
                        <option value="1">دارد</option>
                        <option value="0">ندارد</option>
                      </select>
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input type="number" value={pt.budMin ?? ''} onChange={e => updateProductType(idx, 'budMin', e.target.value === '' ? null : Number(e.target.value))} placeholder="—" style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:80 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input type="number" value={pt.budMax ?? ''} onChange={e => updateProductType(idx, 'budMax', e.target.value === '' ? null : Number(e.target.value))} placeholder="∞" style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:80 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input type="number" value={pt.ageMin ?? ''} onChange={e => updateProductType(idx, 'ageMin', e.target.value === '' ? null : Number(e.target.value))} placeholder="—" style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:70 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <input type="number" value={pt.ageMax ?? ''} onChange={e => updateProductType(idx, 'ageMax', e.target.value === '' ? null : Number(e.target.value))} placeholder="∞" style={{ ...inputStyle, padding:'4px 8px', fontSize:11, width:70 }} />
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
                        {(segmentThresholds||[]).map(t => (
                          <label key={t.segment} style={{ display:'flex', alignItems:'center', gap:3, fontSize:10, color: pt.segs.includes(t.segment) ? (SEG_COLOR[t.segment]||'#818CF8') : '#475569', cursor:'pointer' }}>
                            <input type="checkbox" checked={pt.segs.includes(t.segment)} onChange={() => toggleProductTypeSeg(idx, t.segment)} style={{ cursor:'pointer' }} />
                            {t.segment}
                          </label>
                        ))}
                      </div>
                    </td>
                    <td style={{ padding:'5px 8px' }}>
                      <button onClick={() => removeProductType(idx)} disabled={productTypes.length<=1} title="حذف نوع محصول" style={{ ...iconBtnStyle, color:'#F87171', opacity: productTypes.length<=1?0.3:1 }}>✕</button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          <div style={{ display:'flex', gap:8 }}>
            <button onClick={addProductType} style={{ padding:'6px 14px', borderRadius:7, fontSize:11, cursor:'pointer', border:'1px dashed rgba(99,102,241,0.4)', background:'transparent', color:'#818CF8' }}>+ افزودن نوع محصول</button>
            <div style={{ flex:1 }} />
            <button onClick={saveProductTypes} disabled={savingTypes} style={{ padding:'6px 16px', borderRadius:7, fontSize:11, fontWeight:700, cursor:'pointer', border:'none', background:'#22C55E', color:'#fff' }}>
              {savingTypes ? 'در حال ذخیره...' : '✅ ذخیره تنظیمات'}
            </button>
            <button onClick={() => { loadProductTypes(); setShowProductTypes(false); }} style={{ padding:'6px 12px', borderRadius:7, fontSize:11, cursor:'pointer', border:'1px solid rgba(255,255,255,0.1)', background:'transparent', color:'#64748b' }}>انصراف</button>
          </div>
        </div>
      )}

      <div>
        <div style={{ fontSize:11, color:'#64748b', marginBottom:5 }}>منبع (اختیاری)</div>
        <input value={source} onChange={e => setSource(e.target.value)} placeholder="مثلاً: کمپین اکسل نوین‌هاب" style={{ ...inputStyle, width:'auto', minWidth:260 }} />
      </div>

      <button
        onClick={handlePreview}
        disabled={loading || (!file1 && !file2)}
        style={{ padding:'9px 20px', borderRadius:9, fontSize:12, fontWeight:700, cursor:'pointer', border:'none', background: (!loading && (file1||file2)) ? '#6366F1' : 'rgba(99,102,241,0.2)', color: (!loading && (file1||file2)) ? '#fff' : '#475569', alignSelf:'flex-start' }}
      >
        {loading && !preview ? '⏳ در حال پردازش...' : '🔍 ادغام و سگمنت‌بندی'}
      </button>

      {preview && (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          <div style={{ display:'flex', alignItems:'center', gap:10, flexWrap:'wrap' }}>
            <div style={{ fontSize:12, fontWeight:700, color:'#e2e8f0' }}>
              {fa(preview.preview.length)} لید دارای شماره + {fa(preview.withoutPhoneRows.length)} لید بدون شماره — از {fa(preview.total)} ردیف
            </div>
            <button onClick={handleCommit} disabled={loading || (!preview.preview.length && !preview.withoutPhoneRows.length)} style={{ padding:'7px 18px', borderRadius:8, fontSize:12, fontWeight:700, cursor:'pointer', border:'none', background:'#22C55E', color:'#fff' }}>
              {loading ? 'در حال وارد کردن...' : '✅ تأیید و ایمپورت به استخر'}
            </button>
            <button onClick={() => setPreview(null)} style={{ padding:'7px 12px', borderRadius:8, fontSize:11, cursor:'pointer', border:'1px solid rgba(255,255,255,0.1)', background:'transparent', color:'#64748b' }}>انصراف</button>
          </div>

          <div style={{ maxHeight:320, overflowY:'auto', borderRadius:10, border:'1px solid rgba(255,255,255,0.08)' }}>
            <table style={{ width:'100%', borderCollapse:'collapse', fontSize:11 }}>
              <thead>
                <tr style={{ background:'rgba(255,255,255,0.05)' }}>
                  {['#','نام','موبایل','سن','سگمنت','محصول','یادداشت بودجه'].map(h => (
                    <th key={h} style={{ padding:'7px 12px', textAlign:'right', color:'#64748b', fontWeight:600, borderBottom:'1px solid rgba(255,255,255,0.07)', whiteSpace:'nowrap' }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {preview.preview.slice(0,150).map((r,i) => (
                  <tr key={i} style={{ borderBottom:'1px solid rgba(255,255,255,0.04)' }}>
                    <td style={{ padding:'6px 12px', color:'#334155' }}>{i+1}</td>
                    <td style={{ padding:'6px 12px', color:'#e2e8f0' }}>{r.full_name || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8', fontFamily:'monospace' }}>{r.phone || '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.age ?? '—'}</td>
                    <td style={{ padding:'6px 12px' }}><span style={{ color: SEG_COLOR[r.segment]||'#94a3b8', fontWeight:700 }}>{r.segment}</span></td>
                    <td style={{ padding:'6px 12px', color:'#94a3b8' }}>{r.productCode !== '?' ? `[${r.productCode}] ${r.productName}` : '—'}</td>
                    <td style={{ padding:'6px 12px', color:'#64748b' }}>{r.budgetNote || '—'}</td>
                  </tr>
                ))}
                {preview.preview.length > 150 && (
                  <tr><td colSpan={7} style={{ padding:'8px 12px', textAlign:'center', color:'#475569', fontSize:10 }}>و {fa(preview.preview.length-150)} ردیف دیگر...</td></tr>
                )}
              </tbody>
            </table>
          </div>

          {preview.withoutPhoneRows.length > 0 && (
            <details style={{ borderRadius:10, border:'1px solid rgba(255,255,255,0.08)' }}>
              <summary style={{ padding:'8px 12px', cursor:'pointer', fontSize:11, color:'#94a3b8' }}>
                📋 {fa(preview.withoutPhoneRows.length)} ردیف بدون شماره تماس (با تگ «بدون-شماره» ذخیره می‌شوند)
              </summary>
              <div style={{ maxHeight:180, overflowY:'auto', padding:'0 12px 10px' }}>
                {preview.withoutPhoneRows.slice(0,100).map((r,i) => (
                  <div key={i} style={{ fontSize:11, color:'#64748b', padding:'3px 0' }}>{i+1}. {r.full_name}</div>
                ))}
                {preview.withoutPhoneRows.length > 100 && <div style={{ fontSize:10, color:'#475569' }}>و {fa(preview.withoutPhoneRows.length-100)} ردیف دیگر...</div>}
              </div>
            </details>
          )}
        </div>
      )}

      {result && (
        <div style={{ display:'flex', gap:12, flexWrap:'wrap' }}>
          {[
            { label:'وارد شد',    value: result.inserted,  color:'#4ADE80', bg:'rgba(74,222,128,0.1)'  },
            { label:'تکراری',     value: result.duplicates,color:'#F59E0B', bg:'rgba(245,158,11,0.1)'  },
            { label:'خطا',        value: result.errors,    color:'#F87171', bg:'rgba(248,113,113,0.1)' },
            { label:'کل پردازش', value: result.total,     color:'#818CF8', bg:'rgba(129,140,248,0.1)' },
          ].map(s => (
            <div key={s.label} style={{ padding:'12px 20px', borderRadius:12, background:s.bg, border:`1px solid ${s.color}30`, textAlign:'center', minWidth:90 }}>
              <div style={{ fontSize:22, fontWeight:800, color:s.color }}>{s.value}</div>
              <div style={{ fontSize:10, color:'#64748b', marginTop:3 }}>{s.label}</div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════
//  TAB: قبرستان
// ═══════════════════════════════════════════════════════════
const GraveyardTab = () => {
  const { fa } = window.SB_DATA;
  const { useToast } = window.SB_UI;
  const { useState, useEffect } = React;
  const toast = useToast();
  const token = localStorage.getItem(window.TOKEN_KEY);
  const h = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };
  const api = (url, opts = {}) => fetch(url, { headers: h, ...opts }).then(r => r.json());

  const [data, setData] = useState(null);
  const [selected, setSelected] = useState(new Set());
  const [campaigns, setCampaigns] = useState([]);
  const [campId, setCampId] = useState('');
  const [search, setSearch] = useState('');
  const [detailLead, setDetailLead] = useState(null);
  const [reasonFilter, setReasonFilter] = useState(null);
  const [sellerFilter, setSellerFilter] = useState('');
  const [dateFrom, setDateFrom] = useState('');
  const [dateTo, setDateTo] = useState('');

  // قانونِ کاربر (۲۰۲۶-۰۸-۱۰): مثلِ جدولِ استخر، صفحه‌بندی نمی‌خواد — همه‌ی لیدها یک‌جا لود بشن.
  const load = () => {
    api(`/api/leads/graveyard/list?page=1&limit=5000`).then(d => { if (d.success) { setData(d.data); setSelected(new Set()); } });
  };
  useEffect(() => {
    load();
    // کشفِ زنده: مسیرِ درستِ لیستِ کمپین‌ها /api/campaigns/campaigns است (router روی
    // /api/campaigns مانت شده و خودِ روتِ لیست هم /campaigns است) — /api/campaigns
    // به‌تنهایی مسیرِ نداشته‌ای بود که همیشه کمپینِ خالی برمی‌گردوند و دکمه‌ی
    // «ارسالِ قبرستان به کمپینِ بازیابی» هیچ‌وقت گزینه‌ای نداشت.
    api('/api/campaigns/campaigns').then(d => { const list = Array.isArray(d) ? d : (d.data?.campaigns || d.campaigns || []); setCampaigns(list); }).catch(() => {});
  }, []);

  const toggleSel = (id) => setSelected(s => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });
  // قانونِ کاربر (۲۰۲۶-۰۸-۱۱): سرچ در نام/شماره/یوزرنیم — کاملاً سمتِ کلاینت، چون کلِ
  // لیست (تا ۵۰۰۰ تا) یک‌جا لود شده، نیازی به رفت‌وبرگشتِ سرور نیست.
  const searchNorm = search.trim().toLowerCase();
  const filteredLeads = (data?.leads || []).filter(l => {
    if (searchNorm && !(
      (l.full_name || '').toLowerCase().includes(searchNorm) ||
      (l.username || '').toLowerCase().includes(searchNorm) ||
      (l.phone || '').includes(searchNorm)
    )) return false;
    // قانونِ کاربر (۲۰۲۶-۰۸-۱۱): چیپ‌هایِ «دلایلِ از دست دادن» باید فیلترِ کلیک‌پذیر هم باشن —
    // مقدارِ چیپ خودش COALESCE(NULLIF(lost_reason,''),'بدون دلیل')ه (سمتِ بک‌اند)، پس اینجا
    // هم باید همون نگاشت رو رویِ خودِ لید بزنیم تا «بدون دلیل» با ردیف‌هایِ واقعاً خالی مچ بشه.
    if (reasonFilter && (l.lost_reason || 'بدون دلیل') !== reasonFilter) return false;
    if (sellerFilter && (l.lost_by || '') !== sellerFilter) return false;
    // قانونِ کاربر (۲۰۲۶-۰۸-۱۳): فیلترِ تاریخ بر اساسِ updated_at (همون تاریخی که تویِ
    // ستونِ «تاریخ» نمایش داده می‌شه — یعنی وقتی وارد قبرستان شده).
    const leadDate = (l.updated_at || '').slice(0, 10);
    if (dateFrom && leadDate < dateFrom) return false;
    if (dateTo && leadDate > dateTo) return false;
    return true;
  });
  const toggleAll = () => setSelected(s => s.size === filteredLeads.length ? new Set() : new Set(filteredLeads.map(l => l.id)));
  // قانونِ کاربر (۲۰۲۶-۰۸-۱۳): فیلترِ فروش‌یار در قبرستان — چون seller_id موقعِ حذف/کنسلی
  // خالی می‌شه (طبقِ قانونِ ۲۳/۲۴)، تنها ردِ باقی‌مونده از «کی این لید رو کنسل کرد» فیلدِ
  // lost_by (متنِ «فروش‌یار: X» / «ادمین: Y») است — همون رو برایِ فیلتر استفاده می‌کنیم.
  const sellerOptions = React.useMemo(() => {
    const set = new Set((data?.leads || []).map(l => l.lost_by).filter(Boolean));
    return [...set].sort();
  }, [data]);

  const toCampaign = async () => {
    if (!campId) return toast.error('اول کمپین رو انتخاب کن');
    const r = await api('/api/pool/graveyard/to-campaign', { method:'POST', body: JSON.stringify({ lead_ids: [...selected], campaign_id: campId }) });
    if (r.success) { toast.success(`📨 ${r.data.added} لید وارد کمپین بازیابی شد`); load(); }
    else toast.error(r.message || 'خطا');
  };

  const restore = async () => {
    if (!confirm(`${selected.size} لید به استخر برگردن؟ (وضعیت → پیگیری)`)) return;
    const r = await api('/api/pool/graveyard/restore', { method:'POST', body: JSON.stringify({ lead_ids: [...selected] }) });
    if (r.success) { toast.success(`🌊 ${r.data.restored} لید به استخر برگشت`); load(); }
    else toast.error(r.message || 'خطا');
  };

  const STATUS_LABEL = { lost:'از دست رفته', cancelled:'انصراف', bad_number:'شماره اشتباه' };
  const STATUS_COLOR = { lost:'#f87171', cancelled:'#fb923c', bad_number:'#94a3b8' };
  // قانونِ کاربر (۲۰۲۶-۰۸-۱۰): نمایشِ قبرستان باید هم‌ساختارِ جدولِ استخر باشه.
  const G_OUTCOME_COLOR = { answered:'#34D399', no_answer:'#F87171', call_later:'#818CF8', follow_up:'#818CF8', scheduled:'#A78BFA', sold:'#34D399', not_interested:'#6B7280', cancelled:'#EF4444', bad_number:'#DC2626', re_request:'#60A5FA' };
  const G_OUTCOME_ICON  = { answered:'✅', no_answer:'📵', call_later:'⏰', follow_up:'🔄', scheduled:'📅', sold:'💰', not_interested:'❌', cancelled:'🚫', bad_number:'☎️', re_request:'🔁' };
  const G_OUTCOME_LABEL = { answered:'جواب داد', no_answer:'بی‌پاسخ', call_later:'بعداً', follow_up:'پیگیری', scheduled:'زمان داد', sold:'فروش', not_interested:'علاقه نداشت', cancelled:'کنسل', bad_number:'شماره اشتباه', re_request:'درخواست مجدد' };

  return (
    <div style={{ padding:16, overflowY:'auto', height:'100%', display:'flex', flexDirection:'column', gap:12 }}>
      {data && (
        <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8, padding:'10px 12px', maxWidth:200 }}>
          <div style={{ fontSize:10, color:'var(--text-muted)', marginBottom:4 }}>کل قبرستان</div>
          <div style={{ fontSize:22, fontWeight:700, color:'#475569' }}>{fa(data.total||0)}</div>
        </div>
      )}

      {data && data.stats.by_reason?.length > 0 && (
        <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8, padding:12 }}>
          <div style={{ fontSize:12, fontWeight:600, marginBottom:8, display:'flex', alignItems:'center', gap:8 }}>
            دلایل از دست دادن
            {reasonFilter && <button onClick={() => setReasonFilter(null)} style={{ ...pgBtn, padding:'2px 8px', fontSize:10 }}>✕ حذفِ فیلتر</button>}
          </div>
          <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
            {data.stats.by_reason.map(r => {
              const active = reasonFilter === r.lost_reason;
              return (
                <button key={r.lost_reason} onClick={() => setReasonFilter(active ? null : r.lost_reason)}
                  style={{ fontSize:10, padding:'3px 10px', borderRadius:10, cursor:'pointer', border:'none',
                    background: active ? '#f87171' : '#f8717122', color: active ? '#fff' : '#f87171', fontWeight: active ? 700 : 400 }}>
                  {r.lost_reason||'نامشخص'}: {fa(r.cnt)}
                </button>
              );
            })}
          </div>
        </div>
      )}

      {/* نوار اکشن گروهی */}
      {selected.size > 0 && (
        <div style={{ display:'flex', alignItems:'center', gap:8, padding:'8px 12px', borderRadius:8, background:'#1e1b3a', border:'1px solid #4f46e555', position:'sticky', top:0, zIndex:5 }}>
          <span style={{ fontSize:12, fontWeight:700, color:'#a78bfa' }}>{fa(selected.size)} انتخاب شده</span>
          <div style={{ flex:1 }} />
          <select value={campId} onChange={e => setCampId(e.target.value)} style={{ ...pgBtn, minWidth:160, cursor:'pointer' }}>
            <option value=''>— انتخاب کمپین بازیابی —</option>
            {campaigns.map(c => <option key={c.id} value={c.id}>{c.name||c.title||c.id}</option>)}
          </select>
          <button onClick={toCampaign} style={smBtn('#a78bfa')}>📨 ارسال به کمپین</button>
          <button onClick={restore} style={smBtn('#34d399')}>🌊 برگشت به استخر</button>
        </div>
      )}

      {/* قانونِ کاربر (۲۰۲۶-۰۸-۰۱): این کارت overflow:'hidden' داره و فرزندِ یه ستونِ
          فلکسه — طبقِ رفتارِ استانداردِ CSS، overflow غیرِ visible یعنی min-height:0،
          پس فلکس‌باکس اجازه داره اینو تا هر اندازه له کنه تا توی فضایِ باقی‌مونده جا بشه،
          به‌جایِ اینکه اسکرولِ خودِ صفحه (overflowY:auto رویِ ریشه) فعال بشه — نتیجه:
          فقط چندتا از ۱۱ لید دیده می‌شد و اسکرول هیچ‌کاری نمی‌کرد. flexShrink:0 این
          کارت رو مجبور می‌کنه اندازه‌ی طبیعیِ خودش رو نگه داره تا اسکرولِ صفحه درست کار کنه. */}
      <div style={{ display:'flex', alignItems:'center', gap:8 }}>
        <input value={search} onChange={e => setSearch(e.target.value)} placeholder='🔍 جستجو در نام / شماره / یوزرنیم...'
          style={{ flex:1, padding:'8px 12px', borderRadius:8, border:'1px solid var(--border)', background:'var(--surface)', color:'var(--text)', fontSize:13, outline:'none' }} />
        {search && <button onClick={() => setSearch('')} style={pgBtn}>✕ پاک‌کردن</button>}
        <select value={sellerFilter} onChange={e => setSellerFilter(e.target.value)}
          style={{ padding:'8px 12px', borderRadius:8, border:'1px solid var(--border)', background:'var(--surface)', color:'var(--text)', fontSize:12, cursor:'pointer', minWidth:180 }}>
          <option value=''>همه‌یِ فروش‌یارها</option>
          {sellerOptions.map(o => <option key={o} value={o}>{o}</option>)}
        </select>
        <ShamsiDateFilterMini value={dateFrom} onChange={setDateFrom} placeholder='از تاریخ' />
        <ShamsiDateFilterMini value={dateTo} onChange={setDateTo} placeholder='تا تاریخ' />
        {(dateFrom || dateTo) && (
          <button onClick={() => { setDateFrom(''); setDateTo(''); }} style={pgBtn}>✕ پاکِ‌کردنِ تاریخ</button>
        )}
        <button onClick={() => {
          if (filteredLeads.length === 0) return toast.error('لیستی برای خروجی نیست');
          // قانونِ کاربر (۲۰۲۶-۰۸-۱۳): خروجیِ واقعیِ xlsx (نه CSVِ ساده) — از همون
          // endpointِ رسمیِ export-filtered که همه‌ی اطلاعاتِ کامل + شمسی رو می‌سازه،
          // فقط با lead_idsِ همین لیستِ فیلترشده‌ی محلی.
          fetch('/api/pool/leads/export-filtered', { method:'POST', headers:h, body: JSON.stringify({ lead_ids: filteredLeads.map(l=>l.id) }) })
            .then(res => res.blob()).then(blob => {
              const a = document.createElement('a');
              a.href = URL.createObjectURL(blob);
              a.download = `graveyard_${new Date().toISOString().slice(0,10)}.xlsx`;
              a.click();
              toast.success('فایل اکسل دانلود شد');
            }).catch(() => toast.error('خطا در ساختِ فایل'));
        }} style={smBtn('#34d399')}>📤 خروجیِ اکسل ({fa(filteredLeads.length)})</button>
      </div>

      <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8, overflow:'hidden', flexShrink:0 }}>
        <div style={{ padding:'8px 12px', borderBottom:'1px solid var(--border)', fontSize:12, fontWeight:600, display:'flex', alignItems:'center', gap:10 }}>
          <input type='checkbox' checked={filteredLeads.length > 0 && selected.size === filteredLeads.length} onChange={toggleAll} style={{ cursor:'pointer' }} title='انتخاب همه' />
          لیست قبرستان ({fa(filteredLeads.length)}{(search || reasonFilter) ? ` از ${data ? fa(data.total) : '...'}` : ''})
        </div>
        <div style={{ overflowX:'auto' }}>
          <table className='table table-compact'>
            <thead>
              <tr>
                <th style={{ width:30 }}></th>
                <th>اسم</th>
                <th>شماره</th>
                <th>پلتفرم</th>
                <th>سیستم</th>
                <th>بودجه</th>
                <th>سن</th>
                <th>لید</th>
                <th>نوع محصول</th>
                <th>امتیاز</th>
                <th>تماس</th>
                <th>آخرین نتیجه</th>
                <th>وضعیت</th>
                <th>دلیل</th>
                <th>توسطِ کی</th>
                <th>تاریخ</th>
              </tr>
            </thead>
            <tbody>
          {filteredLeads.map(lead => {
            let lastOutcome = null;
            try { const d = JSON.parse(lead.last_call_json||'null'); if (d?.outcome) lastOutcome = d.outcome; } catch {}
            const segColor = { 'گرم':'#F87171', 'ولرم':'#FBBF24', 'سرد':'#60A5FA' }[lead.novinhub_segment] || '#818CF8';
            const platformLabel = lead.platform?.startsWith('telegram') ? 'تلگرام' : lead.platform?.startsWith('bale') ? 'بله' : lead.platform==='novinhub' ? 'نوین‌هاب' : (lead.platform||'—');
            return (
            <tr key={lead.id} onClick={() => setDetailLead(lead)} style={{ background: selected.has(lead.id) ? '#1e1b3a55' : 'transparent', cursor:'pointer' }}>
              <td onClick={e => e.stopPropagation()}><input type='checkbox' checked={selected.has(lead.id)} onChange={() => toggleSel(lead.id)} style={{ cursor:'pointer' }} /></td>
              <td>
                <div style={{ fontSize:13, fontWeight:500 }}>{lead.full_name||lead.username||'ناشناس'}</div>
                {lead.username && lead.full_name && <div style={{ fontSize:12, color:'var(--text-muted)' }}>@{lead.username}</div>}
              </td>
              <td style={{ fontSize:13, fontFamily:'JetBrains Mono', color:'var(--text-muted)' }}>{lead.phone||'—'}</td>
              <td>
                <span style={{ fontSize:13, padding:'2px 8px', borderRadius:6,
                  background: lead.platform?.startsWith('telegram') ? 'rgba(41,182,246,0.15)' : lead.platform==='novinhub' ? 'rgba(52,211,153,0.15)' : 'rgba(99,102,241,0.15)',
                  color: lead.platform?.startsWith('telegram') ? '#29B6F6' : lead.platform==='novinhub' ? '#34D399' : '#818CF8' }}>
                  {platformLabel}
                </span>
              </td>
              <td style={{ fontSize:13, color:'var(--text-muted)' }}>
                {lead.novinhub_has_system!=null && lead.novinhub_has_system!==''
                  ? (lead.novinhub_has_system>0 ? 'دارد' : 'موبایل')
                  : (lead.chat_system || '—')}
              </td>
              <td style={{ fontSize:13, color:'var(--text-muted)' }}>{lead.novinhub_budget ? `${fa(lead.novinhub_budget)} میلیون` : '—'}</td>
              <td style={{ fontSize:13, color:'var(--text-muted)' }}>{lead.novinhub_age ? fa(lead.novinhub_age) : (lead.chat_age || '—')}</td>
              <td>
                {lead.novinhub_segment ? (
                  <span style={{ fontSize:13, padding:'2px 8px', borderRadius:6, background:segColor+'22', color:segColor }}>{lead.novinhub_segment}</span>
                ) : <span style={{ color:'#374151', fontSize:13 }}>—</span>}
              </td>
              <td style={{ fontSize:13, color:'var(--text-muted)' }}>{lead.novinhub_product_name || '—'}</td>
              <td>
                <span style={{ fontSize:13, fontFamily:'JetBrains Mono', fontWeight:700,
                  color: (lead.score||0)>=7?'#34D399':(lead.score||0)>=4?'#fbbf24':'#94a3b8' }}>
                  {lead.score||0}
                </span>
              </td>
              <td>
                {(lead.call_count||0) > 0 ? (
                  <span style={{ fontSize:13, padding:'3px 9px', borderRadius:6, background:'rgba(52,211,153,0.15)', color:'#34D399' }}>📞 {fa(lead.call_count)}</span>
                ) : <span style={{ color:'#374151', fontSize:13 }}>—</span>}
              </td>
              <td>
                {lastOutcome ? (
                  <span style={{ fontSize:13, padding:'2px 8px', borderRadius:6, background:(G_OUTCOME_COLOR[lastOutcome]||'#6B7280')+'18', color:G_OUTCOME_COLOR[lastOutcome]||'#6B7280' }}>
                    {G_OUTCOME_ICON[lastOutcome]} {G_OUTCOME_LABEL[lastOutcome]||lastOutcome}
                  </span>
                ) : <span style={{ color:'#374151', fontSize:13 }}>—</span>}
              </td>
              <td>
                <span style={{ fontSize:13, padding:'3px 8px', borderRadius:6, background:(STATUS_COLOR[lead.status]||'#475569')+'22', color:STATUS_COLOR[lead.status]||'#94a3b8' }}>
                  {STATUS_LABEL[lead.status]||lead.status}
                </span>
              </td>
              <td style={{ fontSize:12, color:'#f87171', maxWidth:180 }}>{lead.lost_reason || '—'}</td>
              <td style={{ fontSize:12, color:'#818cf8' }}>{lead.lost_by || '—'}</td>
              <td style={{ fontSize:11, color:'var(--text-muted)', whiteSpace:'nowrap' }}>{toShamsiTimeUTC(lead.updated_at)}</td>
            </tr>
            );
          })}
            </tbody>
          </table>
        </div>
      </div>

      {detailLead && <LeadDetailModal lead={detailLead} onClose={() => setDetailLead(null)} onRefresh={load} />}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════
//  TAB: تبدیل‌ها و analytics
// ═══════════════════════════════════════════════════════════
const AnalyticsTab = () => {
  const { fa } = window.SB_DATA;
  const { useState, useEffect } = React;
  const token = localStorage.getItem(window.TOKEN_KEY);
  const h = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };
  const api = (url, opts = {}) => fetch(url, { headers: h, ...opts }).then(r => r.json());

  const [data, setData] = useState(null);
  const [groupBy, setGroupBy] = useState('seller');
  const [period, setPeriod] = useState('30');
  const [sellerFilter, setSellerFilter] = useState(null); // {id, name} یا null

  const load = () => {
    const q = `/api/pool/analytics?period=${period}&group_by=${groupBy}` + (sellerFilter ? `&seller_id=${encodeURIComponent(sellerFilter.id)}` : '');
    api(q).then(d => { if (d.success) setData(d.data); });
  };
  useEffect(() => { load(); }, [groupBy, period, sellerFilter]);

  const GBY = [
    { v:'seller', label:'فروشنده' },{ v:'campaign', label:'کمپین' },{ v:'source', label:'منبع' },
    { v:'product', label:'محصول' },{ v:'free_course', label:'دوره رایگان' },
  ];
  const PERIODS = [{ v:'7', label:'۷ روز' },{ v:'30', label:'۳۰ روز' },{ v:'90', label:'۳ ماه' }];

  return (
    <div style={{ padding:16, overflowY:'auto', height:'100%', display:'flex', flexDirection:'column', gap:12 }}>
      {/* Controls */}
      <div style={{ display:'flex', gap:8, alignItems:'center' }}>
        <div style={{ fontSize:12, color:'var(--text-muted)' }}>گروه‌بندی:</div>
        {GBY.map(g => (
          <button key={g.v} onClick={() => setGroupBy(g.v)} style={{ padding:'4px 12px', borderRadius:6, border:'1px solid var(--border)', cursor:'pointer', fontSize:11,
            background: groupBy===g.v ? '#4f46e5' : 'transparent', color: groupBy===g.v ? 'white' : 'var(--text-muted)' }}>
            {g.label}
          </button>
        ))}
        {sellerFilter && (
          <button onClick={() => setSellerFilter(null)} style={{ padding:'4px 10px', borderRadius:6, border:'1px solid #4f46e5', cursor:'pointer', fontSize:11, background:'#4f46e520', color:'#818cf8' }}>
            فروشنده: {sellerFilter.name} ✕
          </button>
        )}
        <div style={{ marginRight:'auto', display:'flex', gap:4 }}>
          {PERIODS.map(p => (
            <button key={p.v} onClick={() => setPeriod(p.v)} style={{ padding:'4px 10px', borderRadius:6, border:'1px solid var(--border)', cursor:'pointer', fontSize:11,
              background: period===p.v ? '#1e2536' : 'transparent', color: period===p.v ? 'white' : 'var(--text-muted)' }}>
              {p.label}
            </button>
          ))}
        </div>
      </div>

      {/* Summary cards */}
      {data && (
        <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fit,minmax(120px,1fr))', gap:10 }}>
          {[
            { label:'کل تبدیل', val:fa(data.total), color:'#34d399' },
            { label:'درآمد', val: fa(Math.round((data.revenue||0)/1000))+'K', color:'#fbbf24' },
            { label:'نرخ تبدیل', val:fa(data.rate)+'%', color:'#a78bfa' },
            { label:'نرخ دوره رایگان', val:fa(data.freeCourseRate)+'%', color:'#60a5fa' },
            { label:'⚡ سرعت تماس اول', val: data.speedToLead != null ? (data.speedToLead < 24 ? fa(data.speedToLead)+'h' : fa(Math.round(data.speedToLead/24))+'d') : '—', color: data.speedToLead != null && data.speedToLead <= 4 ? '#34d399' : data.speedToLead != null && data.speedToLead <= 24 ? '#fbbf24' : '#f87171', sub: data.speedToLeadCount ? `روی ${fa(data.speedToLeadCount)} لید` : '' },
          ].map(c => (
            <div key={c.label} style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8, padding:'10px 12px' }}>
              <div style={{ fontSize:10, color:'var(--text-muted)', marginBottom:4 }}>{c.label}</div>
              <div style={{ fontSize:20, fontWeight:700, color:c.color }}>{c.val}</div>
              {c.sub && <div style={{ fontSize:10, color:'var(--text-muted)', marginTop:2 }}>{c.sub}</div>}
            </div>
          ))}
        </div>
      )}

      {/* Breakdown table */}
      {data?.breakdown?.length > 0 && (
        <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8, overflow:'hidden' }}>
          <div style={{ padding:'8px 12px', borderBottom:'1px solid var(--border)', fontSize:12, fontWeight:600 }}>
            تفکیک بر اساس {GBY.find(g=>g.v===groupBy)?.label}
          </div>
          {data.breakdown.map((row, i) => {
            const maxConv = data.breakdown[0]?.conversions || 1;
            const pct = Math.round(row.conversions / maxConv * 100);
            const clickable = groupBy === 'seller' && row.id;
            return (
              <div key={i} onClick={clickable ? () => setSellerFilter({ id: row.id, name: row.name || 'نامشخص' }) : undefined}
                style={{ padding:'10px 12px', borderBottom:'1px solid var(--border)', cursor: clickable ? 'pointer' : 'default' }}>
                <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:5 }}>
                  <div style={{ flex:1, fontSize:12, fontWeight:500 }}>{row.name||'نامشخص'}</div>
                  <div style={{ fontSize:13, fontWeight:700, color:'#34d399' }}>{fa(row.conversions)} تبدیل</div>
                  {row.revenue > 0 && <div style={{ fontSize:11, color:'#fbbf24' }}>{fa(Math.round(row.revenue/1000))}K</div>}
                  {row.avg_days != null && <div style={{ fontSize:10, color:'var(--text-muted)' }}>{fa(Math.round(row.avg_days))} روز</div>}
                </div>
                <div style={{ height:4, background:'var(--bg)', borderRadius:2, overflow:'hidden' }}>
                  <div style={{ height:'100%', width:pct+'%', background:'#4f46e5', borderRadius:2, transition:'width 0.3s' }} />
                </div>
              </div>
            );
          })}
        </div>
      )}

      {/* تبدیل به تفکیک منبع/پلتفرم */}
      {data?.bySource?.length > 0 && groupBy !== 'source' && (
        <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8, overflow:'hidden' }}>
          <div style={{ padding:'8px 12px', borderBottom:'1px solid var(--border)', fontSize:12, fontWeight:600 }}>
            📡 تبدیل به تفکیک منبع ورود
          </div>
          {data.bySource.map((row, i) => {
            const maxConv = data.bySource[0]?.conversions || 1;
            const pct = Math.round(row.conversions / maxConv * 100);
            // قانونِ کاربر (۲۰۲۶-۰۸-۱۳): بک‌اند دیگه کدهایِ خامِ platform (telegram/bale/manual)
            // برنمی‌گردونه — رشته‌هایِ فارسیِ آماده (مثلِ «ربات - تلگرام»/«دستی - بله») یا
            // متنِ خامِ شیوه‌یِ آشنایی رو می‌فرسته؛ فقط پلتفرم‌هایِ بدونِ ابهام (novinhub/
            // rubika/instagram/eitaa) هنوز کدِ خام‌ان و نیاز به ترجمه دارن.
            const PLAT = { 'تلگرام (ربات)':'✈️', 'بله (ربات)':'💬', 'تلگرام (دستی)':'✈️', 'بله (دستی)':'💬', rubika:'🔵', instagram:'📷', eitaa:'🟢', novinhub:'📌' };
            const PLAT_LABEL = { rubika:'روبیکا', instagram:'اینستاگرام', eitaa:'ایتا', novinhub:'نوین‌هاب' };
            return (
              <div key={i} style={{ padding:'8px 12px', borderBottom:'1px solid var(--border)' }}>
                <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:4 }}>
                  <div style={{ flex:1, fontSize:12, fontWeight:500 }}>
                    {PLAT[row.name]||'📡'} {PLAT_LABEL[row.name] || row.name || 'نامشخص'}
                  </div>
                  <div style={{ fontSize:13, fontWeight:700, color:'#34d399' }}>{fa(row.conversions)} تبدیل</div>
                  {row.revenue > 0 && <div style={{ fontSize:11, color:'#fbbf24' }}>{fa(Math.round(row.revenue/1000))}K</div>}
                </div>
                <div style={{ height:3, background:'var(--bg)', borderRadius:2, overflow:'hidden' }}>
                  <div style={{ height:'100%', width:pct+'%', background:'#a78bfa', borderRadius:2, transition:'width 0.3s' }} />
                </div>
              </div>
            );
          })}
        </div>
      )}

      {/* Daily trend */}
      {data?.daily && (
        <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8, padding:12 }}>
          <div style={{ fontSize:12, fontWeight:600, marginBottom:10 }}>روند ۷ روز اخیر</div>
          <div style={{ display:'flex', gap:8, alignItems:'flex-end', height:60 }}>
            {data.daily.map(d => {
              const max = Math.max(...data.daily.map(x=>x.conversions), 1);
              const h = Math.round((d.conversions/max)*100);
              return (
                <div key={d.date} style={{ flex:1, display:'flex', flexDirection:'column', alignItems:'center', gap:4 }}>
                  <div style={{ fontSize:9, color:'#34d399' }}>{fa(d.conversions)}</div>
                  <div style={{ width:'100%', background:'#4f46e5', borderRadius:'3px 3px 0 0', height: h+'%', minHeight: d.conversions>0?4:1 }} />
                  <div style={{ fontSize:8, color:'var(--text-muted)' }}>{d.date.slice(5)}</div>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
};

// ═══════════════════════════════════════════════════════════
//  Lead Detail Modal
// ═══════════════════════════════════════════════════════════
const LeadDetailModal = ({ lead, onClose, onRefresh }) => {
  const { Icon, Button, Modal, useToast } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const { useState, useEffect } = React;
  const toast = useToast();
  const token = localStorage.getItem(window.TOKEN_KEY);
  const h = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };
  const api = (url, opts = {}) => fetch(url, { headers: h, ...opts }).then(r => r.json());

  const [detail, setDetail] = useState(null);
  // قانونِ کاربر (۲۰۲۶-۰۸-۰۲): اگه این لید «درخواستِ مجدد»ه (شماره/یوزرنیمِ مشترک با یه
  // پروفایلِ پیشرفته‌تر)، سابقه‌ی اون پروفایل رو هم می‌کشیم تا فروشنده/ادمین بدونِ نیاز
  // به گشتن، مشاور/محصول/تاریخِ مشاوره‌ی قبلی رو همینجا ببینه.
  const [priorHistory, setPriorHistory] = useState(null);
  const [tags, setTags] = useState([]);
  const [newTag, setNewTag] = useState('');
  const [editing, setEditing] = useState(false);
  const [editName, setEditName] = useState(lead.full_name || '');
  const [editPhone, setEditPhone] = useState(lead.phone || '');
  const [editSegment, setEditSegment] = useState(lead.novinhub_segment || '');
  const [editSystem, setEditSystem] = useState(lead.novinhub_has_system ?? '');
  const [editBudget, setEditBudget] = useState(lead.novinhub_budget ?? '');
  const [editProduct, setEditProduct] = useState(lead.product_id || '');
  const [editAge, setEditAge] = useState(lead.novinhub_age ?? '');
  const [editSource, setEditSource] = useState(lead.source || '');
  const [editSourceCustom, setEditSourceCustom] = useState(false);
  const [editInterest, setEditInterest] = useState(lead.interest || '');
  const [products, setProducts] = useState([]);
  const [saving, setSaving] = useState(false);

  const SOURCE_OPTIONS = ['تلگرام', 'بله', 'اینستاگرام', 'ایتا'];

  const loadDetail = () => {
    api(`/api/leads/${lead.id}`).then(d => { if (d.success) setDetail(d.data); });
  };

  useEffect(() => {
    loadDetail();
    api(`/api/pool/leads/${lead.id}/tags`).then(d => { if (d.success) setTags(d.data.tags); });
    api('/api/market/products').then(d => { if (d.success) setProducts((d.data.products || []).filter(p => p.is_active !== 0)); }).catch(() => {});
    api(`/api/leads/${lead.id}/prior-history`).then(d => { if (d.success) setPriorHistory(d.data); });
  }, [lead.id]);

  // نمایش همیشه بر اساسِ آخرین دیتای واقعیِ دریافت‌شده از سرور باشه، نه پراپِ اولیه‌ی lead که بعدِ ذخیره آپدیت نمی‌شه
  const displayLead = detail?.lead || lead;

  const saveEdit = async () => {
    setSaving(true);
    try {
      const r = await api(`/api/leads/${lead.id}`, { method:'PUT', body: JSON.stringify({
        full_name: editName.trim(), phone: editPhone.trim(),
        novinhub_segment: editSegment || null,
        novinhub_has_system: editSystem === '' ? null : Number(editSystem),
        novinhub_budget: editBudget === '' ? null : Number(editBudget),
        product_id: editProduct || null,
        novinhub_age: editAge === '' ? null : Number(editAge),
        source: editSource || null,
        interest: editInterest.trim() || null,
      }) });
      if (r.success) { toast('✅ ذخیره شد', 'success'); setEditing(false); loadDetail(); onRefresh && onRefresh(); }
      else toast(r.message || 'خطا در ذخیره', 'error');
    } catch { toast('خطای شبکه', 'error'); }
    setSaving(false);
  };

  const addTag = async () => {
    if (!newTag.trim()) return;
    await api(`/api/pool/leads/${lead.id}/tags`, { method:'POST', body: JSON.stringify({ tag: newTag.trim() }) });
    setNewTag('');
    api(`/api/pool/leads/${lead.id}/tags`).then(d => { if (d.success) setTags(d.data.tags); });
  };

  const removeTag = async (tag) => {
    await api(`/api/pool/leads/${lead.id}/tags/${encodeURIComponent(tag)}`, { method:'DELETE' });
    setTags(t => t.filter(x => x.tag !== tag));
  };

  const STATUS_COLOR = { new:'#60a5fa',follow_up:'#94a3b8',cold:'#64748b',warm:'#fbbf24',hot:'#f87171',interested:'#fb923c',scheduled:'#a78bfa',buyer:'#34d399',lost:'#475569',cancelled:'#374151',bad_number:'#1f2937' };

  return (
    <Modal open={true} onClose={onClose} title={displayLead.full_name || displayLead.username || displayLead.id}>
      <div style={{ minWidth:480, maxHeight:'80vh', overflowY:'auto' }}>

        {/* ویرایش نام/شماره */}
        <div style={{ marginBottom:12 }}>
          {editing ? (
            <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
              <div style={{ display:'flex', gap:6, alignItems:'center' }}>
                <input value={editName} onChange={e => setEditName(e.target.value)} placeholder='نام کامل' style={{ ...selStyle, flex:1 }} />
                <input value={editPhone} onChange={e => setEditPhone(e.target.value)} placeholder='شماره تماس' style={{ ...selStyle, flex:1 }} />
              </div>
              <div style={{ display:'flex', gap:6, alignItems:'center' }}>
                <select value={editSegment} onChange={e => setEditSegment(e.target.value)} style={{ ...selStyle, flex:1 }}>
                  <option value=''>— سگمنت نامشخص —</option>
                  <option value='گرم'>گرم</option>
                  <option value='ولرم'>ولرم</option>
                  <option value='سرد'>سرد</option>
                </select>
                <select value={editSystem} onChange={e => setEditSystem(e.target.value)} style={{ ...selStyle, flex:1 }}>
                  <option value=''>— سیستم نامشخص —</option>
                  <option value='1'>✅ دارد</option>
                  <option value='0'>📱 فقط موبایل</option>
                  <option value='-1'>❌ ندارد</option>
                </select>
              </div>
              <div style={{ display:'flex', gap:6, alignItems:'center' }}>
                <input value={editBudget} onChange={e => setEditBudget(e.target.value)} placeholder='بودجه (تومان)' type='number' style={{ ...selStyle, flex:1 }} />
                <select value={editProduct} onChange={e => setEditProduct(e.target.value)} style={{ ...selStyle, flex:1 }}>
                  <option value=''>— بدون محصول —</option>
                  {products.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
                </select>
              </div>
              <div style={{ display:'flex', gap:6, alignItems:'center' }}>
                <input value={editAge} onChange={e => setEditAge(e.target.value)} placeholder='سن' type='number' style={{ ...selStyle, flex:1 }} />
                {editSourceCustom ? (
                  <input value={editSource} onChange={e => setEditSource(e.target.value)} placeholder='شیوه آشنایی (دستی)' style={{ ...selStyle, flex:1 }} />
                ) : (
                  <select value={SOURCE_OPTIONS.includes(editSource) ? editSource : ''} onChange={e => {
                    if (e.target.value === '__custom__') { setEditSourceCustom(true); setEditSource(''); }
                    else setEditSource(e.target.value);
                  }} style={{ ...selStyle, flex:1 }}>
                    <option value=''>— شیوه آشنایی نامشخص —</option>
                    {SOURCE_OPTIONS.map(s => <option key={s} value={s}>{s}</option>)}
                    <option value='__custom__'>✏️ وارد کردن دستی...</option>
                  </select>
                )}
              </div>
              <div style={{ display:'flex', gap:6, alignItems:'center' }}>
                <input value={editInterest} onChange={e => setEditInterest(e.target.value)} placeholder='علاقه/هدف' style={{ ...selStyle, flex:1 }} />
              </div>
              <div style={{ display:'flex', gap:6, justifyContent:'flex-end' }}>
                <Button size='sm' kind='primary' onClick={saveEdit} disabled={saving}>{saving ? '...' : 'ذخیره'}</Button>
                <Button size='sm' variant='ghost' onClick={() => {
                  setEditing(false); setEditName(displayLead.full_name||''); setEditPhone(displayLead.phone||'');
                  setEditSegment(displayLead.novinhub_segment||''); setEditSystem(displayLead.novinhub_has_system ?? '');
                  setEditBudget(displayLead.novinhub_budget ?? ''); setEditProduct(displayLead.product_id||'');
                  setEditAge(displayLead.novinhub_age ?? ''); setEditSource(displayLead.source||'');
                  setEditSourceCustom(!!displayLead.source && !SOURCE_OPTIONS.includes(displayLead.source));
                  setEditInterest(displayLead.interest||'');
                }}>انصراف</Button>
              </div>
            </div>
          ) : (
            <Button size='sm' variant='ghost' icon='edit' onClick={() => {
              setEditName(displayLead.full_name||''); setEditPhone(displayLead.phone||'');
              setEditSegment(displayLead.novinhub_segment||''); setEditSystem(displayLead.novinhub_has_system ?? '');
              setEditBudget(displayLead.novinhub_budget ?? ''); setEditProduct(displayLead.product_id||'');
              setEditAge(displayLead.novinhub_age ?? ''); setEditSource(displayLead.source||'');
              setEditSourceCustom(!!displayLead.source && !SOURCE_OPTIONS.includes(displayLead.source));
              setEditInterest(displayLead.interest||'');
              setEditing(true);
            }}>✏️ ویرایش نام/شماره/سگمنت/سیستم</Button>
          )}
        </div>

        {/* قانونِ کاربر (۲۰۲۶-۰۸-۰۲): پنلِ «درخواستِ مجدد» — فقط وقتی این لید شماره/یوزرنیمِ
            مشترک با یه پروفایلِ پیشرفته‌تر (خریدار/مشاوره‌شده/زمان‌بندی‌شده) داره. */}
        {priorHistory?.found && (
          <div style={{ background:'rgba(96,165,250,0.1)', border:'1px solid rgba(96,165,250,0.3)', borderRadius:8, padding:12, marginBottom:12 }}>
            <div style={{ fontSize:12, fontWeight:700, color:'#60A5FA', marginBottom:8 }}>
              🔁 درخواستِ مجدد — این شخص قبلاً تحتِ نامِ «{priorHistory.full_name || 'بدونِ نام'}» سابقه داشته
            </div>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:6, fontSize:11.5 }}>
              <div><span style={{ color:'var(--text-muted)' }}>وضعیتِ قبلی: </span>{{ buyer:'💰 خریدار', consultation:'🗣 مشاوره‌شده', scheduled:'📅 زمان‌بندی‌شده' }[priorHistory.status] || priorHistory.status}</div>
              <div><span style={{ color:'var(--text-muted)' }}>مشاور/فروشنده: </span>{priorHistory.seller_name || '—'}</div>
              <div><span style={{ color:'var(--text-muted)' }}>محصول: </span>{priorHistory.product_name || '—'}</div>
              <div><span style={{ color:'var(--text-muted)' }}>مبلغِ فروش: </span>{priorHistory.sale_amount ? fa(priorHistory.sale_amount) + ' تومان' : '—'}</div>
              <div><span style={{ color:'var(--text-muted)' }}>تخفیف: </span>{priorHistory.discount_amount ? fa(priorHistory.discount_amount) + ' تومان' : '—'}</div>
              <div><span style={{ color:'var(--text-muted)' }}>روشِ پرداخت: </span>{{ cash:'نقدی', installment:'اقساط', card:'کارت', transfer:'انتقال بانکی' }[priorHistory.pay_method] || priorHistory.pay_method || '—'}</div>
              <div><span style={{ color:'var(--text-muted)' }}>زمانِ مشاوره: </span>{priorHistory.consultation_at ? toShamsiTimeUTC(priorHistory.consultation_at) : '—'}</div>
              <div><span style={{ color:'var(--text-muted)' }}>آخرین تماس: </span>{priorHistory.last_call_at ? toShamsiTimeUTC(priorHistory.last_call_at) : '—'}</div>
              {priorHistory.last_call_note && (
                <div style={{ gridColumn:'1 / -1' }}><span style={{ color:'var(--text-muted)' }}>آخرین یادداشتِ تماس: </span>{priorHistory.last_call_note}</div>
              )}
            </div>
          </div>
        )}

        {/* سربرگ اطلاعات */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:8, marginBottom:12 }}>
          {[
            { label:'وضعیت', val: <span style={{ color:STATUS_COLOR[displayLead.status]||'#94a3b8' }}>{displayLead.status}</span> },
            { label:'امتیاز', val: fa(displayLead.score||0) },
            { label:'پلتفرم', val: displayLead.platform },
            { label:'شماره', val: displayLead.phone||'—' },
            { label:'نوع سگمنت', val: displayLead.novinhub_segment || '—' },
            { label:'سیستم', val: displayLead.novinhub_has_system!=null && displayLead.novinhub_has_system!==''
                ? (Number(displayLead.novinhub_has_system)>0 ? '✅ دارد' : '📱 موبایل') : '—' },
            { label:'بودجه', val: displayLead.novinhub_budget ? fa(displayLead.novinhub_budget) + ' تومان' : '—' },
            { label:'نوع محصول', val: products.find(p => p.id === displayLead.product_id)?.name || displayLead.novinhub_product_name || '—' },
            { label:'سن', val: displayLead.novinhub_age ? fa(displayLead.novinhub_age) : '—' },
            { label:'شیوه آشنایی', val: displayLead.source || '—' },
            { label:'علاقه/هدف', val: displayLead.interest || '—' },
            { label:'یونیت', val: displayLead.unit||'market' },
            { label:'مالک فعال', val: displayLead.active_owner||<span style={{color:'#475569'}}>آزاد</span> },
            { label:'تاریخ ثبت', val: displayLead.created_at ? toShamsiTimeUTC(displayLead.created_at) : '—' },
            ...(displayLead.lost_reason || displayLead.lost_by ? [
              { label:'دلیلِ کنسلی/ازدست‌رفتن', val: <span style={{ color:'#f87171' }}>{displayLead.lost_reason || '—'}</span> },
              { label:'توسطِ کی', val: <span style={{ color:'#818cf8' }}>{displayLead.lost_by || '—'}</span> },
            ] : []),
          ].map(item => (
            <div key={item.label} style={{ background:'var(--bg)', borderRadius:6, padding:'6px 10px' }}>
              <div style={{ fontSize:10, color:'var(--text-muted)', marginBottom:2 }}>{item.label}</div>
              <div style={{ fontSize:12, fontWeight:500 }}>{item.val}</div>
            </div>
          ))}
        </div>

        {/* تگ‌ها */}
        <div style={{ marginBottom:12 }}>
          <div style={{ fontSize:11, fontWeight:600, marginBottom:6 }}>تگ‌ها</div>
          <div style={{ display:'flex', flexWrap:'wrap', gap:5, marginBottom:8 }}>
            {tags.map(t => (
              <span key={t.tag} style={{ fontSize:10, padding:'2px 8px', borderRadius:10, background:t.tag_color+'22', color:t.tag_color, display:'flex', alignItems:'center', gap:4 }}>
                {t.tag_icon} {t.tag}
                <button onClick={() => removeTag(t.tag)} style={{ background:'none', border:'none', cursor:'pointer', color:t.tag_color, fontSize:12, padding:0, lineHeight:1 }}>×</button>
              </span>
            ))}
            {tags.length === 0 && <span style={{ fontSize:11, color:'var(--text-muted)' }}>بدون تگ</span>}
          </div>
          <div style={{ display:'flex', gap:6 }}>
            <input value={newTag} onChange={e => setNewTag(e.target.value)} onKeyDown={e => e.key==='Enter'&&addTag()}
              placeholder='تگ جدید...' style={{ ...selStyle, flex:1 }} />
            <Button size='sm' variant='ghost' onClick={addTag}>+ افزودن</Button>
          </div>
        </div>

        {/* کل فعالیت — همه‌ی lead_events (نه فقط تماس)، برایِ تبِ قبرستان مهمه که دلیل/روندِ کامل دیده بشه */}
        {detail?.events?.length > 0 && (
          <div style={{ marginBottom:12 }}>
            <div style={{ fontSize:11, fontWeight:600, marginBottom:6 }}>کل فعالیت ({fa(detail.events.length)})</div>
            <div style={{ maxHeight:260, overflowY:'auto', display:'flex', flexDirection:'column', gap:5 }}>
              {detail.events.map(ev => {
                const EVENT_LABEL = { call:'📞 تماس', refer:'↪️ ارجاع', status_change:'🔀 تغییرِ وضعیت', note:'📝 یادداشت', activity:'📌 فعالیت' };
                let line = null;
                if (ev.event_type === 'status_change') {
                  line = <span>{ev.old_value || '—'} ← {ev.new_value || '—'}</span>;
                } else if (ev.event_type === 'call') {
                  const OUTCOME = { answered:'جواب داد',no_answer:'جواب نداد',sold:'فروخته شد',follow_up:'پیگیری',not_interested:'علاقه ندارد',cancelled:'کنسل',call_later:'بعداً',scheduled:'وقت گرفت',bad_number:'شماره اشتباه' };
                  line = <span>{OUTCOME[ev.parsed?.outcome] || ev.parsed?.outcome || '—'}{ev.parsed?.note ? ` — ${ev.parsed.note}` : ''}</span>;
                } else if (ev.event_type === 'refer') {
                  line = <span>ارجاع به {ev.parsed?.seller_name || '—'}{ev.parsed?.reason ? ` — ${ev.parsed.reason}` : ''}</span>;
                } else if (ev.parsed?.title) {
                  line = <span>{ev.parsed.title}</span>;
                } else {
                  line = <span>{ev.new_value || '—'}</span>;
                }
                return (
                  <div key={ev.id} style={{ padding:'6px 10px', background:'var(--bg)', borderRadius:6, display:'flex', gap:8, alignItems:'flex-start' }}>
                    <div style={{ flex:1 }}>
                      <div style={{ fontSize:10, color:'var(--text-muted)', marginBottom:2 }}>
                        {EVENT_LABEL[ev.event_type] || ev.event_type}{ev.seller_name ? ` — ${ev.seller_name}` : ''}
                      </div>
                      <div style={{ fontSize:11.5 }}>{line}</div>
                    </div>
                    <div style={{ fontSize:9, color:'var(--text-muted)', whiteSpace:'nowrap' }}>{ev.created_at ? toShamsi(ev.created_at) : ''}</div>
                  </div>
                );
              })}
            </div>
          </div>
        )}

        {/* تاریخچه تماس */}
        {detail?.callLogs?.length > 0 && (
          <div>
            <div style={{ fontSize:11, fontWeight:600, marginBottom:6 }}>تاریخچه تماس</div>
            {detail.callLogs.slice(0,5).map((log, i) => {
              const OUTCOME = { answered:'جواب داد',no_answer:'جواب نداد',sold:'فروخته شد',follow_up:'پیگیری',not_interested:'علاقه ندارد',cancelled:'کنسل',call_later:'بعداً',scheduled:'وقت گرفت',bad_number:'شماره اشتباه' };
              return (
                <div key={i} style={{ padding:'6px 10px', background:'var(--bg)', borderRadius:6, marginBottom:5, display:'flex', gap:8, alignItems:'flex-start' }}>
                  <div style={{ flex:1 }}>
                    <div style={{ fontSize:11 }}>{OUTCOME[log.outcome]||log.outcome||'—'}{log.seller_name && <span style={{ color:'var(--text-muted)', fontSize:10 }}> — {log.seller_name}</span>}</div>
                    {log.note && <div style={{ fontSize:10, color:'var(--text-muted)', marginTop:2 }}>{log.note}</div>}
                  </div>
                  <div style={{ fontSize:9, color:'var(--text-muted)', whiteSpace:'nowrap' }}>{log.created_at ? toShamsi(log.created_at) : ''}</div>
                </div>
              );
            })}
          </div>
        )}
      </div>
    </Modal>
  );
};

// ─── Shared styles ────────────────────────────────────────
const selStyle = {
  width:'100%', padding:'6px 8px', borderRadius:6, border:'1px solid var(--border)',
  background:'var(--bg)', color:'var(--text)', fontSize:13, outline:'none', boxSizing:'border-box',
};
const pgBtn = {
  padding:'4px 12px', borderRadius:6, border:'1px solid var(--border)', background:'transparent',
  color:'var(--text-muted)', fontSize:12, cursor:'pointer',
};
const smBtn = (color) => ({
  padding:'3px 10px', borderRadius:6, border:`1px solid ${color}22`, background:`${color}11`,
  color, fontSize:10, cursor:'pointer',
});

// ═══════════════════════════════════════════════════════════
//  TAB: قوانین وضعیت (سرد / گرم / داغ) — متن آزاد برای AI
// ═══════════════════════════════════════════════════════════
const LP_RULE_TYPES = [
  { id: 'cold', label: 'سرد',  color: '#94A3B8', bg: 'rgba(148,163,184,0.08)', icon: '❄️',
    hint: 'مثال: بیش از ۳ بار بی‌پاسخ بوده / بیشتر از ۱۴ روز از تماس آخر گذشته / در مکالمه گفت بودجه ندارد' },
  { id: 'warm', label: 'گرم',  color: '#FB923C', bg: 'rgba(251,146,60,0.08)',  icon: '🌡️',
    hint: 'مثال: جواب داده و سوال پرسیده / شماره داده / یک دوره رایگان دیده / گفت در نظر دارد' },
  { id: 'hot',  label: 'داغ',  color: '#F87171', bg: 'rgba(248,113,113,0.08)', icon: '🔥',
    hint: 'مثال: گفت آماده پرداخته / سیستم دارد و بودجه دارد / سه دوره رایگان دیده / خودش دوباره پیام داده' },
];

const StatusRulesTab = () => {
  const { Icon } = window.SB_UI;
  const { fa } = window.SB_DATA;
  const { useState, useEffect } = React;
  const token = localStorage.getItem(window.TOKEN_KEY);
  const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };

  const [rules, setRules] = useState([]);
  const [inputs, setInputs] = useState({ cold: '', warm: '', hot: '' });
  const [editId, setEditId] = useState(null);
  const [editText, setEditText] = useState('');

  const load = () => {
    fetch('/api/rules', { headers: { Authorization: `Bearer ${token}` } })
      .then(r => r.json())
      .then(d => { if (d.success) setRules(d.data?.rules || []); });
  };
  useEffect(() => { load(); }, []);

  const add = (type) => {
    const text = inputs[type]?.trim();
    if (!text) return;
    fetch('/api/rules', { method: 'POST', headers, body: JSON.stringify({ type, text }) })
      .then(r => r.json()).then(d => {
        if (d.success) { setInputs(p => ({ ...p, [type]: '' })); load(); }
      });
  };

  const toggle = (rule) => {
    fetch(`/api/rules/${rule.id}`, { method: 'PUT', headers, body: JSON.stringify({ is_active: rule.is_active ? 0 : 1 }) })
      .then(() => load());
  };

  const remove = (id) => {
    if (!confirm('حذف شود؟')) return;
    fetch(`/api/rules/${id}`, { method: 'DELETE', headers }).then(() => load());
  };

  const saveEdit = (id) => {
    if (!editText.trim()) return;
    fetch(`/api/rules/${id}`, { method: 'PUT', headers, body: JSON.stringify({ text: editText }) })
      .then(() => { setEditId(null); load(); });
  };

  return (
    <div style={{ padding:16, overflowY:'auto', height:'100%' }}>
      <div style={{ padding: '10px 14px', borderRadius: 8, background: 'rgba(99,102,241,0.08)', borderRight: '3px solid #818CF8', marginBottom: 16, fontSize: 12, color: '#94a3b8', lineHeight: 1.7, maxWidth: 720 }}>
        این قوانین رو AI موقع تحلیل هر تماس می‌خونه و وضعیت لید (سرد / گرم / داغ) رو تعیین می‌کنه.
        می‌تونی هر شرطی بنویسی — رفتار در مکالمه، تعداد تماس، بودجه، سیستم، دوره‌های دیده‌شده و...
      </div>

      <div style={{ display:'flex', flexDirection:'column', gap:28, maxWidth: 720 }}>
        {LP_RULE_TYPES.map(t => {
          const items = rules.filter(r => r.type === t.id);
          return (
            <div key={t.id}>
              {/* هدر بخش */}
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderRadius: 10, background: t.bg, border: `1px solid ${t.color}25`, marginBottom: 12 }}>
                <span style={{ fontSize: 20 }}>{t.icon}</span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 700, fontSize: 14, color: t.color }}>{t.label}</div>
                  <div style={{ fontSize: 11, color: '#475569', marginTop: 2 }}>{t.hint}</div>
                </div>
                <span style={{ fontSize: 11, color: t.color, opacity: 0.7, fontFamily: 'JetBrains Mono' }}>{fa(items.filter(r => r.is_active).length)} فعال</span>
              </div>

              {/* لیست قوانین */}
              <div style={{ display:'flex', flexDirection:'column', gap:6, marginBottom: 10 }}>
                {items.length === 0 && (
                  <div style={{ padding: '12px 14px', color: '#374151', fontSize: 12, textAlign: 'center', borderRadius: 8, border: '1px dashed rgba(255,255,255,0.07)' }}>
                    هنوز قانونی تعریف نشده
                  </div>
                )}
                {items.map(r => (
                  <div key={r.id} style={{
                    padding: '9px 12px', borderRadius: 8,
                    background: r.is_active ? t.bg : 'rgba(255,255,255,0.02)',
                    border: `1px solid ${r.is_active ? t.color + '20' : 'rgba(255,255,255,0.05)'}`,
                    opacity: r.is_active ? 1 : 0.4,
                  }}>
                    {editId === r.id ? (
                      <div style={{ display:'flex', gap:8 }}>
                        <input value={editText} onChange={e => setEditText(e.target.value)}
                          onKeyDown={e => { if (e.key === 'Enter') saveEdit(r.id); if (e.key === 'Escape') setEditId(null); }}
                          autoFocus style={{ flex: 1, background: 'rgba(255,255,255,0.08)', border: '1px solid rgba(255,255,255,0.15)', borderRadius: 6, padding: '5px 10px', color: '#e2e8f0', fontSize: 13, outline: 'none', direction: 'rtl' }} />
                        <button onClick={() => saveEdit(r.id)} className="icon-btn" style={{ width: 26, height: 26, color: '#34D399' }}><Icon name="check" size={12} /></button>
                        <button onClick={() => setEditId(null)} className="icon-btn" style={{ width: 26, height: 26 }}><Icon name="x" size={12} /></button>
                      </div>
                    ) : (
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                        <div style={{ width: 6, height: 6, borderRadius: '50%', background: r.is_active ? t.color : '#374151', flexShrink: 0 }} />
                        <span style={{ flex: 1, fontSize: 13, lineHeight: 1.6, color: r.is_active ? '#e2e8f0' : '#475569' }}>{r.text}</span>
                        <div style={{ display: 'flex', gap: 2 }}>
                          <button onClick={() => { setEditId(r.id); setEditText(r.text); }} className="icon-btn" style={{ width: 24, height: 24 }}><Icon name="pencil" size={11} /></button>
                          <button onClick={() => toggle(r)} className="icon-btn" style={{ width: 24, height: 24, color: r.is_active ? '#34D399' : '#475569' }}>
                            <Icon name={r.is_active ? 'toggle-right' : 'toggle-left'} size={13} />
                          </button>
                          <button onClick={() => remove(r.id)} className="icon-btn" style={{ width: 24, height: 24, color: '#F87171' }}><Icon name="trash-2" size={11} /></button>
                        </div>
                      </div>
                    )}
                  </div>
                ))}
              </div>

              {/* ورودی قانون جدید */}
              <div style={{ display: 'flex', gap: 8 }}>
                <input
                  value={inputs[t.id] || ''}
                  onChange={e => setInputs(p => ({ ...p, [t.id]: e.target.value }))}
                  onKeyDown={e => e.key === 'Enter' && add(t.id)}
                  placeholder={`قانون جدید برای ${t.label}...`}
                  style={{ flex: 1, background: 'rgba(255,255,255,0.04)', border: `1px solid ${t.color}25`, borderRadius: 8, padding: '8px 12px', color: '#e2e8f0', fontSize: 13, outline: 'none', direction: 'rtl' }}
                />
                <button onClick={() => add(t.id)} style={{ padding: '8px 14px', borderRadius: 8, background: t.bg, border: `1px solid ${t.color}30`, color: t.color, cursor: 'pointer', fontSize: 13, fontWeight: 600 }}>
                  + افزودن
                </button>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
};

// ═══════════════════════════════════════════════════════════
//  TAB: گزارش برگشتی‌ها
// ═══════════════════════════════════════════════════════════
const ReturnReportTab = () => {
  const { useState, useEffect } = React;
  const { fa } = window.SB_DATA;
  const token = localStorage.getItem(window.TOKEN_KEY);
  const h = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };

  const [days,    setDays]    = useState(30);
  const [data,    setData]    = useState(null);
  const [loading, setLoading] = useState(true);
  const [expand,  setExpand]  = useState(null);

  const load = (d) => {
    setLoading(true);
    fetch(`/api/pool/return-report?days=${d}`, { headers: h })
      .then(r => r.json())
      .then(res => { if (res.success) setData(res.data); })
      .finally(() => setLoading(false));
  };
  useEffect(() => { load(days); }, [days]);

  const autoCount   = data?.summary?.find(s => s.action === 'auto_returned')?.cnt || 0;
  const manualCount = (data?.summary?.find(s => s.action === 'returned')?.cnt || 0)
                    + (data?.summary?.find(s => s.action === 'return')?.cnt   || 0);

  const sellerMap = {};
  (data?.bySeller || []).forEach(row => {
    if (!sellerMap[row.seller_id]) sellerMap[row.seller_id] = { id: row.seller_id, name: row.seller_name || row.seller_id, auto: 0, manual: 0, last: '' };
    const s = sellerMap[row.seller_id];
    if (row.action === 'auto_returned') s.auto += row.cnt;
    else s.manual += row.cnt;
    if (row.last_at > s.last) s.last = row.last_at;
  });
  const sellers = Object.values(sellerMap).sort((a, b) => (b.manual + b.auto) - (a.manual + a.auto));

  const ACTION_LABEL = { auto_returned: 'خودکار (قانون)', returned: 'دستی توسط ادمین', return: 'دستی از CRM' };

  return (
    <div style={{ padding: '16px 20px', display: 'flex', flexDirection: 'column', gap: 14, height: '100%', overflowY: 'auto' }}>

      <div style={{ display:'flex', alignItems:'center', gap:10, flexWrap:'wrap' }}>
        <div style={{ flex:1 }}>
          <div style={{ fontSize:14, fontWeight:700, color:'#e2e8f0' }}>↩️ گزارش برگشتی‌ها</div>
          <div style={{ fontSize:11, color:'#64748b', marginTop:2 }}>تفکیک برگشت قانونی (سیستم) از برگشت خارج از قوانین (دستی)</div>
        </div>
        <div style={{ display:'flex', gap:4 }}>
          {[7, 14, 30, 60].map(d => (
            <button key={d} onClick={() => setDays(d)} style={{ padding:'4px 12px', borderRadius:6, fontSize:11, cursor:'pointer', border:'none',
              background: days===d ? '#6366F1' : 'rgba(255,255,255,0.06)', color: days===d ? '#fff' : '#64748b' }}>
              {fa(d)} روز
            </button>
          ))}
        </div>
      </div>

      {loading ? (
        <div style={{ padding:40, textAlign:'center', color:'#374151' }}>در حال بارگذاری...</div>
      ) : (
        <React.Fragment>
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
            <div style={{ padding:'12px 16px', borderRadius:10, background:'rgba(100,116,139,0.08)', border:'1px solid rgba(100,116,139,0.2)' }}>
              <div style={{ fontSize:11, color:'#64748b', marginBottom:4 }}>برگشت قانونی (سیستم)</div>
              <div style={{ fontSize:26, fontWeight:800, color:'#94a3b8' }}>{fa(autoCount)}</div>
              <div style={{ fontSize:10, color:'#475569', marginTop:2 }}>انقضا، بی‌پاسخی، راکد، کنسل</div>
            </div>
            <div style={{ padding:'12px 16px', borderRadius:10, background: manualCount>0?'rgba(245,158,11,0.1)':'rgba(52,211,153,0.07)', border:`1px solid ${manualCount>0?'rgba(245,158,11,0.3)':'rgba(52,211,153,0.2)'}` }}>
              <div style={{ fontSize:11, color: manualCount>0?'#F59E0B':'#64748b', marginBottom:4 }}>برگشت دستی (خارج از قوانین)</div>
              <div style={{ fontSize:26, fontWeight:800, color: manualCount>0?'#F59E0B':'#34D399' }}>{fa(manualCount)}</div>
              <div style={{ fontSize:10, color:'#475569', marginTop:2 }}>
                {manualCount>0 ? 'توسط ادمین برگشت داده شده — نیاز به بررسی' : 'بدون دخالت دستی ✅'}
              </div>
            </div>
          </div>

          {sellers.length === 0 ? (
            <div style={{ padding:32, textAlign:'center', color:'#374151', fontSize:12 }}>
              هیچ برگشتی در {fa(days)} روز گذشته ثبت نشده
            </div>
          ) : (
            <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
              <div style={{ fontSize:11, fontWeight:600, color:'#64748b', marginBottom:2 }}>به تفکیک فروشنده — {fa(sellers.length)} نفر</div>
              {sellers.map(s => {
                const hasManual  = s.manual > 0;
                const isExpanded = expand === s.id;
                const manualLeads = (data?.manual || []).filter(m => m.seller_id === s.id);
                return (
                  <div key={s.id} style={{ borderRadius:10, border:`1px solid ${hasManual?'rgba(245,158,11,0.35)':'rgba(255,255,255,0.07)'}`, background: hasManual?'rgba(245,158,11,0.04)':'rgba(255,255,255,0.025)', overflow:'hidden' }}>
                    <div onClick={() => setExpand(isExpanded ? null : s.id)}
                      style={{ display:'flex', alignItems:'center', gap:12, padding:'10px 14px', cursor:'pointer' }}>
                      <div style={{ flex:1, minWidth:0 }}>
                        <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                          <span style={{ fontSize:13, fontWeight:600, color:'#e2e8f0' }}>{s.name}</span>
                          {hasManual && <span style={{ fontSize:10, padding:'1px 8px', borderRadius:20, background:'rgba(245,158,11,0.2)', color:'#F59E0B', fontWeight:700 }}>⚠️ دستی</span>}
                        </div>
                        <div style={{ fontSize:10, color:'#475569', marginTop:3 }}>آخرین برگشت: {s.last ? toShamsi(s.last) : '—'}</div>
                      </div>
                      <div style={{ display:'flex', gap:12, alignItems:'center', flexShrink:0 }}>
                        <div style={{ textAlign:'center' }}>
                          <div style={{ fontSize:16, fontWeight:700, color:'#94a3b8' }}>{fa(s.auto)}</div>
                          <div style={{ fontSize:9, color:'#374151' }}>قانون</div>
                        </div>
                        {hasManual && (
                          <div style={{ textAlign:'center' }}>
                            <div style={{ fontSize:16, fontWeight:700, color:'#F59E0B' }}>{fa(s.manual)}</div>
                            <div style={{ fontSize:9, color:'#374151' }}>دستی</div>
                          </div>
                        )}
                        <div style={{ fontSize:12, color:'#374151' }}>{isExpanded ? '▲' : '▼'}</div>
                      </div>
                    </div>

                    {isExpanded && (
                      <div style={{ borderTop:'1px solid rgba(255,255,255,0.06)', padding:'10px 14px', display:'flex', flexDirection:'column', gap:6 }}>
                        {s.auto > 0 && (
                          <div style={{ padding:'6px 10px', borderRadius:7, background:'rgba(100,116,139,0.1)', fontSize:11, color:'#64748b' }}>
                            ⚙️ {fa(s.auto)} برگشت قانونی — سیستم خودکار (انقضا / بی‌پاسخی / راکد)
                          </div>
                        )}
                        {manualLeads.length > 0 && (
                          <div>
                            <div style={{ fontSize:11, color:'#F59E0B', marginBottom:6, fontWeight:600 }}>⚠️ برگشت‌های دستی (خارج از قوانین):</div>
                            {manualLeads.map((ml, i) => (
                              <div key={i} style={{ display:'flex', alignItems:'flex-start', gap:10, padding:'7px 10px', borderRadius:7, background:'rgba(245,158,11,0.07)', marginBottom:4 }}>
                                <div style={{ flex:1, minWidth:0 }}>
                                  <div style={{ fontSize:12, fontWeight:600, color:'#e2e8f0' }}>
                                    {ml.lead_name || ml.lead_user || ml.lead_phone || ml.lead_id}
                                  </div>
                                  {ml.lead_phone && (
                                    <div style={{ fontSize:10, color:'#64748b', fontFamily:'monospace', direction:'ltr', textAlign:'right' }}>{ml.lead_phone}</div>
                                  )}
                                  {ml.note && <div style={{ fontSize:10, color:'#94a3b8', marginTop:2 }}>{ml.note}</div>}
                                </div>
                                <div style={{ textAlign:'center', flexShrink:0 }}>
                                  <div style={{ fontSize:10, padding:'2px 8px', borderRadius:20, background:'rgba(245,158,11,0.15)', color:'#F59E0B' }}>
                                    {ACTION_LABEL[ml.action] || ml.action}
                                  </div>
                                  <div style={{ fontSize:9, color:'#374151', marginTop:3 }}>{ml.created_at ? toShamsi(ml.created_at) : ''}</div>
                                </div>
                              </div>
                            ))}
                          </div>
                        )}
                        {manualLeads.length === 0 && s.auto > 0 && (
                          <div style={{ fontSize:11, color:'#475569' }}>فقط برگشت قانونی — بدون دخالت دستی ✅</div>
                        )}
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          )}

          <div style={{ padding:'10px 14px', borderRadius:9, background:'rgba(99,102,241,0.05)', border:'1px solid rgba(99,102,241,0.15)', fontSize:11, color:'#64748b', lineHeight:1.8 }}>
            <div style={{ fontWeight:600, color:'#818cf8', marginBottom:4 }}>راهنما:</div>
            <div>⚙️ <strong style={{ color:'#94a3b8' }}>برگشت قانونی:</strong> سیستم خودکار — انقضای مهلت، تعداد بی‌پاسخی، بی‌تماسی (راکد)</div>
            <div style={{ marginTop:3 }}>⚠️ <strong style={{ color:'#F59E0B' }}>برگشت دستی:</strong> مدیر دستی لید را از فروشنده گرفته — احتمال کم‌کاری یا درخواست فروشنده</div>
          </div>
        </React.Fragment>
      )}
    </div>
  );
};

// بوقِ کوتاهِ اعلان — بدونِ فایلِ صوتیِ خارجی (قانونِ کاربر ۲۰۲۶-۰۷-۲۸: همه‌ی اعلانات بوق داشته باشن)
function playPoolNotifBeep() {
  try {
    const ctx = new (window.AudioContext || window.webkitAudioContext)();
    const osc = ctx.createOscillator();
    const gain = ctx.createGain();
    osc.type = 'sine';
    osc.frequency.value = 880;
    gain.gain.setValueAtTime(0.001, ctx.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.25, ctx.currentTime + 0.01);
    gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.18);
    osc.connect(gain); gain.connect(ctx.destination);
    osc.start();
    osc.stop(ctx.currentTime + 0.2);
  } catch {}
}

// ── تبِ پیگیری — چتِ فروش‌یار × تیمِ تولید محتوا (قانونِ کاربر ۲۰۲۶-۰۷-۲۸) ──
const FollowupTab = () => {
  const { useState, useEffect, useRef } = React;
  const { fa } = window.SB_DATA;
  const token = localStorage.getItem(window.TOKEN_KEY);
  const h = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` };

  const [threads, setThreads] = useState(null);
  const [active,  setActive]  = useState(null); // lead_id
  const [notes,   setNotes]   = useState(null);
  const [text,    setText]    = useState('');
  const [sending, setSending] = useState(false);
  const [showSms, setShowSms] = useState(false);
  const [smsText, setSmsText] = useState('');
  const [smsSending, setSmsSending] = useState(false);
  const [showPm, setShowPm] = useState(false);
  const [pmText, setPmText] = useState('');
  const [pmSending, setPmSending] = useState(false);
  const [context, setContext] = useState(null); // { lead, notes, activities }
  const lastUnreadRef = useRef(0);
  // قانونِ کاربر (۲۰۲۶-۰۸-۰۵): این تب قبلاً فقط لیدهایی رو نشون می‌داد که از قبل یه پیامِ
  // پیگیری داشتن — نمی‌شد یه لیدِ جدید (که تویِ استخر/دستِ فروش‌یار هست ولی هنوز اینجا
  // گفتگویی نداره) رو پیدا و باهاش شروع کرد. این جست‌وجو هر لیدِ سیستم رو پیدا می‌کنه.
  const [addQuery,   setAddQuery]   = useState('');
  const [addResults, setAddResults] = useState([]);
  const [addSearching, setAddSearching] = useState(false);

  const activeThread = (threads || []).find(t => t.lead_id === active);

  const loadThreads = () => {
    fetch('/api/pool/content-notes/threads', { headers: h }).then(r => r.json())
      .then(res => {
        if (!res.success) return;
        setThreads(res.data.threads);
        const totalUnread = res.data.threads.reduce((s, t) => s + (t.unread || 0), 0);
        // قانونِ کاربر (۲۰۲۶-۰۸-۰۵): این اعلان دیگه فقط برایِ فروش‌یار نیست — پاسخِ پیامکیِ
        // خودِ مخاطب (webhookِ پارس‌گرین) هم همینجا حساب می‌شه
        if (totalUnread > lastUnreadRef.current) { playPoolNotifBeep(); toast.info('💬 پیامِ جدیدی رسید (فروش‌یار یا پاسخِ مخاطب)'); }
        lastUnreadRef.current = totalUnread;
      });
  };
  useEffect(() => {
    loadThreads();
    const t = setInterval(loadThreads, 20000); // هر ۲۰ ثانیه پول برایِ پیامِ جدید
    return () => clearInterval(t);
  }, []);

  const openThread = (leadId) => {
    setActive(leadId);
    setNotes(null);
    setContext(null);
    setShowSms(false);
    setSmsText('');
    setShowPm(false);
    setPmText('');
    fetch(`/api/pool/leads/${leadId}/content-notes`, { headers: h }).then(r => r.json())
      .then(res => { if (res.success) setNotes(res.data.notes); loadThreads(); });
    fetch(`/api/pool/leads/${leadId}/context`, { headers: h }).then(r => r.json())
      .then(res => { if (res.success) setContext(res.data); });
  };

  useEffect(() => {
    const q = addQuery.trim();
    if (!q) { setAddResults([]); setNewLeadName(''); setNewLeadPhone(''); return; }
    setAddSearching(true);
    const t = setTimeout(() => {
      fetch(`/api/leads?search=${encodeURIComponent(q)}&limit=8`, { headers: h }).then(r => r.json())
        .then(res => {
          const found = res.success ? (res.data?.leads || []) : [];
          setAddResults(found);
          if (found.length === 0) {
            // پیش‌پرکردنِ فرمِ ساختِ لیدِ جدید — اگه شبیهِ شماره بود تویِ فیلدِ شماره، وگرنه نام
            const isPhone = /^0?9\d{9}$/.test(q.replace(/\D/g, ''));
            setNewLeadPhone(isPhone ? q.replace(/\D/g, '') : '');
            setNewLeadName(isPhone ? '' : q);
          }
        })
        .finally(() => setAddSearching(false));
    }, 350);
    return () => clearTimeout(t);
  }, [addQuery]);

  const startThreadWithLead = (lead) => {
    setAddQuery(''); setAddResults([]);
    openThread(lead.id);
  };

  const [creatingLead, setCreatingLead] = useState(false);
  const [newLeadName,  setNewLeadName]  = useState('');
  const [newLeadPhone, setNewLeadPhone] = useState('');
  // قانونِ کاربر (۲۰۲۶-۰۸-۰۵): قبلاً فقط همون متنِ جست‌وجو (یا نام یا شماره، نه هردو) پاس
  // می‌شد — نتیجه‌ش لیدی بود که یا «بدون نام» می‌موند یا شماره نداشت (پس دکمه‌ی پیامک هم
  // نبود). حالا یه فرمِ کوچیکِ نام+شماره جداگانه‌ست — هر دو رو با هم می‌گیره.
  const createLeadAndStart = () => {
    const name = newLeadName.trim(), phone = newLeadPhone.trim();
    if (!name && !phone) return;
    setCreatingLead(true);
    fetch('/api/market/leads/create', { method:'POST', headers: h, body: JSON.stringify({
      full_name: name || undefined, phone: phone || undefined,
    })}).then(r => r.json()).then(res => {
      if (res.success) { setAddQuery(''); setAddResults([]); setNewLeadName(''); setNewLeadPhone(''); openThread(res.data.id); }
      else if (res.data?.existing_lead_id) { openThread(res.data.existing_lead_id); setAddQuery(''); setAddResults([]); setNewLeadName(''); setNewLeadPhone(''); toast.info('این لید از قبل بود — گفتگو باهاش باز شد'); }
      else toast.error(res.message || 'خطا در ساختِ لید');
    }).finally(() => setCreatingLead(false));
  };

  const sendSms = () => {
    const message = smsText.trim();
    if (!message || !active) return;
    setSmsSending(true);
    fetch(`/api/pool/leads/${active}/sms`, { method:'POST', headers: h, body: JSON.stringify({ message }) })
      .then(r => r.json())
      .then(res => {
        if (res.success) { setSmsText(''); setShowSms(false); toast.success('پیامک ارسال شد'); }
        else toast.error(res.message || 'خطا در ارسالِ پیامک');
      })
      .finally(() => setSmsSending(false));
  };

  const sendPm = () => {
    const message = pmText.trim();
    if (!message || !active) return;
    setPmSending(true);
    fetch(`/api/pool/leads/${active}/platform-message`, { method:'POST', headers: h, body: JSON.stringify({ message }) })
      .then(r => r.json())
      .then(res => {
        if (res.success) { setPmText(''); setShowPm(false); toast.success('پیام ارسال شد'); }
        else toast.error(res.message || 'خطا در ارسالِ پیام');
      })
      .finally(() => setPmSending(false));
  };

  const send = () => {
    const message = text.trim();
    if (!message || !active) return;
    setSending(true);
    fetch(`/api/pool/leads/${active}/content-notes`, { method:'POST', headers: h, body: JSON.stringify({ message }) })
      .then(r => r.json())
      .then(() => { setText(''); openThread(active); })
      .finally(() => setSending(false));
  };

  return (
    <div style={{ display:'flex', height:'100%' }}>
      <div style={{ width:300, flexShrink:0, borderInlineEnd:'1px solid var(--border)', overflowY:'auto' }}>
        {/* جست‌وجو/افزودنِ لیدِ جدید به این تب — قانونِ کاربر (۲۰۲۶-۰۸-۰۵) */}
        <div style={{ padding:'10px 14px', borderBottom:'1px solid var(--border)', position:'relative' }}>
          <input value={addQuery} onChange={e => setAddQuery(e.target.value)}
            placeholder="🔍 جست‌وجویِ لید (نام/شماره) برایِ شروعِ پیام..."
            style={{ width:'100%', padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)',
              background:'var(--bg)', color:'var(--text)', fontSize:12, boxSizing:'border-box' }} />
          {addQuery.trim() && (
            <div style={{ position:'absolute', top:'calc(100% - 4px)', insetInline:14, zIndex:50,
              background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8,
              maxHeight:260, overflowY:'auto', boxShadow:'0 8px 24px rgba(0,0,0,0.3)' }}>
              {addSearching && <div style={{padding:10,fontSize:11,color:'var(--text-muted)'}}>در حال جست‌وجو…</div>}
              {!addSearching && addResults.length === 0 && (
                <div style={{ padding:10, display:'flex', flexDirection:'column', gap:6 }}>
                  <div style={{fontSize:11,color:'var(--text-muted)'}}>لیدی پیدا نشد — شاید تو استخر نیست. ثبتِ لیدِ جدید:</div>
                  <input value={newLeadName} onChange={e => setNewLeadName(e.target.value)} placeholder="نام"
                    style={{ padding:'6px 9px', borderRadius:7, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:12, boxSizing:'border-box' }} />
                  <input value={newLeadPhone} onChange={e => setNewLeadPhone(e.target.value)} placeholder="شماره (برایِ پیامک لازمه)"
                    style={{ padding:'6px 9px', borderRadius:7, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:12, boxSizing:'border-box', direction:'ltr', textAlign:'right' }} />
                  <button onClick={creatingLead ? undefined : createLeadAndStart} disabled={creatingLead || (!newLeadName.trim() && !newLeadPhone.trim())} style={{
                    padding:'7px 0', borderRadius:7, border:'none', cursor: creatingLead ? 'default' : 'pointer', fontSize:12, fontWeight:600,
                    background:'var(--primary)', color:'#fff', opacity: (!newLeadName.trim() && !newLeadPhone.trim()) ? 0.5 : 1,
                  }}>
                    {creatingLead ? '⏳ در حال ساختن…' : '➕ ثبت و شروعِ پیام'}
                  </button>
                </div>
              )}
              {addResults.map(l => (
                <div key={l.id} onClick={() => startThreadWithLead(l)} style={{
                  padding:'8px 10px', cursor:'pointer', borderBottom:'1px solid var(--border)', fontSize:12,
                }}>
                  <div style={{fontWeight:600}}>{l.full_name || 'بدون نام'}</div>
                  <div style={{color:'var(--text-muted)', fontSize:11, marginTop:2}}>{l.phone || '—'} · {l.platform || '—'}</div>
                </div>
              ))}
            </div>
          )}
        </div>
        {threads === null && <div style={{padding:16,fontSize:12,color:'var(--text-muted)'}}>در حال بارگذاری…</div>}
        {threads && threads.length === 0 && <div style={{padding:16,fontSize:12,color:'var(--text-muted)'}}>هنوز گفتگویی ثبت نشده</div>}
        {threads && threads.map(t => (
          <div key={t.lead_id} onClick={() => openThread(t.lead_id)} style={{
            padding:'12px 14px', cursor:'pointer', borderBottom:'1px solid var(--border)',
            background: active === t.lead_id ? 'var(--bg)' : 'transparent',
          }}>
            <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', gap:8 }}>
              <b style={{fontSize:13}}>{t.full_name || t.phone || 'بدون نام'}</b>
              <div style={{display:'flex',alignItems:'center',gap:6}}>
                {!t.has_content_thread && <span style={{fontSize:9.5,padding:'1px 6px',borderRadius:999,background:'rgba(139,92,246,0.15)',color:'#8b5cf6'}}>📱 فقط پیامک</span>}
                {t.unread > 0 && <span style={{background:'#ef4444',color:'#fff',fontSize:10,fontWeight:700,borderRadius:999,padding:'1px 7px'}}>{fa(t.unread)}</span>}
              </div>
            </div>
            <div style={{fontSize:11,color:'var(--text-muted)',marginTop:3}}>فروش‌یار: {t.seller_name || t.seller_id || '—'}</div>
            <div style={{fontSize:12,color:'var(--text-muted)',marginTop:4,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>{t.last_message}</div>
          </div>
        ))}
      </div>
      <div style={{ flex:1, display:'flex', flexDirection:'column' }}>
        {!active && <div style={{margin:'auto',color:'var(--text-muted)',fontSize:13}}>یه لید رو از لیست انتخاب کنید</div>}
        {active && (
          <>
            <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', gap:10, padding:'10px 16px', borderBottom:'1px solid var(--border)' }}>
              <div>
                <b style={{fontSize:14}}>{context?.lead?.full_name || activeThread?.full_name || 'بدون نام'}</b>
                {(context?.lead?.phone || activeThread?.phone) && <span style={{fontSize:12,color:'var(--text-muted)',marginRight:8}}>{context?.lead?.phone || activeThread?.phone}</span>}
              </div>
              <div style={{display:'flex',gap:8}}>
                {context?.lead?.platform && context?.lead?.platform !== 'manual' && (
                  <Button size="sm" variant="ghost" onClick={() => setShowPm(s => !s)}>
                    ✈️ پیام از طریقِ {context.lead.platform}
                  </Button>
                )}
                {context?.lead?.username && ['telegram','bale','manual'].includes(context?.lead?.platform) && (
                  <a href={(context.lead.platform === 'bale' ? 'https://ble.ir/' : 'https://t.me/') + context.lead.username.replace(/^@/,'')}
                    target="_blank" rel="noreferrer"
                    style={{display:'flex',alignItems:'center',gap:6,padding:'6px 12px',borderRadius:8,border:'1px solid var(--border)',color:'var(--text)',fontSize:12,textDecoration:'none'}}>
                    {context.lead.platform === 'bale' ? '🔵' : '✈️'} {context.lead.username}
                  </a>
                )}
                {(context?.lead?.phone || activeThread?.phone) && (
                  <Button size="sm" variant="ghost" onClick={() => setShowSms(s => !s)}>📱 پیامک به مخاطب</Button>
                )}
                <Button size="sm" variant="ghost" onClick={() => {
                  if (!window.confirm('کلِ رشته‌ی پیگیریِ این لید (پیام‌ها) پاک بشه؟')) return;
                  fetch(`/api/pool/leads/${active}/content-notes`, { method:'DELETE', headers: h })
                    .then(r => r.json())
                    .then(res => { if (res.success) { toast.success('پیگیری حذف شد'); setActive(null); setNotes(null); loadThreads(); } else toast.error(res.message||'خطا'); });
                }}>🗑 حذفِ پیگیری</Button>
              </div>
            </div>
            {showPm && (
              <div style={{ display:'flex', gap:8, padding:'10px 16px', borderBottom:'1px solid #e2e8f0', background:'#fff' }}>
                <textarea value={pmText} onChange={e=>setPmText(e.target.value)} rows={2} dir="rtl"
                  placeholder={`پیام مستقیم از طریقِ ${context?.lead?.platform || 'پلتفرم'}…`}
                  style={{flex:1,padding:'9px 12px',borderRadius:9,border:'1px solid #cbd5e1',background:'#fff',color:'#0f172a',fontFamily:'inherit',fontSize:13,resize:'vertical',outline:'none',textAlign:'right'}}/>
                <Button variant="primary" onClick={sendPm} disabled={pmSending || !pmText.trim()}>
                  {pmSending ? '...' : 'ارسال'}
                </Button>
              </div>
            )}
            {showSms && (
              <div style={{ display:'flex', gap:8, padding:'10px 16px', borderBottom:'1px solid #e2e8f0', background:'#fff' }}>
                <textarea value={smsText} onChange={e=>setSmsText(e.target.value)} rows={2} dir="rtl"
                  placeholder={`پیامک مستقیم به شماره‌ی ${context?.lead?.phone || activeThread?.phone || ''}…`}
                  style={{flex:1,padding:'9px 12px',borderRadius:9,border:'1px solid #cbd5e1',background:'#fff',color:'#0f172a',fontFamily:'inherit',fontSize:13,resize:'vertical',outline:'none',textAlign:'right'}}/>
                <Button variant="primary" onClick={sendSms} disabled={smsSending || !smsText.trim()}>
                  {smsSending ? '...' : 'ارسالِ پیامک'}
                </Button>
              </div>
            )}
            {/* قانونِ کاربر (۲۰۲۶-۰۷-۲۸): فقط داخلِ پنجره‌ی چت (لیستِ پیام‌ها + کادرِ تایپ) سفید باشه، بقیه‌ی صفحه طبقِ تمِ اصلی */}
            <div style={{ flex:1, overflowY:'auto', padding:16, display:'flex', flexDirection:'column', gap:8, background:'#fff' }}>
              {notes === null && <div style={{fontSize:12,color:'#64748b'}}>در حال بارگذاری…</div>}
              {notes && notes.map(n => (
                <div key={n.id} dir="rtl" style={{
                  alignSelf: n.sender === 'content_team' ? 'flex-end' : 'flex-start',
                  maxWidth:'70%', padding:'8px 12px', borderRadius:12,
                  background: n.sender === 'content_team' ? '#6366f1' : '#f1f5f9',
                  color: n.sender === 'content_team' ? '#fff' : '#0f172a',
                  fontSize:13, lineHeight:1.7, textAlign:'right',
                }}>
                  <div style={{fontSize:10.5, opacity:.75, marginBottom:3, fontWeight:700}}>
                    {/* قانونِ کاربر (۲۰۲۶-۰۸-۰۲): sender_id از قبل اسمِ واقعیِ فرستنده رو
                        نگه می‌داره (هم برایِ content_team هم برایِ seller) — چون اکانتِ
                        «تیمِ محتوا» بینِ چندنفر مشترکه، «شما» فقط وقتی نشون داده می‌شه که
                        واقعاً هیچ اسمی ثبت نشده باشه، نه به‌صورتِ پیش‌فرض. */}
                    {n.sender === 'content_team'
                      ? (n.sender_id || 'شما')
                      : `فروش‌یار${n.sender_id ? ': ' + n.sender_id : ''}`}
                  </div>
                  {n.message}
                  <div style={{fontSize:9.5, opacity:.65, marginTop:4}}>{toShamsiTimeUTC(n.created_at)}</div>
                </div>
              ))}
            </div>
            <div style={{ display:'flex', gap:8, borderTop:'1px solid #e2e8f0', padding:12, background:'#fff' }}>
              <textarea value={text} onChange={e=>setText(e.target.value)} rows={1} dir="rtl"
                placeholder="پیام برای فروش‌یار…"
                style={{flex:1,padding:'7px 12px',borderRadius:9,border:'1px solid #cbd5e1',background:'#fff',color:'#0f172a',fontFamily:'inherit',fontSize:13,resize:'vertical',outline:'none',textAlign:'right'}}/>
              <Button variant="primary" onClick={send} disabled={sending || !text.trim()}>ارسال</Button>
            </div>
          </>
        )}
      </div>
      {active && (
        <div style={{ width:420, flexShrink:0, borderInlineStart:'1px solid var(--border)', overflowY:'auto', padding:14 }}>
          <div style={{fontSize:12,fontWeight:700,color:'var(--text-muted)',marginBottom:10}}>جزئیاتِ مخاطب</div>
          {!context && <div style={{fontSize:12,color:'var(--text-muted)'}}>در حال بارگذاری…</div>}
          {context && (
            <>
              <div style={{fontSize:13,marginBottom:4}}>پلتفرم: {context.lead.platform || '—'}</div>
              <div style={{fontSize:13,marginBottom:4}}>یوزرنیم: {context.lead.username || '—'}</div>
              <div style={{fontSize:13,marginBottom:14}}>وضعیت: {context.lead.status || '—'}</div>

              <div style={{fontSize:12,fontWeight:700,color:'var(--text-muted)',margin:'12px 0 8px'}}>📝 یادداشت‌هایِ فروش‌یار</div>
              {context.notes.length === 0 && <div style={{fontSize:12,color:'var(--text-muted)'}}>یادداشتی ثبت نشده</div>}
              {context.notes.map(n => (
                <div key={n.id} style={{fontSize:12.5,padding:'8px 10px',borderRadius:8,background:'var(--bg)',marginBottom:6,lineHeight:1.7}}>
                  {n.text}
                  <div style={{fontSize:10.5,color:'var(--text-muted)',marginTop:4}}>{toShamsiTimeUTC(n.created_at)}</div>
                </div>
              ))}

              <div style={{fontSize:12,fontWeight:700,color:'var(--text-muted)',margin:'14px 0 8px'}}>✅ فعالیت‌ها</div>
              {context.activities.length === 0 && <div style={{fontSize:12,color:'var(--text-muted)'}}>فعالیتی ثبت نشده</div>}
              {context.activities.map(a => (
                <div key={a.id} style={{fontSize:12.5,padding:'8px 10px',borderRadius:8,background:'var(--bg)',marginBottom:6,lineHeight:1.7}}>
                  <b>{a.title}</b>{a.done ? ' ✓' : ''}
                  <div style={{fontSize:10.5,color:'var(--text-muted)',marginTop:4}}>{toShamsiTimeUTC(a.scheduled_at || a.created_at)}</div>
                </div>
              ))}

              <div style={{fontSize:12,fontWeight:700,color:'var(--text-muted)',margin:'14px 0 8px'}}>📱 پیامک‌ها</div>
              {(!context.smsHistory || context.smsHistory.length === 0) && <div style={{fontSize:12,color:'var(--text-muted)'}}>پیامکی ارسال نشده</div>}
              {/* قانونِ کاربر (۲۰۲۶-۰۸-۰۵): پاسخِ دریافتی از خودِ مخاطب (direction='in'، از
                  webhookِ پارس‌گرین) باید بصری از پیامکِ ارسالی جدا باشه — گفتگویِ دوطرفه */}
              {(context.smsHistory || []).map(s => (
                <div key={s.id} style={{fontSize:12.5,padding:'8px 10px',borderRadius:8,marginBottom:6,lineHeight:1.7,
                  background: s.direction === 'in' ? 'rgba(52,211,153,0.1)' : 'var(--bg)',
                  border: s.direction === 'in' ? '1px solid rgba(52,211,153,0.3)' : 'none'}}>
                  <span style={{fontSize:10.5,fontWeight:800,color: s.direction === 'in' ? '#34D399' : s.sent_by === 'content_team' ? '#8b5cf6' : '#3b82f6'}}>
                    {s.direction === 'in' ? '📩 پاسخِ مخاطب' : s.sent_by === 'content_team' ? `🎬 ${s.sent_by_name || 'تیمِ تولید محتوا'}` : '👤 فروش‌یار'}
                  </span>
                  <div>{s.message}</div>
                  <div style={{fontSize:10.5,color:'var(--text-muted)',marginTop:4}}>{toShamsiTimeUTC(s.created_at)}{s.direction !== 'in' && ` — ${s.status === 'sent' ? '✓ ارسال شد' : s.status}`}</div>
                </div>
              ))}
            </>
          )}
        </div>
      )}
    </div>
  );
};

window.LeadPool = LeadPool;