/* ============================================================
   AI Insights — distributsiya analitigi
   2 bo'lim: AI Insights (avtomatik audit) + AI Chat (savol-javob).
   Hammasi platforma backendi orqali (Anthropic kaliti serverda).
   ============================================================ */

/* ============================================================
   Umumiy yordamchilar — fayl biriktirish + PDF eksport
   (Babel global scope: bu funksiyalar barcha panellarga ko'rinadi)
   ============================================================ */

// Biriktirilgan fayl matnining maksimal hajmi (backend xabar limiti 8000 belgi —
// yozilgan matn + o'rama uchun joy qoldiramiz)
const AI_FILE_MAX = 5000;

// Matn sifatida o'qib bo'ladigan fayl turlari (binar/rasm emas)
const AI_TEXT_EXT = /\.(txt|csv|tsv|md|markdown|json|log|xml|yaml|yml|ini|conf|html?|js|ts|css|sql)$/i;

// Faylni matn sifatida o'qiydi → {name,size,kind,text,truncated}. Faqat matnli fayllar.
function aiReadFile(file) {
  return new Promise((resolve, reject) => {
    if (!file) return reject(new Error('Fayl tanlanmadi'));
    const isText = /^text\//.test(file.type) || file.type === 'application/json' || AI_TEXT_EXT.test(file.name || '');
    if (!isText) {
      return reject(new Error('Faqat matnli fayllar (txt, csv, md, json, xml...) qoʻllab-quvvatlanadi.'));
    }
    if (file.size > 2 * 1024 * 1024) {
      return reject(new Error('Fayl juda katta (2 MB dan oshmasin).'));
    }
    const reader = new FileReader();
    reader.onerror = () => reject(new Error('Faylni oʻqib boʻlmadi'));
    reader.onload = () => {
      let text = String(reader.result || '');
      const truncated = text.length > AI_FILE_MAX;
      if (truncated) text = text.slice(0, AI_FILE_MAX);
      resolve({ name: file.name || 'fayl', size: file.size, kind: file.type || 'text', text, truncated });
    };
    reader.readAsText(file);
  });
}

// AI'ga yuboriladigan to'liq matn: foydalanuvchi matni + biriktirilgan fayl mazmuni.
function aiWireContent(m) {
  const base = String((m && m.content) || '');
  const at = m && m.attachment;
  if (!at || !at.text) return base || '(fayl)';
  const head = base ? base + '\n\n' : '';
  const note = at.truncated ? ' (qisqartirilgan)' : '';
  return head + '[Biriktirilgan fayl: ' + at.name + note + ']\n"""\n' + at.text + '\n"""';
}

// Biriktirilgan fayl belgisi (chip)
function AiFileChip({ at, onRemove }) {
  if (!at) return null;
  const kb = at.size ? Math.max(1, Math.round(at.size / 1024)) : null;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, maxWidth: '100%', fontSize: 11.5, fontWeight: 600, padding: '4px 10px', borderRadius: 999, border: '1px solid var(--border)', background: 'var(--bg-soft, rgba(142,116,255,.08))', color: 'var(--ink-2)' }}>
      <Icon name="file" size={12} />
      <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 160 }}>{at.name}</span>
      {kb != null && <span style={{ color: 'var(--ink-4)', flex: 'none' }}>{kb} KB</span>}
      {onRemove && (
        <button onClick={onRemove} title="Olib tashlash" style={{ display: 'inline-flex', border: 'none', background: 'transparent', color: 'var(--ink-4)', cursor: 'pointer', padding: 0, flex: 'none' }}>
          <Icon name="x" size={12} />
        </button>
      )}
    </span>
  );
}

// --- PDF eksport (tashqi kutubxonasiz — bosib chiqarish oynasi orqali "PDF saqlash") ---
function aiHtmlEsc(s) {
  return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
function aiRichHtml(text) {
  return aiHtmlEsc(text).replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
}
function aiExportPdf(title, items) {
  const rows = (items || []).map((it) => {
    const who = aiHtmlEsc(it.who);
    const sub = it.sub ? '<span class="sub">' + aiHtmlEsc(it.sub) + '</span>' : '';
    const col = it.color || '#5B45D6';
    const cls = it.role === 'user' ? 'me' : (it.moderator ? 'mod' : 'ai');
    const att = it.attachment ? '<div class="att">Biriktirilgan fayl: ' + aiHtmlEsc(it.attachment) + '</div>' : '';
    return '<div class="msg ' + cls + '"><div class="who" style="color:' + col + '">' + who + sub + '</div>' + att + '<div class="body">' + aiRichHtml(it.content) + '</div></div>';
  }).join('');
  const when = new Date().toLocaleString('ru-RU');
  const doc = '<!doctype html><html lang="uz"><head><meta charset="utf-8"><title>' + aiHtmlEsc(title) + '</title>'
    + '<style>'
    + 'body{font-family:-apple-system,Segoe UI,Roboto,Arial,sans-serif;color:#1f2430;margin:32px;line-height:1.55}'
    + 'h1{font-size:20px;margin:0 0 4px}.meta{color:#888;font-size:12px;margin-bottom:20px}'
    + '.msg{border:1px solid #E6DFD7;border-radius:10px;padding:11px 14px;margin:0 0 11px;page-break-inside:avoid}'
    + '.msg.me{background:#EFEBFD}.msg.mod{background:#E6F5EF;border-color:#86efac}'
    + '.who{font-weight:700;font-size:13px;margin-bottom:5px}.who .sub{font-weight:500;color:#999;margin-left:6px;font-size:11px}'
    + '.att{font-size:11px;color:#7A7068;margin-bottom:5px}'
    + '.body{font-size:13px;white-space:pre-wrap;word-break:break-word}'
    + '@media print{body{margin:14mm}}'
    + '</style></head><body>'
    + '<h1>' + aiHtmlEsc(title) + '</h1><div class="meta">' + aiHtmlEsc(when) + '</div>'
    + rows
    + '<scr' + 'ipt>window.onload=function(){setTimeout(function(){window.print();},250);};</scr' + 'ipt>'
    + '</body></html>';
  const w = window.open('', '_blank');
  if (!w) { alert('Pop-up oynasi bloklandi. Brauzerda ruxsat bering.'); return; }
  w.document.open(); w.document.write(doc); w.document.close();
}

const AI_SEVERITY = {
  risk:        { label: 'Xavf',       tint: 'rgba(232,115,95,.12)',  ink: '#C2453A', dot: '#E8735F' },
  warning:     { label: 'Ogohlantirish', tint: 'rgba(227,162,59,.16)', ink: '#A6651E', dot: '#E3A23B' },
  opportunity: { label: 'Imkoniyat',  tint: 'rgba(142,116,255,.12)', ink: '#5B45D6', dot: '#8E74FF' },
  good:        { label: 'Yaxshi',     tint: 'rgba(61,190,156,.14)',  ink: '#1D8A6E', dot: '#3DBE9C' },
};
const aiSev = (s) => AI_SEVERITY[s] || AI_SEVERITY.warning;

// --- Bir martalik animatsiya + markdown uslublari ---
(function injectAiStyles() {
  if (typeof document === 'undefined' || document.getElementById('ai-styles')) return;
  const s = document.createElement('style');
  s.id = 'ai-styles';
  s.textContent = [
    '@keyframes aiBlink{0%,80%,100%{opacity:.2;transform:translateY(0)}40%{opacity:1;transform:translateY(-4px)}}',
    '.ai-typing{display:inline-flex;gap:4px;align-items:center}',
    '.ai-typing i{width:7px;height:7px;border-radius:50%;background:#8E74FF;display:inline-block;animation:aiBlink 1.2s infinite}',
    '.ai-typing i:nth-child(2){animation-delay:.18s}.ai-typing i:nth-child(3){animation-delay:.36s}',
    '@keyframes aiFadeUp{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:translateY(0)}}',
    '.ai-in{animation:aiFadeUp .26s ease both}',
    '@keyframes aiShimmer{0%{background-position:-340px 0}100%{background-position:340px 0}}',
    '.ai-shimmer{background:linear-gradient(90deg,var(--ink-4,#9aa) 0,var(--ink,#222) 30%,var(--ink-4,#9aa) 60%);background-size:340px 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:aiShimmer 1.6s linear infinite}',
    '.ai-md{font-size:13.5px;line-height:1.62;color:var(--ink);word-break:break-word}',
    '.ai-md>*:first-child{margin-top:0}.ai-md>*:last-child{margin-bottom:0}',
    '.ai-md h2{font-size:15px;font-weight:800;margin:13px 0 6px}',
    '.ai-md h3{font-size:13.5px;font-weight:700;margin:11px 0 5px}',
    '.ai-md p{margin:6px 0}',
    '.ai-md ul{margin:6px 0;padding-left:18px}.ai-md li{margin:3px 0}',
    '.ai-md code{background:rgba(127,127,127,.16);padding:1px 5px;border-radius:5px;font-size:12px}',
    '.ai-md blockquote{margin:8px 0;padding:6px 12px;border-left:3px solid #8E74FF;background:rgba(142,116,255,.07);border-radius:6px;color:var(--ink-2)}',
    '.ai-md hr{border:none;border-top:1px solid var(--border);margin:12px 0}',
    '.ai-md table{border-collapse:collapse;width:100%;margin:8px 0;font-size:12.5px;overflow:hidden;border-radius:8px}',
    '.ai-md th,.ai-md td{border:1px solid var(--border);padding:6px 9px;text-align:left}',
    '.ai-md th{background:rgba(127,127,127,.08);font-weight:700}',
  ].join('');
  document.head.appendChild(s);
})();

// Jonli "yozmoqda" animatsiyasi (3 ta sakrab turuvchi nuqta + shimmer matn)
function AiTyping({ label }) {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 10 }}>
      <span className="ai-typing"><i></i><i></i><i></i></span>
      <span className="ai-shimmer" style={{ fontSize: 13, fontWeight: 600 }}>{label || 'yozmoqda'}</span>
    </span>
  );
}

// --- Yengil markdown → React (tashqi kutubxonasiz) ---
function mdInline(text, key) {
  const nodes = [];
  let rest = String(text);
  let i = 0;
  const re = /(\*\*([^*]+)\*\*|`([^`]+)`)/;
  let m;
  while ((m = rest.match(re))) {
    const idx = m.index;
    if (idx > 0) nodes.push(rest.slice(0, idx));
    if (m[2] !== undefined) nodes.push(<strong key={key + 'b' + i}>{m[2]}</strong>);
    else if (m[3] !== undefined) nodes.push(<code key={key + 'c' + i}>{m[3]}</code>);
    rest = rest.slice(idx + m[0].length);
    i++;
  }
  if (rest) nodes.push(rest);
  return nodes;
}

function AiMarkdown({ text }) {
  const lines = String(text || '').replace(/\r/g, '').split('\n');
  const blocks = [];
  let i = 0, k = 0;
  const isSpecial = (s) => /^(#{1,6}\s|>\s?|\||(\d+\.|[-*])\s|-{3,}$|\*{3,}$|_{3,}$)/.test(s);
  while (i < lines.length) {
    const t = lines[i].trim();
    if (!t) { i++; continue; }
    if (/^(-{3,}|\*{3,}|_{3,})$/.test(t)) { blocks.push(<hr key={k++} />); i++; continue; }
    const hm = t.match(/^(#{1,6})\s+(.*)$/);
    if (hm) {
      const Tag = hm[1].length <= 2 ? 'h2' : 'h3';
      blocks.push(<Tag key={k++}>{mdInline(hm[2], 'h' + k)}</Tag>);
      i++; continue;
    }
    if (/^>\s?/.test(t)) {
      const buf = [];
      while (i < lines.length && /^>\s?/.test(lines[i].trim())) { buf.push(lines[i].trim().replace(/^>\s?/, '')); i++; }
      blocks.push(<blockquote key={k++}>{mdInline(buf.join(' '), 'q' + k)}</blockquote>);
      continue;
    }
    if (/^\|/.test(t) && i + 1 < lines.length && /^\|?[\s:|-]+\|/.test(lines[i + 1].trim())) {
      const rows = [];
      while (i < lines.length && /^\|/.test(lines[i].trim())) { rows.push(lines[i].trim()); i++; }
      const cells = (r) => r.replace(/^\||\|$/g, '').split('|').map((c) => c.trim());
      const header = cells(rows[0]);
      const body = rows.slice(2).map(cells);
      blocks.push(
        <table key={k++}>
          <thead><tr>{header.map((h, hi) => <th key={hi}>{mdInline(h, 'th' + k + hi)}</th>)}</tr></thead>
          <tbody>{body.map((r, ri) => <tr key={ri}>{r.map((c, ci) => <td key={ci}>{mdInline(c, 'td' + k + ri + ci)}</td>)}</tr>)}</tbody>
        </table>,
      );
      continue;
    }
    if (/^(\d+\.|[-*])\s+/.test(t)) {
      const items = [];
      while (i < lines.length && /^(\d+\.|[-*])\s+/.test(lines[i].trim())) { items.push(lines[i].trim().replace(/^(\d+\.|[-*])\s+/, '')); i++; }
      blocks.push(<ul key={k++}>{items.map((it, ii) => <li key={ii}>{mdInline(it, 'l' + k + ii)}</li>)}</ul>);
      continue;
    }
    const buf = [];
    while (i < lines.length && lines[i].trim() && !isSpecial(lines[i].trim())) { buf.push(lines[i].trim()); i++; }
    blocks.push(<p key={k++}>{mdInline(buf.join(' '), 'p' + k)}</p>);
  }
  return <div className="ai-md">{blocks}</div>;
}

const AI_SUGGESTIONS = [
  'Hozir eng katta xavf nimada?',
  'Qaysi regionlar rejadan orqada?',
  'Qaysi dillerlar nofaol (zakaz qilmayapti)?',
  'Sell-out prognozi reja bilan qanchalik mos?',
  'Brendlar ulushi qanday?',
  'Muddati o\'tgan zakazlar bo\'yicha nima qilish kerak?',
];

// Health gauge (0-100) — rang holatiga qarab
function AiHealth({ score }) {
  if (score == null) return null;
  const s = Math.max(0, Math.min(100, score));
  const col = s >= 70 ? '#3DBE9C' : s >= 45 ? '#E3A23B' : '#E8735F';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
      <div style={{ position: 'relative', width: 64, height: 64, flex: 'none' }}>
        <svg width="64" height="64" viewBox="0 0 64 64" style={{ transform: 'rotate(-90deg)' }}>
          <circle cx="32" cy="32" r="27" fill="none" stroke="var(--border)" strokeWidth="7" />
          <circle cx="32" cy="32" r="27" fill="none" stroke={col} strokeWidth="7" strokeLinecap="round"
            strokeDasharray={`${(s / 100) * 169.6} 169.6`} />
        </svg>
        <div className="tnum" style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', fontSize: 16, fontWeight: 800, color: col }}>{s}</div>
      </div>
      <div>
        <div style={{ fontSize: 12, color: 'var(--ink-4)', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.04em' }}>Distributsiya sogʻligi</div>
        <div style={{ fontSize: 13, color: 'var(--ink-3)' }}>{s >= 70 ? 'Barqaror' : s >= 45 ? 'Eʼtibor talab' : 'Tahlikali'}</div>
      </div>
    </div>
  );
}

function AiInsightCard({ it }) {
  const sv = aiSev(it.severity);
  return (
    <div style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderLeft: `3px solid ${sv.dot}`, borderRadius: 'var(--r-lg)', padding: '14px 16px', boxShadow: 'var(--sh-1)', display: 'flex', flexDirection: 'column', gap: 8 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10 }}>
        <div style={{ fontWeight: 700, fontSize: 13.5, lineHeight: 1.3 }}>{it.title}</div>
        <span style={{ flex: 'none', fontSize: 10.5, fontWeight: 700, padding: '2px 8px', borderRadius: 999, background: sv.tint, color: sv.ink, whiteSpace: 'nowrap' }}>{sv.label}</span>
      </div>
      {it.metric && <div className="tnum" style={{ fontSize: 18, fontWeight: 800, letterSpacing: '-.02em', color: sv.ink }}>{it.metric}</div>}
      {it.finding && <div style={{ fontSize: 12.5, color: 'var(--ink-2)', lineHeight: 1.5 }}>{it.finding}</div>}
      {it.recommendation && (
        <div style={{ display: 'flex', gap: 7, alignItems: 'flex-start', fontSize: 12.5, color: 'var(--ink-3)', background: 'var(--bg-soft, rgba(127,127,127,.06))', borderRadius: 8, padding: '8px 10px' }}>
          <span style={{ color: sv.dot, flex: 'none', marginTop: 1 }}><Icon name="bulb" size={14} /></span>
          <span>{it.recommendation}</span>
        </div>
      )}
      {it.area && <div style={{ fontSize: 10.5, color: 'var(--ink-4)', textTransform: 'uppercase', letterSpacing: '.04em' }}>{it.area}</div>}
    </div>
  );
}

// --- AI sozlanmagan holati ---
function AiSetupNotice() {
  return (
    <div style={{ maxWidth: 560, margin: '40px auto', textAlign: 'center', display: 'flex', flexDirection: 'column', gap: 12, color: 'var(--ink-3)' }}>
      <div style={{ width: 56, height: 56, borderRadius: 16, background: 'rgba(142,116,255,.12)', color: '#5B45D6', display: 'grid', placeItems: 'center', margin: '0 auto' }}>
        <Icon name="sparkle" size={26} />
      </div>
      <div style={{ fontSize: 16, fontWeight: 700, color: 'var(--ink)' }}>AI hali ulanmagan</div>
      <div style={{ fontSize: 13, lineHeight: 1.6 }}>
        AI ishlashi uchun Railway sozlamalarida <b>ANTHROPIC_API_KEY</b> oʻzgaruvchisini qoʻshish kerak.
        Kalit faqat serverda saqlanadi — brauzerga chiqmaydi.
      </div>
    </div>
  );
}

// Davom etayotgan "Qayta tahlil" so'rovlari — komponent tashqarisida (modul darajasida)
// saqlanadi. Shunda boshqa bo'limga o'tib qaytsangiz ham tahlil to'xtamaydi, qaytib
// kelganda natijaga qayta ulanadi. Kalit — foydalanuvchi bo'yicha.
const aiInsightsJobs = {}; // userId -> Promise<res>

/* ============================================================
   Faol AI ishlari (chat + davra suhbati) — komponent tashqarisida
   (modul darajasida) yuritiladi. Foydalanuvchi boshqa bo'limga o'tib
   ketsa ham so'rov to'xtamaydi; har qadam localStorage'ga yoziladi va
   komponent qaytib kelganda faol ishga qayta ulanadi.
   ============================================================ */
const aiChatJobs = {}; // CHAT_KEY -> job
const aiRtJobs = {};   // RT_KEY -> job

// Umumiy ish yurituvchi. worker({ setMessages, setTyping }) qadamlarni bajaradi;
// har yangilanish snapshotni localStorage'ga yozadi va obunachilarga xabar beradi.
function aiRunJob(store, key, persistKey, persistLimit, initialMessages, worker) {
  const listeners = new Set();
  let snap = { messages: initialMessages, busy: true, typing: null, err: null };
  const persist = () => {
    try { localStorage.setItem(persistKey, JSON.stringify((snap.messages || []).slice(-persistLimit))); } catch (e) { /* to'la bo'lsa e'tibor bermaymiz */ }
  };
  const update = (patch) => {
    snap = Object.assign({}, snap, patch);
    persist();
    listeners.forEach((fn) => { try { fn(snap); } catch (e) { /* */ } });
  };
  persist(); // boshlang'ich holat (foydalanuvchi xabari) darhol saqlanadi
  const job = {
    get snap() { return snap; },
    subscribe(fn) { listeners.add(fn); return () => listeners.delete(fn); },
  };
  job.promise = (async () => {
    try {
      await worker({
        setMessages: (msgs) => update({ messages: msgs }),
        setTyping: (t) => update({ typing: t }),
      });
    } catch (ex) {
      update({ err: (ex && ex.message) || 'Xatolik' });
    } finally {
      update({ busy: false, typing: null });
      if (store[key] === job) delete store[key];
    }
    return snap;
  })();
  store[key] = job;
  return job;
}

// AI chat — bitta so'rov (foydalanuvchi → analitik javobi).
function aiStartChatJob(CHAT_KEY, baseMessages, wire) {
  return aiRunJob(aiChatJobs, CHAT_KEY, CHAT_KEY, 40, baseMessages, async ({ setMessages }) => {
    try {
      const res = await API.aiChat(wire);
      setMessages([...baseMessages, { role: 'assistant', content: res.answer || '(boʻsh javob)' }]);
    } catch (ex) {
      const msg = (ex && ex.message) || 'Javob olinmadi';
      setMessages([...baseMessages, { role: 'assistant', content: '⚠️ Xatolik: ' + msg }]);
      throw ex;
    }
  });
}

// Davra suhbati — tanlangan agent(lar)ga ketma-ket savol.
function aiStartRtSendJob(RT_KEY, baseMessages, targets, toWire) {
  return aiRunJob(aiRtJobs, RT_KEY, RT_KEY, 60, baseMessages, async ({ setMessages, setTyping }) => {
    let convo = baseMessages;
    for (const a of targets) {
      setTyping({ name: a.name, emoji: a.emoji });
      const r = await API.aiAgentReply(a.id, convo.map(toWire));
      convo = [...convo, { role: 'agent', agentId: a.id, name: r.name, title: r.title, emoji: r.emoji, color: r.color, content: r.content }];
      setMessages(convo);
    }
  });
}

// Davra suhbati — moderator yakuniy xulosasi.
function aiStartRtConcludeJob(RT_KEY, baseMessages, moderatorId, moderator, toWire) {
  return aiRunJob(aiRtJobs, RT_KEY, RT_KEY, 60, baseMessages, async ({ setMessages, setTyping }) => {
    setTyping({ name: (moderator && moderator.name) || 'Moderator', emoji: (moderator && moderator.emoji) || '⚖️' });
    const r = await API.aiAgentConclude(baseMessages.map(toWire), moderatorId);
    setMessages([...baseMessages, { role: 'agent', isModerator: true, agentId: r.id, name: r.name, title: r.title, emoji: r.emoji, color: r.color, content: r.content }]);
  });
}

function AiInsightsPanel({ enabled, user }) {
  // Oxirgi insaytlar localStorage'da saqlanadi — sahifa yangilansa yoki qayta login qilinsa
  // ham darhol ko'rinadi (yo'qolmaydi). Kalit foydalanuvchi bo'yicha — birovning maxfiy
  // (hudud kesimidagi) tahlili boshqasiga ko'rinmasligi uchun.
  const cacheKey = 'mm_ai_insights:' + ((user && user.id) || 'anon');
  const [data, setData] = useState(() => {
    try { return JSON.parse(localStorage.getItem(cacheKey) || 'null'); } catch { return null; }
  });
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [err, setErr] = useState(null);

  async function load(force) {
    const jobKey = (user && user.id) || 'anon';
    const existing = aiInsightsJobs[jobKey];
    const reattach = !force && !!existing; // davom etayotgan tahlilga qayta ulanish
    if (force || reattach) setRefreshing(true); else setLoading(true);
    setErr(null);
    // Bir vaqtning o'zida bitta so'rov — komponent unmount bo'lsa ham davom etadi.
    let p = existing;
    if (force || !p) {
      p = API.aiInsights(force);
      aiInsightsJobs[jobKey] = p;
    }
    try {
      const res = await p;
      const hasContent = !!(res && ((res.insights && res.insights.length) || res.summary));
      if (hasContent) {
        setData(res);
        try { localStorage.setItem(cacheKey, JSON.stringify(res)); } catch { /* to'la bo'lsa e'tibor bermaymiz */ }
      } else if (!data) {
        setData(res); // keshda hech narsa yo'q — bo'sh/xato javobni ko'rsatamiz
      }
      // aks holda: yangi javob bo'sh, ammo keshda oxirgi yaxshi tahlil bor — uni saqlab qolamiz
    } catch (ex) {
      setErr(ex.message || 'Insaytlarni yuklab boʻlmadi');
    } finally {
      if (aiInsightsJobs[jobKey] === p) delete aiInsightsJobs[jobKey];
      setLoading(false);
      setRefreshing(false);
    }
  }

  useEffect(() => { if (enabled) load(false); }, [enabled]); // eslint-disable-line

  if (!enabled) return <AiSetupNotice />;

  if (loading && !data) {
    return (
      <div style={{ display: 'grid', placeItems: 'center', padding: 50, color: 'var(--ink-4)' }}>
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12 }}>
          <Icon name="sparkle" size={24} />
          <div style={{ fontSize: 13, fontWeight: 600 }}>AI zanjirni tahlil qilmoqda…</div>
        </div>
      </div>
    );
  }

  const insights = (data && data.insights) || [];
  const apiError = (data && data.error) || null;

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 14, flexWrap: 'wrap', marginBottom: 16 }}>
        <AiHealth score={data && data.healthScore} />
        <button className="btn btn--ghost" onClick={() => load(true)} disabled={refreshing} style={{ gap: 8 }}>
          <Icon name="refresh" size={15} />
          {refreshing ? 'Tahlil qilinmoqda…' : 'Qayta tahlil'}
        </button>
      </div>

      {apiError && (
        <div style={{ background: 'rgba(232,115,95,.10)', border: '1px solid rgba(232,115,95,.35)', borderRadius: 'var(--r-lg)', padding: '14px 18px', marginBottom: 16, display: 'flex', gap: 12, alignItems: 'flex-start' }}>
          <span style={{ flex: 'none', color: '#C2453A' }}><Icon name="alert" size={17} /></span>
          <div>
            <div style={{ fontWeight: 700, fontSize: 13.5, color: '#C2453A' }}>AI tahlilini bajarib boʻlmadi</div>
            <div style={{ fontSize: 12.5, color: 'var(--ink-2)', marginTop: 3 }}>{apiError}</div>
          </div>
        </div>
      )}

      {data && data.summary && (
        <div style={{ background: 'linear-gradient(120deg, rgba(142,116,255,.08), rgba(142,116,255,.02))', border: '1px solid var(--border)', borderRadius: 'var(--r-lg)', padding: '14px 18px', marginBottom: 16, display: 'flex', gap: 12, alignItems: 'flex-start' }}>
          <span style={{ flex: 'none', color: '#5B45D6' }}><Icon name="sparkle" size={18} /></span>
          <div style={{ fontSize: 13.5, color: 'var(--ink-2)', lineHeight: 1.55 }}>{data.summary}</div>
        </div>
      )}

      {err && <div style={{ fontSize: 12.5, color: '#C2453A', marginBottom: 12 }}>{err}</div>}

      {insights.length > 0 ? (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 14 }}>
          {insights.map((it, i) => <AiInsightCard key={i} it={it} />)}
        </div>
      ) : (
        !loading && !err && <div style={{ fontSize: 13, color: 'var(--ink-4)', padding: 20 }}>Hozircha insayt yoʻq.</div>
      )}

      {data && data.generatedAt && (
        <div style={{ fontSize: 11, color: 'var(--ink-4)', marginTop: 16, textAlign: 'right' }}>
          Tahlil vaqti: {new Date(data.generatedAt).toLocaleString('ru-RU', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })}
          {data.cached ? ' · keshdan' : ''}
        </div>
      )}
    </div>
  );
}

// Kalit foydalanuvchi bo'yicha — bir foydalanuvchining chati boshqasiga ko'rinmaydi,
// ammo tarix saqlanib qoladi (localStorage brauzer ichida, har foydalanuvchi uchun alohida).
function aiChatKey(user) { return 'mm_ai_chat:' + ((user && user.id) || 'anon'); }

function AiChatPanel({ enabled, user }) {
  const CHAT_KEY = aiChatKey(user);
  const [messages, setMessages] = useState(() => {
    try { return JSON.parse(localStorage.getItem(CHAT_KEY) || '[]'); } catch { return []; }
  }); // {role, content}
  const [input, setInput] = useState('');
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);
  const [file, setFile] = useState(null); // biriktirilgan fayl {name,size,text,...}
  const scrollRef = useRef(null);
  const fileRef = useRef(null);

  async function pickFile(e) {
    const f = e.target.files && e.target.files[0];
    if (e.target) e.target.value = '';
    if (!f) return;
    setErr(null);
    try { setFile(await aiReadFile(f)); }
    catch (ex) { setErr(ex.message || 'Faylni oʻqib boʻlmadi'); }
  }

  function exportPdf() {
    if (!messages.length) return;
    aiExportPdf('AI Chat — suhbat', messages.map((m) => ({
      role: m.role,
      who: m.role === 'user' ? ((user && user.name) || 'Men') : 'AI analitik',
      color: m.role === 'user' ? '#5B45D6' : '#5A9FD4',
      attachment: m.attachment ? m.attachment.name : null,
      content: m.content,
    })));
  }

  // Foydalanuvchi almashganda (logout/login) tarixni yuklaymiz; davom etayotgan
  // so'rov bo'lsa — unga qayta ulanamiz (boshqa bo'limga o'tib qaytsa to'xtamaydi).
  useEffect(() => {
    let base = [];
    try { base = JSON.parse(localStorage.getItem(CHAT_KEY) || '[]'); } catch { base = []; }
    setMessages(base);
    const job = aiChatJobs[CHAT_KEY];
    if (job) {
      setMessages(job.snap.messages);
      setBusy(job.snap.busy);
      return job.subscribe((snap) => {
        setMessages(snap.messages);
        setBusy(snap.busy);
        if (snap.err) setErr(snap.err);
      });
    }
    setBusy(false);
  }, [CHAT_KEY]);

  // Tarixni saqlab boramiz — sahifa yangilansa ham yo'qolmaydi (oxirgi 40 ta)
  useEffect(() => {
    try { localStorage.setItem(CHAT_KEY, JSON.stringify(messages.slice(-40))); } catch { /* to'la bo'lsa e'tibor bermaymiz */ }
  }, [messages, CHAT_KEY]);

  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, busy]);

  function clearChat() {
    setMessages([]);
    try { localStorage.removeItem(CHAT_KEY); } catch { /* */ }
  }

  async function send(text) {
    const q = (text != null ? text : input).trim();
    const at = file;
    if ((!q && !at) || busy) return;
    setErr(null);
    setInput('');
    setFile(null);
    const userMsg = { role: 'user', content: q };
    if (at) userMsg.attachment = at;
    const next = [...messages, userMsg];
    // tezlik uchun oxirgi 12 ta; fayl mazmuni wire-content ichiga qo'shiladi
    const wire = next.slice(-12).map((m) => ({ role: m.role, content: aiWireContent(m) }));
    setMessages(next);
    setBusy(true);
    // So'rov modul darajasida yuritiladi — boshqa bo'limga o'tsa ham to'xtamaydi
    const job = aiStartChatJob(CHAT_KEY, next, wire);
    const unsub = job.subscribe((snap) => {
      setMessages(snap.messages);
      setBusy(snap.busy);
      if (snap.err) setErr(snap.err);
    });
    try { await job.promise; } finally { unsub(); }
  }

  if (!enabled) return <AiSetupNotice />;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}>
      {messages.length > 0 && (
        <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8, paddingBottom: 6 }}>
          <button onClick={exportPdf} title="Suhbatni PDF qilib yuklab olish" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 11.5, fontWeight: 600, padding: '4px 10px', borderRadius: 999, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink-3)', cursor: 'pointer' }}>
            <Icon name="download" size={12} /> PDF
          </button>
          <button onClick={clearChat} title="Suhbatni tozalash" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 11.5, fontWeight: 600, padding: '4px 10px', borderRadius: 999, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink-3)', cursor: 'pointer' }}>
            <Icon name="trash" size={12} /> Tozalash
          </button>
        </div>
      )}
      <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 12, padding: '4px 2px 12px' }}>
        {messages.length === 0 && (
          <div style={{ margin: 'auto', textAlign: 'center', color: 'var(--ink-4)', display: 'flex', flexDirection: 'column', gap: 14, maxWidth: 520 }}>
            <div style={{ width: 52, height: 52, borderRadius: 14, background: 'rgba(142,116,255,.12)', color: '#5B45D6', display: 'grid', placeItems: 'center', margin: '0 auto' }}>
              <Icon name="bot" size={24} />
            </div>
            <div style={{ fontSize: 14.5, fontWeight: 700, color: 'var(--ink)' }}>Distributsiya analitigi</div>
            <div style={{ fontSize: 12.5 }}>Platforma maʼlumotlari (zakaz, sell-out, zavod) asosida savol bering.</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, justifyContent: 'center', marginTop: 4 }}>
              {AI_SUGGESTIONS.map((s, i) => (
                <button key={i} onClick={() => send(s)} style={{ fontSize: 12, padding: '6px 12px', borderRadius: 999, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink-2)', cursor: 'pointer' }}>{s}</button>
              ))}
            </div>
          </div>
        )}
        {messages.map((m, i) => (
          <div key={i} className="ai-in" style={{ display: 'flex', justifyContent: m.role === 'user' ? 'flex-end' : 'flex-start' }}>
            <div style={{
              maxWidth: m.role === 'user' ? '80%' : '88%', padding: '10px 14px', borderRadius: 14,
              fontSize: 13.5, lineHeight: 1.55, wordBreak: 'break-word',
              whiteSpace: m.role === 'user' ? 'pre-wrap' : 'normal',
              background: m.role === 'user' ? 'var(--brand)' : 'var(--surface)',
              color: m.role === 'user' ? 'var(--surface)' : 'var(--ink)',
              border: m.role === 'user' ? 'none' : '1px solid var(--border)',
              borderBottomRightRadius: m.role === 'user' ? 4 : 14,
              borderBottomLeftRadius: m.role === 'user' ? 14 : 4,
            }}>
              {m.role === 'assistant' ? <AiMarkdown text={m.content} /> : (
                <div style={{ display: 'flex', flexDirection: 'column', gap: m.attachment ? 7 : 0 }}>
                  {m.content && <span>{m.content}</span>}
                  {m.attachment && <AiFileChip at={m.attachment} />}
                </div>
              )}
            </div>
          </div>
        ))}
        {busy && (
          <div className="ai-in" style={{ display: 'flex', justifyContent: 'flex-start' }}>
            <div style={{ padding: '11px 16px', borderRadius: 14, border: '1px solid var(--border)', background: 'var(--surface)' }}>
              <AiTyping label="Analitik tahlil qilmoqda" />
            </div>
          </div>
        )}
      </div>

      {err && <div style={{ fontSize: 12, color: '#C2453A', padding: '4px 2px' }}>{err}</div>}

      {file && (
        <div style={{ display: 'flex', padding: '6px 2px 0' }}>
          <AiFileChip at={file} onRemove={() => setFile(null)} />
        </div>
      )}

      <div style={{ display: 'flex', gap: 8, alignItems: 'flex-end', paddingTop: 8, borderTop: '1px solid var(--border)' }}>
        <input ref={fileRef} type="file" accept=".txt,.csv,.tsv,.md,.json,.log,.xml,.yaml,.yml,text/*" onChange={pickFile} style={{ display: 'none' }} />
        <button onClick={() => fileRef.current && fileRef.current.click()} title="Fayl biriktirish (matnli)" disabled={busy} className="btn btn--ghost" style={{ height: 44, padding: '0 12px' }}>
          <Icon name="clip" size={17} />
        </button>
        <textarea
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
          placeholder="Savolingizni yozing…"
          rows={1}
          style={{ flex: 1, resize: 'none', maxHeight: 120, padding: '11px 14px', borderRadius: 12, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink)', fontSize: 13.5, fontFamily: 'inherit', lineHeight: 1.5 }}
        />
        <button className="btn btn--primary" onClick={() => send()} disabled={busy || (!input.trim() && !file)} style={{ gap: 7, height: 44 }}>
          <Icon name="send" size={16} />
        </button>
      </div>
    </div>
  );
}

/* ============================================================
   Davra suhbati (round-table) — agentlar + moderator yakuniy xulosa
   ============================================================ */
function AiAgentBubble({ a }) {
  const initials = (a.name || '?').slice(0, 2).toUpperCase();
  return (
    <div className="ai-in" style={{ background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-lg)', padding: '14px 16px', boxShadow: 'var(--sh-1)' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
        <div style={{ width: 34, height: 34, borderRadius: 10, background: 'rgba(142,116,255,.14)', color: '#5B45D6', display: 'grid', placeItems: 'center', fontWeight: 800, fontSize: 12.5, flex: 'none' }}>{initials}</div>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontWeight: 700, fontSize: 13.5 }}>{a.name}</div>
          {a.title && <div style={{ fontSize: 11.5, color: 'var(--ink-4)' }}>{a.title}</div>}
        </div>
      </div>
      {a.error ? <div style={{ fontSize: 12.5, color: '#C2453A' }}>{a.error}</div> : <AiMarkdown text={a.text} />}
    </div>
  );
}

// Kalit foydalanuvchi bo'yicha — bir foydalanuvchining davra suhbati boshqasiga ko'rinmaydi,
// ammo tarix saqlanib qoladi.
function aiRtKey(user) { return 'mm_ai_roundtable:' + ((user && user.id) || 'anon'); }

// Agent avatari — emoji bo'lsa emoji, bo'lmasa bosh harflar
function rtFace(a) {
  return a && a.emoji && a.emoji.trim() ? a.emoji.trim() : ((a && a.name) || '?').slice(0, 2).toUpperCase();
}

// Suhbatdagi bitta bubble (rahbar / agent / moderator)
function RtBubble({ m }) {
  if (m.role === 'user') {
    return (
      <div className="ai-in" style={{ display: 'flex', justifyContent: 'flex-end' }}>
        <div style={{ maxWidth: '82%', padding: '10px 14px', borderRadius: 14, borderBottomRightRadius: 4, background: 'var(--brand)', color: 'var(--surface)', fontSize: 13.5, lineHeight: 1.55, whiteSpace: 'pre-wrap', wordBreak: 'break-word', display: 'flex', flexDirection: 'column', gap: m.attachment ? 7 : 0 }}>
          {m.content && <span>{m.content}</span>}
          {m.attachment && <AiFileChip at={m.attachment} />}
        </div>
      </div>
    );
  }
  const col = m.color || (m.isModerator ? '#3DBE9C' : '#8E74FF');
  return (
    <div className="ai-in" style={{ display: 'flex', justifyContent: 'flex-start' }}>
      <div style={{
        maxWidth: '94%', width: m.isModerator ? '100%' : 'auto', padding: '12px 15px', borderRadius: 14, borderBottomLeftRadius: 4,
        background: m.isModerator ? 'linear-gradient(120deg, rgba(61,190,156,.12), rgba(61,190,156,.02))' : 'var(--surface)',
        border: '1px solid ' + (m.isModerator ? 'rgba(61,190,156,.4)' : 'var(--border)'),
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 9, marginBottom: 7 }}>
          <div style={{ width: 30, height: 30, borderRadius: 9, background: col + '22', color: col, display: 'grid', placeItems: 'center', fontWeight: 800, fontSize: 13, flex: 'none' }}>{rtFace(m)}</div>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 700, fontSize: 13, color: col }}>{m.name}{m.isModerator && <span style={{ fontSize: 10.5, fontWeight: 700, marginLeft: 6, color: '#1D8A6E' }}>· yakuniy xulosa</span>}</div>
            {m.title && <div style={{ fontSize: 11, color: 'var(--ink-4)' }}>{m.title}</div>}
          </div>
        </div>
        {m.error ? <div style={{ fontSize: 12.5, color: '#C2453A' }}>{m.error}</div> : <AiMarkdown text={m.content} />}
      </div>
    </div>
  );
}

function RoundtablePanel({ enabled, perms, showToast, user }) {
  const RT_KEY = aiRtKey(user);
  const [agents, setAgents] = useState(null);     // sozlangan agentlar (selektor + identifikatsiya)
  const [messages, setMessages] = useState(() => {
    try { return JSON.parse(localStorage.getItem(RT_KEY) || '[]'); } catch { return []; }
  });
  const [input, setInput] = useState('');
  const [target, setTarget] = useState('all');    // 'all' yoki agent.id
  const [busy, setBusy] = useState(false);
  const [typing, setTyping] = useState(null);      // hozir kim yozyapti {name,emoji}
  const [err, setErr] = useState(null);
  const [manage, setManage] = useState(false);
  const [file, setFile] = useState(null);          // biriktirilgan fayl
  const scrollRef = useRef(null);
  const fileRef = useRef(null);

  async function pickFile(e) {
    const f = e.target.files && e.target.files[0];
    if (e.target) e.target.value = '';
    if (!f) return;
    setErr(null);
    try { setFile(await aiReadFile(f)); }
    catch (ex) { setErr(ex.message || 'Faylni oʻqib boʻlmadi'); }
  }

  async function loadAgents() {
    try { const r = await API.aiAgents(); setAgents(r.agents || []); }
    catch (ex) { setErr(ex.message || 'Agentlar yuklanmadi'); setAgents([]); }
  }
  useEffect(() => { if (enabled) loadAgents(); }, [enabled]); // eslint-disable-line

  // Foydalanuvchi almashganda tarixni yuklaymiz; davom etayotgan suhbat bo'lsa —
  // unga qayta ulanamiz (boshqa bo'limga o'tib qaytsa to'xtamaydi).
  useEffect(() => {
    let base = [];
    try { base = JSON.parse(localStorage.getItem(RT_KEY) || '[]'); } catch { base = []; }
    setMessages(base);
    const job = aiRtJobs[RT_KEY];
    if (job) {
      setMessages(job.snap.messages);
      setBusy(job.snap.busy);
      setTyping(job.snap.typing);
      return job.subscribe((snap) => {
        setMessages(snap.messages);
        setBusy(snap.busy);
        setTyping(snap.typing);
        if (snap.err) setErr(snap.err);
      });
    }
    setBusy(false);
    setTyping(null);
  }, [RT_KEY]);

  useEffect(() => {
    try { localStorage.setItem(RT_KEY, JSON.stringify(messages.slice(-60))); } catch { /* */ }
  }, [messages, RT_KEY]);
  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, typing, busy]);

  const list = agents || [];
  const participants = list.filter((a) => a.enabled && !a.isModerator);
  const moderator = list.find((a) => a.enabled && a.isModerator);
  const toWire = (m) => ({ role: m.role === 'user' ? 'user' : 'agent', name: m.name, title: m.title, content: aiWireContent(m) });

  function clearChat() {
    setMessages([]);
    try { localStorage.removeItem(RT_KEY); } catch { /* */ }
  }

  function exportPdf() {
    if (!messages.length) return;
    aiExportPdf('Davra suhbati — bayonnoma', messages.map((m) => ({
      role: m.role,
      moderator: !!m.isModerator,
      who: m.role === 'user' ? ((user && user.name) || 'Rahbar') : (m.name || 'Agent'),
      sub: m.role === 'user' ? null : (m.isModerator ? 'yakuniy xulosa' : (m.title || null)),
      color: m.role === 'user' ? '#5B45D6' : (m.color || (m.isModerator ? '#1D8A6E' : '#8E74FF')),
      attachment: m.attachment ? m.attachment.name : null,
      content: m.content,
    })));
  }

  async function send() {
    const q = input.trim();
    const at = file;
    if ((!q && !at) || busy) return;
    const targets = target === 'all' ? participants : participants.filter((a) => a.id === target);
    if (!targets.length) { setErr('Avval agent tanlang (yoki sozlamalardan qo`shing).'); return; }
    setErr(null);
    setInput('');
    setFile(null);
    const userMsg = { role: 'user', content: q };
    if (at) userMsg.attachment = at;
    const base = [...messages, userMsg];
    setMessages(base);
    setBusy(true);
    // Modul darajasida yuritiladi — boshqa bo'limga o'tsa ham suhbat to'xtamaydi
    const job = aiStartRtSendJob(RT_KEY, base, targets, toWire);
    const unsub = job.subscribe((snap) => {
      setMessages(snap.messages);
      setBusy(snap.busy);
      setTyping(snap.typing);
      if (snap.err) setErr(snap.err);
    });
    try { await job.promise; } finally { unsub(); setTyping(null); }
  }

  async function conclude() {
    if (busy || !messages.length) return;
    setErr(null);
    setBusy(true);
    const base = messages;
    const job = aiStartRtConcludeJob(RT_KEY, base, moderator ? moderator.id : undefined, moderator, toWire);
    const unsub = job.subscribe((snap) => {
      setMessages(snap.messages);
      setBusy(snap.busy);
      setTyping(snap.typing);
      if (snap.err) setErr(snap.err);
    });
    try { await job.promise; } finally { unsub(); setTyping(null); }
  }

  if (!enabled) return <AiSetupNotice />;

  const targetName = target === 'all' ? 'Hammasi' : (participants.find((a) => a.id === target) || {}).name || 'tanlang';

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}>
      {/* Yuqori panel — agent tanlash + boshqaruv */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', paddingBottom: 10, marginBottom: 4, borderBottom: '1px solid var(--border)' }}>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', flex: 1, minWidth: 0 }}>
          <button onClick={() => setTarget('all')} style={chipStyle(target === 'all')}>👥 Hammasi</button>
          {participants.map((a) => (
            <button key={a.id} onClick={() => setTarget(a.id)} style={chipStyle(target === a.id, a.color)}>
              <span style={{ marginRight: 4 }}>{rtFace(a)}</span>{a.name}
            </button>
          ))}
          {agents == null && <span style={{ fontSize: 12, color: 'var(--ink-4)' }}>Agentlar yuklanmoqda…</span>}
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
          {perms && perms.managePerms && (
            <button className="btn btn--ghost" onClick={() => setManage(true)} style={{ gap: 6, padding: '6px 11px', fontSize: 12.5 }}><Icon name="gear" size={14} /> Sozlash</button>
          )}
          {messages.length > 0 && (
            <button onClick={exportPdf} title="Suhbat va xulosani PDF qilib yuklab olish" className="btn btn--ghost" style={{ gap: 6, padding: '6px 11px', fontSize: 12.5, color: 'var(--ink-3)' }}><Icon name="download" size={13} /> PDF</button>
          )}
          {messages.length > 0 && (
            <button onClick={clearChat} className="btn btn--ghost" style={{ gap: 6, padding: '6px 11px', fontSize: 12.5, color: 'var(--ink-3)' }}><Icon name="trash" size={13} /> Tozalash</button>
          )}
        </div>
      </div>

      {/* Suhbat */}
      <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 12, padding: '10px 2px 12px' }}>
        {messages.length === 0 && (
          <div style={{ margin: 'auto', textAlign: 'center', color: 'var(--ink-4)', display: 'flex', flexDirection: 'column', gap: 12, maxWidth: 540 }}>
            <div style={{ width: 52, height: 52, borderRadius: 14, background: 'rgba(142,116,255,.12)', color: '#5B45D6', display: 'grid', placeItems: 'center', margin: '0 auto' }}><Icon name="users" size={24} /></div>
            <div style={{ fontSize: 14.5, fontWeight: 700, color: 'var(--ink)' }}>Davra suhbati — siz boshqarasiz</div>
            <div style={{ fontSize: 12.5, lineHeight: 1.6 }}>
              Yuqoridan agentni (yoki <b>Hammasi</b>ni) tanlang, savol yoki topshiriq yozing — ular platforma raqamlariga tayanib javob beradi.
              Suhbat tugagach <b>«Yakuniy xulosa»</b> tugmasini bossangiz, moderator hamma fikrni umumlashtiradi.
            </div>
            {participants.length > 0 && (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 7, justifyContent: 'center', marginTop: 2 }}>
                {['Hozirgi eng katta xavf nimada?', 'Qaysi regionlar orqada?', 'Nofaol dillerlar bo`yicha nima qilamiz?'].map((s, i) => (
                  <button key={i} onClick={() => setInput(s)} style={{ fontSize: 12, padding: '6px 12px', borderRadius: 999, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink-2)', cursor: 'pointer' }}>{s}</button>
                ))}
              </div>
            )}
          </div>
        )}
        {messages.map((m, i) => <RtBubble key={i} m={m} />)}
        {typing && (
          <div className="ai-in" style={{ display: 'flex', justifyContent: 'flex-start' }}>
            <div style={{ padding: '11px 15px', borderRadius: 14, border: '1px solid var(--border)', background: 'var(--surface)' }}>
              <AiTyping label={(typing.emoji ? typing.emoji + ' ' : '') + typing.name + ' o`ylayapti'} />
            </div>
          </div>
        )}
      </div>

      {err && <div style={{ fontSize: 12, color: '#C2453A', padding: '4px 2px' }}>{err}</div>}

      {/* Yakuniy xulosa */}
      {messages.length > 0 && (
        <div style={{ display: 'flex', justifyContent: 'center', paddingBottom: 8 }}>
          <button onClick={conclude} disabled={busy} style={{ display: 'inline-flex', alignItems: 'center', gap: 7, fontSize: 12.5, fontWeight: 700, padding: '7px 16px', borderRadius: 999, border: '1px solid rgba(61,190,156,.5)', background: 'rgba(61,190,156,.12)', color: '#1D8A6E', cursor: busy ? 'default' : 'pointer', opacity: busy ? 0.6 : 1 }}>
            <Icon name="sparkle" size={14} /> Bo`ldi, yakuniy xulosa qilamiz
          </button>
        </div>
      )}

      {/* Biriktirilgan fayl */}
      {file && (
        <div style={{ display: 'flex', padding: '0 2px 6px' }}>
          <AiFileChip at={file} onRemove={() => setFile(null)} />
        </div>
      )}

      {/* Kiritish */}
      <div style={{ display: 'flex', gap: 8, alignItems: 'flex-end', paddingTop: 8, borderTop: '1px solid var(--border)' }}>
        <input ref={fileRef} type="file" accept=".txt,.csv,.tsv,.md,.json,.log,.xml,.yaml,.yml,text/*" onChange={pickFile} style={{ display: 'none' }} />
        <button onClick={() => fileRef.current && fileRef.current.click()} title="Fayl biriktirish (matnli)" disabled={busy} className="btn btn--ghost" style={{ height: 44, padding: '0 12px' }}>
          <Icon name="clip" size={17} />
        </button>
        <textarea
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
          placeholder={'Xabaringiz (' + targetName + ' uchun)…'}
          rows={1}
          disabled={busy}
          style={{ flex: 1, resize: 'none', maxHeight: 120, padding: '11px 14px', borderRadius: 12, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink)', fontSize: 13.5, fontFamily: 'inherit', lineHeight: 1.5 }}
        />
        <button className="btn btn--primary" onClick={send} disabled={busy || (!input.trim() && !file)} style={{ gap: 7, height: 44 }}>
          <Icon name="send" size={16} />
        </button>
      </div>

      {manage && <AgentsManager onClose={() => setManage(false)} onSaved={loadAgents} showToast={showToast} />}
    </div>
  );
}

function chipStyle(on, color) {
  const c = color || '#8E74FF';
  return {
    display: 'inline-flex', alignItems: 'center', fontSize: 12, fontWeight: on ? 700 : 500,
    padding: '6px 12px', borderRadius: 999, cursor: 'pointer',
    border: '1px solid ' + (on ? c : 'var(--border)'),
    background: on ? c + '1f' : 'var(--surface)',
    color: on ? c : 'var(--ink-3)',
  };
}

// Bitta agent tahrirlash formasi
function AgentForm({ agent, scopes, saving, onSave, onCancel, onDelete }) {
  const [a, setA] = useState(agent);
  const set = (k, v) => setA((s) => ({ ...s, [k]: v }));
  const toggleScope = (key) => setA((s) => ({ ...s, scope: s.scope.includes(key) ? s.scope.filter((x) => x !== key) : [...s.scope, key] }));
  const inputStyle = { width: '100%', padding: '9px 12px', borderRadius: 10, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink)', fontSize: 13, fontFamily: 'inherit', boxSizing: 'border-box' };
  const label = (t) => <div style={{ fontSize: 11.5, fontWeight: 700, color: 'var(--ink-3)', margin: '12px 0 5px', textTransform: 'uppercase', letterSpacing: '.03em' }}>{t}</div>;
  const canSave = a.name.trim() && a.prompt.trim();
  return (
    <div>
      {label('Nomi')}
      <input style={inputStyle} value={a.name} onChange={(e) => set('name', e.target.value)} placeholder="Masalan: Analitik" />
      {label('Lavozim (ixtiyoriy)')}
      <input style={inputStyle} value={a.title || ''} onChange={(e) => set('title', e.target.value)} placeholder="Masalan: Savdo bo`limi boshlig`i" />
      {label('Rol / ko`rsatma')}
      <textarea style={{ ...inputStyle, minHeight: 120, resize: 'vertical', lineHeight: 1.5 }} value={a.prompt} onChange={(e) => set('prompt', e.target.value)} placeholder="Bu agent kim va nimaga e`tibor berishi kerak..." />
      {label("Qaysi ma'lumotlarni ko`radi")}
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
        {scopes.map((sc) => {
          const on = a.scope.includes(sc.key);
          return <button key={sc.key} type="button" onClick={() => toggleScope(sc.key)} style={{ fontSize: 12, padding: '6px 11px', borderRadius: 999, cursor: 'pointer', border: '1px solid ' + (on ? '#8E74FF' : 'var(--border)'), background: on ? 'rgba(142,116,255,.12)' : 'var(--surface)', color: on ? '#5B45D6' : 'var(--ink-3)', fontWeight: on ? 700 : 500 }}>{sc.label}</button>;
        })}
      </div>
      {a.isModerator && <div style={{ fontSize: 11.5, color: 'var(--ink-4)', marginTop: 6 }}>Moderator boshqalarning fikrini oladi — ma'lumot bo'lagi shart emas.</div>}

      {/* Ko'rinish */}
      <div style={{ display: 'flex', gap: 14, flexWrap: 'wrap' }}>
        <div style={{ width: 110 }}>
          {label('Belgi (emoji)')}
          <input style={inputStyle} value={a.emoji || ''} maxLength={4} onChange={(e) => set('emoji', e.target.value)} placeholder="📊" />
        </div>
        <div>
          {label('Rang')}
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <input type="color" value={a.color || '#8E74FF'} onChange={(e) => set('color', e.target.value)} style={{ width: 40, height: 36, padding: 2, borderRadius: 8, border: '1px solid var(--border)', background: 'var(--surface)', cursor: 'pointer' }} />
            {['#8E74FF', '#5A9FD4', '#E3A23B', '#3DBE9C', '#E8735F', '#A98CFF'].map((c) => (
              <button key={c} type="button" onClick={() => set('color', c)} title={c} style={{ width: 22, height: 22, borderRadius: 6, border: a.color === c ? '2px solid var(--ink)' : '1px solid var(--border)', background: c, cursor: 'pointer' }} />
            ))}
          </div>
        </div>
      </div>

      {/* Xulq-atvor */}
      {label('Ijodkorlik (temperatura): ' + Number(a.temperature ?? 0.4).toFixed(1))}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <span style={{ fontSize: 11, color: 'var(--ink-4)' }}>Aniq</span>
        <input type="range" min={0} max={1} step={0.1} value={a.temperature ?? 0.4} onChange={(e) => set('temperature', parseFloat(e.target.value))} style={{ flex: 1 }} />
        <span style={{ fontSize: 11, color: 'var(--ink-4)' }}>Ijodiy</span>
      </div>

      {label('Javob uzunligi (token): ' + (a.maxTokens ?? 1100))}
      <input type="range" min={400} max={4000} step={100} value={a.maxTokens ?? 1100} onChange={(e) => set('maxTokens', parseInt(e.target.value, 10))} style={{ width: '100%' }} />

      {label('Model (ixtiyoriy — bo`sh = platforma standarti)')}
      <input style={inputStyle} value={a.model || ''} onChange={(e) => set('model', e.target.value)} placeholder="masalan: claude-3-5-sonnet-...  (bo`sh qoldiring)" />

      <div style={{ display: 'flex', gap: 18, marginTop: 16, flexWrap: 'wrap' }}>
        <label style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 12.5, cursor: 'pointer' }}>
          <input type="checkbox" checked={a.enabled} onChange={(e) => set('enabled', e.target.checked)} /> Faol
        </label>
        <label style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 12.5, cursor: 'pointer' }}>
          <input type="checkbox" checked={a.isModerator} onChange={(e) => set('isModerator', e.target.checked)} /> Moderator (yakuniy xulosa)
        </label>
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', gap: 10, marginTop: 18 }}>
        <button onClick={() => onDelete(a)} className="btn btn--ghost" style={{ color: '#C2453A' }}>{a.id ? 'O`chirish' : 'Bekor'}</button>
        <div style={{ display: 'flex', gap: 8 }}>
          <button onClick={onCancel} className="btn btn--ghost">Bekor</button>
          <button onClick={() => onSave(a)} disabled={!canSave || saving} className="btn btn--primary">{saving ? 'Saqlanmoqda…' : 'Saqlash'}</button>
        </div>
      </div>
    </div>
  );
}

// Agentlarni boshqarish modali (managePerms)
function AgentsManager({ onClose, onSaved, showToast }) {
  const [agents, setAgents] = useState(null);
  const [scopes, setScopes] = useState([]);
  const [editing, setEditing] = useState(null);
  const [err, setErr] = useState(null);
  const [saving, setSaving] = useState(false);

  async function load() {
    try { const r = await API.aiAgents(); setAgents(r.agents || []); setScopes(r.scopes || []); }
    catch (ex) { setErr(ex.message || 'Yuklab bo`lmadi'); }
  }
  useEffect(() => { load(); }, []);

  function newAgent() {
    setEditing({ name: '', title: '', prompt: '', scope: [], isModerator: false, enabled: true, position: agents ? agents.length : 0, emoji: '', color: '#8E74FF', temperature: 0.4, maxTokens: 1100, model: '' });
  }

  async function save(a) {
    setSaving(true); setErr(null);
    try {
      const payload = {
        name: a.name, title: a.title, prompt: a.prompt, scope: a.scope,
        isModerator: !!a.isModerator, enabled: a.enabled !== false, position: a.position,
        emoji: a.emoji || '', color: a.color || '',
        temperature: a.temperature ?? 0.4, maxTokens: a.maxTokens ?? 1100, model: a.model || '',
      };
      if (a.id) await API.aiUpdateAgent(a.id, payload);
      else await API.aiCreateAgent(payload);
      setEditing(null);
      await load();
      if (onSaved) onSaved();
      if (showToast) showToast('Agent saqlandi');
    } catch (ex) { setErr(ex.message || 'Saqlanmadi'); }
    finally { setSaving(false); }
  }

  async function remove(a) {
    if (!a.id) { setEditing(null); return; }
    if (!confirm(a.name + ' agentini o`chirasizmi?')) return;
    setErr(null);
    try { await API.aiDeleteAgent(a.id); setEditing(null); await load(); if (onSaved) onSaved(); }
    catch (ex) { setErr(ex.message || 'O`chirilmadi'); }
  }

  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.4)', zIndex: 200, display: 'grid', placeItems: 'center', padding: 16 }}>
      <div onClick={(e) => e.stopPropagation()} style={{ width: 'min(720px, 96vw)', maxHeight: '88vh', overflowY: 'auto', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 16, padding: 18, boxShadow: 'var(--sh-2, 0 20px 60px rgba(0,0,0,.3))' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
          <div style={{ fontSize: 16, fontWeight: 800, display: 'flex', alignItems: 'center', gap: 8 }}><Icon name="bot" size={18} /> Davra suhbati agentlari</div>
          <button onClick={onClose} className="btn btn--ghost" style={{ padding: '6px 10px' }}><Icon name="x" size={16} /></button>
        </div>
        {err && <div style={{ fontSize: 12.5, color: '#C2453A', marginBottom: 10 }}>{err}</div>}

        {editing ? (
          <AgentForm agent={editing} scopes={scopes} saving={saving} onSave={save} onCancel={() => setEditing(null)} onDelete={remove} />
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {agents == null ? <div style={{ color: 'var(--ink-4)', fontSize: 13, padding: 12 }}>Yuklanmoqda…</div> :
              agents.map((a) => (
                <div key={a.id} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '10px 12px', border: '1px solid var(--border)', borderRadius: 12, opacity: a.enabled ? 1 : 0.5 }}>
                  <div style={{ width: 32, height: 32, borderRadius: 9, background: a.isModerator ? 'rgba(61,190,156,.16)' : 'rgba(142,116,255,.14)', color: a.isModerator ? '#1D8A6E' : '#5B45D6', display: 'grid', placeItems: 'center', fontWeight: 800, fontSize: 12, flex: 'none' }}>{(a.name || '?').slice(0, 2).toUpperCase()}</div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight: 700, fontSize: 13.5 }}>{a.name}{a.isModerator && <span style={{ fontSize: 10.5, color: '#1D8A6E', fontWeight: 700 }}> · moderator</span>}{!a.enabled && <span style={{ fontSize: 10.5, color: 'var(--ink-4)' }}> · o`chirilgan</span>}</div>
                    <div style={{ fontSize: 11.5, color: 'var(--ink-4)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{a.title || a.prompt.slice(0, 70)}</div>
                  </div>
                  <button onClick={() => setEditing(a)} className="btn btn--ghost" style={{ padding: '6px 10px', fontSize: 12 }}>Tahrirlash</button>
                </div>
              ))
            }
            <button onClick={newAgent} className="btn btn--ghost" style={{ gap: 7, marginTop: 4 }}><Icon name="plus" size={15} /> Yangi agent</button>
          </div>
        )}
      </div>
    </div>
  );
}

// Model tanlagich — kalitga MAVJUD modellardan birini tanlash (Railway env shart emas).
function AiModelPicker({ model, onChange }) {
  const [open, setOpen] = useState(false);
  const [models, setModels] = useState(null);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState(null);

  async function toggle() {
    const next = !open;
    setOpen(next);
    if (!next || models || loading) return;
    setLoading(true); setErr(null);
    try {
      const res = await API.aiModels();
      setModels(res.models || []);
    } catch (ex) {
      setErr(ex.message || 'Modellar olinmadi');
    } finally {
      setLoading(false);
    }
  }

  async function choose(id) {
    if (id === model) { setOpen(false); return; }
    setSaving(true); setErr(null);
    try {
      await API.aiSetModel(id);
      if (onChange) onChange(id);
      setOpen(false);
    } catch (ex) {
      setErr(ex.message || 'Saqlanmadi');
    } finally {
      setSaving(false);
    }
  }

  return (
    <span style={{ position: 'relative', display: 'inline-block' }}>
      <button onClick={toggle} title="AI modelni tanlash" style={{
        display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11.5, fontWeight: 600,
        padding: '3px 9px', borderRadius: 999, border: '1px solid var(--border)',
        background: 'var(--surface)', color: 'var(--ink-3)', cursor: 'pointer',
      }}>
        <Icon name="bot" size={12} />
        {saving ? 'Saqlanmoqda…' : (model || 'model tanlang')}
        <span style={{ fontSize: 9, opacity: .7 }}>▼</span>
      </button>
      {open && (
        <div style={{
          position: 'absolute', top: '100%', right: 0, marginTop: 6, zIndex: 50,
          minWidth: 260, maxHeight: 320, overflowY: 'auto',
          background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 12,
          boxShadow: 'var(--sh-2, 0 8px 28px rgba(0,0,0,.18))', padding: 6,
        }}>
          {loading && <div style={{ padding: 12, fontSize: 12, color: 'var(--ink-4)' }}>Yuklanmoqda…</div>}
          {err && <div style={{ padding: 12, fontSize: 12, color: '#C2453A' }}>{err}</div>}
          {!loading && !err && models && models.length === 0 && (
            <div style={{ padding: 12, fontSize: 12, color: 'var(--ink-4)' }}>Model topilmadi.</div>
          )}
          {!loading && models && models.map((m) => (
            <button key={m.id} onClick={() => choose(m.id)} disabled={saving} style={{
              display: 'block', width: '100%', textAlign: 'left', padding: '8px 10px', borderRadius: 8,
              border: 'none', cursor: 'pointer', fontSize: 12.5,
              background: m.id === model ? 'rgba(142,116,255,.12)' : 'transparent',
              color: m.id === model ? '#5B45D6' : 'var(--ink-2)', fontWeight: m.id === model ? 700 : 500,
            }}>
              {m.name}
              <div style={{ fontSize: 10.5, color: 'var(--ink-4)', fontWeight: 400 }}>{m.id}</div>
            </button>
          ))}
        </div>
      )}
    </span>
  );
}

function AiInsights({ perms, showToast, user }) {
  // Regional menejer — davra suhbati (roundtable) yopiq. AI Insights + AI Chat qoladi.
  const isRegional = !!(user && user.role === 'regional');
  const [tab, setTab] = useState('insights'); // insights | roundtable | chat
  const [status, setStatus] = useState(null); // {enabled, model}

  useEffect(() => {
    let alive = true;
    API.aiStatus().then((s) => { if (alive) setStatus(s); }).catch(() => { if (alive) setStatus({ enabled: false }); });
    return () => { alive = false; };
  }, []);

  // Roundtable tab regional uchun ko'rsatilmaydi — agar shu tabda turgan bo'lsa, insights'ga qaytaramiz.
  useEffect(() => {
    if (isRegional && tab === 'roundtable') setTab('insights');
  }, [isRegional, tab]);

  const enabled = !!(status && status.enabled);

  const tabs = [
    { key: 'insights', label: 'AI Insights', icon: 'sparkle' },
    ...(isRegional ? [] : [{ key: 'roundtable', label: 'Davra suhbati', icon: 'users' }]),
    { key: 'chat', label: 'AI Chat', icon: 'bot' },
  ];

  return (
    <div className="dash-wrap" style={{ padding: '8px 28px 24px', height: '100%', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 14, flexWrap: 'wrap', margin: '8px 0 14px' }}>
        <div>
          <h2 style={{ fontSize: 22, fontWeight: 700, letterSpacing: '-.02em', margin: 0, display: 'flex', alignItems: 'center', gap: 9 }}>
            <span style={{ color: '#8E74FF' }}><Icon name="sparkle" size={22} /></span>
            AI Insights
          </h2>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', margin: '5px 0 0' }}>
            <p style={{ fontSize: 12.5, margin: 0, color: 'var(--ink-4)' }}>
              Distributsiya analitigi — platforma maʼlumotlari asosida
            </p>
            {enabled && <AiModelPicker model={status && status.model} onChange={(m) => setStatus((s) => ({ ...(s || {}), model: m }))} />}
          </div>
        </div>
        <div style={{ display: 'inline-flex', gap: 4, background: 'var(--bg-soft, rgba(127,127,127,.08))', padding: 4, borderRadius: 12 }}>
          {tabs.map((t) => (
            <button key={t.key} onClick={() => setTab(t.key)} style={{
              display: 'inline-flex', alignItems: 'center', gap: 7, padding: '7px 14px', borderRadius: 9, border: 'none', cursor: 'pointer',
              fontSize: 13, fontWeight: 600,
              background: tab === t.key ? 'var(--surface)' : 'transparent',
              color: tab === t.key ? 'var(--ink)' : 'var(--ink-3)',
              boxShadow: tab === t.key ? 'var(--sh-1)' : 'none',
            }}>
              <Icon name={t.icon} size={15} />{t.label}
            </button>
          ))}
        </div>
      </div>

      <div style={{ flex: 1, minHeight: 0, overflowY: (tab === 'chat' || tab === 'roundtable') ? 'hidden' : 'auto', display: 'flex', flexDirection: 'column' }}>
        {status == null ? (
          <div style={{ display: 'grid', placeItems: 'center', padding: 50, color: 'var(--ink-4)', fontSize: 13 }}>Yuklanmoqda…</div>
        ) : tab === 'insights' ? (
          <AiInsightsPanel enabled={enabled} user={user} />
        ) : tab === 'roundtable' ? (
          <RoundtablePanel enabled={enabled} perms={perms} showToast={showToast} user={user} />
        ) : (
          <AiChatPanel enabled={enabled} user={user} />
        )}
      </div>
    </div>
  );
}

window.AiInsights = AiInsights;
