/* AAU CRM — Hệ thống: 7 màn quản trị port từ backend CQA gốc
   (Nguồn kết nối · AI Cost · Nhật ký hoạt động · MCP · Nhật ký thông báo · Agents · Dữ liệu mẫu)
   Mỗi màn map thẳng vào endpoint backend gốc — xem caption dưới tiêu đề. */

const FX_RATE = 25400; // USD→VND, đồng bộ với System Settings › Tỷ giá

function nowMinus(min) { return new Date(Date.now() - min * 60000).toISOString(); }
function fmtTime(iso) {
  const d = new Date(iso);
  const p = n => String(n).padStart(2, '0');
  return p(d.getDate()) + '/' + p(d.getMonth() + 1) + ' ' + p(d.getHours()) + ':' + p(d.getMinutes());
}

/* ───────────────────────── 1 · NGUỒN KẾT NỐI (Channels) ───────────────────────── */
const SYNC_CHANNELS = [
  { id: 'ch_fb', ch: 'fb', name: 'AAU Academy', handle: 'fb.com/aau.academy', status: 'connected', convs: 3420, lastSync: nowMinus(5), tokenDays: 58, mode: 'Mỗi 15 phút' },
  { id: 'ch_zalo', ch: 'zalo', name: 'AAU Academy OA', handle: 'OA · 400089...', status: 'connected', convs: 1862, lastSync: nowMinus(12), tokenDays: 21, mode: 'Sau mỗi lần đồng bộ' },
  { id: 'ch_ig', ch: 'instagram', name: 'aau.academy', handle: 'ig/aau.academy', status: 'error', convs: 740, lastSync: nowMinus(2880), tokenDays: -1, mode: 'Mỗi 30 phút' },
  { id: 'ch_tiktok', ch: 'tiktok', name: 'TikTok @aauacademy', handle: 'chưa hỗ trợ ingest', status: 'disconnected', convs: 0, lastSync: null, tokenDays: null, mode: '—' },
];
const SYNC_HISTORY = [
  { t: nowMinus(5), kind: 'Tự động', added: 34, status: 'ok', dur: '4,2s' },
  { t: nowMinus(20), kind: 'Sau đồng bộ', added: 12, status: 'ok', dur: '2,8s' },
  { t: nowMinus(35), kind: 'Thủ công', added: 58, status: 'ok', dur: '6,1s' },
  { t: nowMinus(95), kind: 'Tự động', added: 0, status: 'error', dur: '30s (timeout)' },
  { t: nowMinus(140), kind: 'Tự động', added: 21, status: 'ok', dur: '3,5s' },
];
const CH_STATUS = { connected: { tone: 'success', label: 'Đã kết nối', dot: true }, error: { tone: 'critical', label: 'Lỗi token' }, disconnected: { tone: 'neutral', label: 'Chưa kết nối' } };

// Form kết nối / sửa kênh — token thật do người dùng cấp; backend chỉ đánh dấu hasToken.
// Có `channel` ⇒ chế độ SỬA (prefill + PUT); không có ⇒ tạo mới (POST).
function ConnectChannelModal({ channel, onClose, onSubmit }) {
  const editing = !!channel;
  const [ch, setCh] = useState(channel ? channel.ch : 'zalo');
  const [name, setName] = useState(channel ? channel.name || '' : '');
  const [handle, setHandle] = useState(channel ? channel.handle || '' : '');
  const [mode, setMode] = useState(channel ? channel.mode || 'Mỗi 15 phút' : 'Mỗi 15 phút');
  const [token, setToken] = useState('');
  const [busy, setBusy] = useState(false);
  const chOpts = [
    { value: 'zalo', label: 'Zalo OA' }, { value: 'fb', label: 'Facebook Messenger' },
    { value: 'instagram', label: 'Instagram' }, { value: 'tiktok', label: 'TikTok' },
  ];
  const modeOpts = ['Mỗi 15 phút', 'Mỗi 30 phút', 'Mỗi giờ', 'Sau mỗi lần đồng bộ', 'Thủ công'].map(m => ({ value: m, label: m }));
  const submit = async () => {
    if (!name.trim() || busy) return;
    setBusy(true);
    try { await onSubmit({ ch, name: name.trim(), handle: handle.trim(), mode, token: token.trim() }); onClose(); }
    finally { setBusy(false); }
  };
  return (
    <Modal title={editing ? 'Sửa kênh' : 'Kết nối kênh mới'} width={520} onClose={onClose}
      footer={<><Button variant="plain" onClick={onClose}>Hủy</Button><Button variant="primary" icon={editing ? 'edit' : 'plus'} onClick={submit} disabled={busy || !name.trim()}>{busy ? 'Đang lưu…' : (editing ? 'Lưu thay đổi' : 'Kết nối')}</Button></>}>
      <Field label="Loại kênh"><Select value={ch} onChange={setCh} options={chOpts} /></Field>
      <Field label="Tên hiển thị"><Input value={name} onChange={setName} placeholder="VD: AAU Academy OA" autoFocus /></Field>
      <Field label="Định danh (handle · OA id · page)"><Input value={handle} onChange={setHandle} placeholder="OA · 400089...  hoặc  fb.com/aau.academy" /></Field>
      <Field label="Lịch đồng bộ"><Select value={mode} onChange={setMode} options={modeOpts} /></Field>
      <Field label={editing ? 'Đổi access token (để trống nếu giữ nguyên)' : 'Access token (tùy chọn)'}><Input value={token} onChange={setToken} type="password" placeholder="Dán token nền tảng nếu có" /></Field>
      <div className="t11 subtle mt8" style={{ lineHeight: 1.5 }}>Token thật của Zalo/FB do bạn cấp. App chỉ đánh dấu <b>đã có token</b> (production chuyển cho CQA / secret store), <b>không lưu</b> chuỗi token trong DB.</div>
    </Modal>
  );
}

function ChatChannels() {
  const live = !!(window.API && window.API.enabled);
  const [sel, setSel] = useState('ch_fb');
  const [list, setList] = useState(() => SYNC_CHANNELS.map(c => ({ ...c })));
  const [modal, setModal] = useState(null); // null = đóng · {} = tạo mới · {channel} = sửa
  const [testMsg, setTestMsg] = useState(null);

  const reload = () => { if (live && window.API) window.API.channels().then(cs => { if (Array.isArray(cs)) { setList(cs); setSel(cs[0] ? cs[0].id : null); } }).catch(() => {}); };
  useEffect(() => { reload(); }, []);
  const wipe = () => {
    if (!window.confirm('Xoá SẠCH toàn bộ hội thoại + kênh + lịch sử đồng bộ? (để chạy real data)')) return;
    const done = () => {
      setList([]); setSel(null); setTestMsg(null);
      if (window.AAU) AAU.conversations = {};                          // clear local để Inbox + badge về 0 ngay
      try { window.dispatchEvent(new Event('aau:conversations-changed')); } catch (e) {}
    };
    if (live && window.API && window.API.wipeChat) window.API.wipeChat().then(done).catch(() => {});
    else done();
  };

  const cur = list.find(c => c.id === sel) || list[0];
  const connected = list.filter(c => c.status === 'connected').length;
  const totalConvs = list.reduce((s, c) => s + (c.convs || 0), 0);

  const sync = id => {
    if (live) window.API.syncChannel(id).then(r => { if (r && r.channel) setList(ls => ls.map(c => c.id === id ? r.channel : c)); }).catch(() => {});
    else setList(ls => ls.map(c => c.id === id ? { ...c, lastSync: new Date().toISOString(), convs: c.convs + Math.floor(Math.random() * 20) } : c));
  };
  const reauth = id => { if (live) window.API.reauthChannel(id).then(rc => setList(ls => ls.map(c => c.id === id ? rc : c))).catch(() => {}); else setList(ls => ls.map(c => c.id === id ? { ...c, status: 'connected', tokenDays: 90 } : c)); };
  const test = id => {
    setTestMsg({ level: 'pending', text: 'Đang kiểm tra…' });
    if (live) window.API.testChannel(id).then(r => setTestMsg({ level: r.level || (r.ok ? 'ok' : 'fail'), text: r.detail })).catch(e => setTestMsg({ level: 'fail', text: 'Lỗi: ' + e.message }));
    else setTestMsg({ level: 'warn', text: 'Chế độ mock — không kiểm tra kết nối thật được.' });
  };
  const purge = id => { const after = ls => { const n = ls.filter(c => c.id !== id); if (sel === id && n[0]) setSel(n[0].id); return n; }; if (live) window.API.purgeChannel(id).then(() => setList(after)).catch(() => {}); else setList(after); };
  const create = async data => {
    if (live) { const nc = await window.API.createChannel(data); setList(ls => [...ls, nc]); setSel(nc.id); }
    else { const nc = { id: 'ch_' + Date.now(), ...data, status: 'connected', convs: 0, lastSync: null, tokenDays: 90, mode: data.mode || 'Mỗi 15 phút', syncHistory: [] }; setList(ls => [...ls, nc]); setSel(nc.id); }
  };
  const saveEdit = async data => {
    const id = (modal && modal.channel && modal.channel.id) || sel;
    if (live) { const uc = await window.API.updateChannel(id, data); if (uc && uc.id) setList(ls => ls.map(c => c.id === uc.id ? uc : c)); }
    else setList(ls => ls.map(c => c.id === id ? { ...c, ...data } : c));
  };
  const chMeta = ch => (AAU.channels && AAU.channels[ch]) || { color: '#8a8f98', short: (ch || '?').toUpperCase(), label: ch };
  const history = (cur && cur.syncHistory && cur.syncHistory.length) ? cur.syncHistory : SYNC_HISTORY;

  return (
    <div className="page wide">
      {modal && <ConnectChannelModal channel={modal.channel} onClose={() => setModal(null)} onSubmit={modal.channel ? saveEdit : create} />}
      <PageHead title="Nguồn kết nối" subtitle="Kênh chat (Zalo OA · Facebook · Instagram) đồng bộ về để chấm QC · backend: channels — test · sync · reauth · sync-history · purge"
        actions={<div className="row aic g8"><Button variant="plain" icon="trash" onClick={wipe}>Xoá dữ liệu chat</Button><Button variant="primary" icon="plus" onClick={() => setModal({})}>Kết nối kênh mới</Button></div>} />

      <div className="grid gc4 mb16">
        <KPI label="Kênh đã kết nối" value={connected + '/' + list.length} icon="message" />
        <KPI label="Hội thoại đã đồng bộ" value={AAU.fmtNum(totalConvs)} icon="inbox" />
        <KPI label="Đồng bộ gần nhất" value="5 phút" sub="Facebook Page" icon="refresh" />
        <KPI label="Token sắp hết hạn" value="1" sub="Instagram đã hết hạn" icon="alert" />
      </div>

      {list.length === 0 ? (
        <EmptyState icon="message" title="Chưa có kênh nào"
          desc="Đã xoá sạch để chạy real data. Thêm kênh thật rồi nối CQA (CQA_DB_DSN) + Đồng bộ để kéo tin nhắn thật vào Inbox."
          action={<Button variant="primary" icon="plus" onClick={() => setModal({})}>Kết nối kênh mới</Button>} />
      ) : (
      <div className="grid mb16" style={{ gridTemplateColumns: '1.15fr 1fr', alignItems: 'start' }}>
        <Card pad={false} title="Kênh chat">
          <table className="tbl">
            <thead><tr><th>Kênh</th><th>Trạng thái</th><th className="num">Hội thoại</th><th>Đồng bộ gần nhất</th><th></th></tr></thead>
            <tbody>
              {list.map(c => {
                const st = CH_STATUS[c.status]; const meta = chMeta(c.ch);
                return (
                  <tr key={c.id} onClick={() => setSel(c.id)} style={{ cursor: 'pointer', background: c.id === sel ? 'var(--p-bg-surface-secondary)' : undefined }}>
                    <td>
                      <div className="row aic g10">
                        <span className="center" style={{ width: 30, height: 30, borderRadius: 7, background: meta.color, color: '#fff', fontSize: 12, fontWeight: 700, flexShrink: 0 }}>{meta.short[0]}</span>
                        <div><div className="t13 fw6">{c.name}</div><div className="t11 subtle">{meta.label} · {c.handle}</div></div>
                      </div>
                    </td>
                    <td><Badge tone={st.tone} dot={st.dot}>{st.label}</Badge></td>
                    <td className="num t12">{c.convs ? AAU.fmtNum(c.convs) : '—'}</td>
                    <td className="t12 subtle">{c.lastSync ? AAU.relTime ? relTime(c.lastSync) : fmtTime(c.lastSync) : '—'}</td>
                    <td className="num"><Button size="sm" variant="plain" icon="chevronRight" /></td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </Card>

        <Card title={cur.name} subtitle={chMeta(cur.ch).label + ' · ' + cur.handle}
          actions={<Badge tone={CH_STATUS[cur.status].tone} dot={CH_STATUS[cur.status].dot}>{CH_STATUS[cur.status].label}</Badge>}>
          <div className="grid gc2 mb16">
            <div><div className="t11 subtle">Token</div><div className="t14 fw6" style={{ color: cur.tokenDays == null ? 'var(--p-text-subdued)' : cur.tokenDays < 0 ? '#c4320a' : cur.tokenDays < 30 ? '#9a6700' : '#0e7c4a' }}>{cur.tokenDays == null ? '—' : cur.tokenDays < 0 ? 'Đã hết hạn' : 'Còn ' + cur.tokenDays + ' ngày'}</div></div>
            <div><div className="t11 subtle">Lịch đồng bộ</div><div className="t14 fw6">{cur.mode}</div></div>
          </div>
          {cur.status === 'error' && <div className="row g8 mb16" style={{ padding: 12, borderRadius: 10, background: 'var(--p-critical-bg)' }}><Icon name="alert" size={18} color="#8e1f0b" /><div className="t12"><b>Token hết hạn.</b> Cần Reauth để tiếp tục đồng bộ hội thoại.</div></div>}
          <div className="row g8 mb16" style={{ flexWrap: 'wrap' }}>
            <Button variant="primary" size="sm" icon="refresh" onClick={() => sync(cur.id)} disabled={cur.status === 'disconnected'}>Đồng bộ ngay</Button>
            <Button size="sm" icon="edit" onClick={() => setModal({ channel: cur })}>Sửa</Button>
            <Button size="sm" icon="lock" onClick={() => reauth(cur.id)}>Reauth</Button>
            <Button size="sm" variant="plain" onClick={() => test(cur.id)}>Test kết nối</Button>
            <Button size="sm" variant="plain" icon="trash" onClick={() => purge(cur.id)}>Purge</Button>
          </div>
          {testMsg && (() => {
            const M = { ok: ['checkCircle', '#0a7d4f', 'var(--p-success-bg)'], warn: ['alert', '#9a6700', 'var(--p-warning-bg)'], fail: ['alert', '#c4320a', 'var(--p-critical-bg)'], pending: ['refresh', '#6b7280', 'var(--p-bg-surface-secondary)'] };
            const [ic, col, bg] = M[testMsg.level] || M.pending;
            return <div className="row aic g8 mb16 t12" style={{ padding: '8px 11px', borderRadius: 9, background: bg }}><Icon name={ic} size={14} color={col} /><span style={{ lineHeight: 1.5 }}>{testMsg.text}</span></div>;
          })()}
          <div className="t11 fw7 subtle mb8">LỊCH SỬ ĐỒNG BỘ</div>
          <table className="tbl">
            <thead><tr><th>Thời điểm</th><th>Loại</th><th className="num">Tin mới</th><th className="num">Trạng thái</th></tr></thead>
            <tbody>{history.map((h, i) => <tr key={i}><td className="t12">{fmtTime(h.t)}</td><td className="t12 muted">{h.kind}</td><td className="num t12">{h.added}</td><td className="num">{h.status === 'ok' ? <Badge tone="success">{h.dur}</Badge> : <Badge tone="critical">{h.dur}</Badge>}</td></tr>)}</tbody>
          </table>
        </Card>
      </div>
      )}

      <div style={{ marginTop: 16 }}><AdsSourcesSection /></div>
    </div>
  );
}

// Nguồn quảng cáo (Ads) — cùng trang Nguồn kết nối nhưng TÁCH namespace với kênh chat
// (Quyết định #2: chat = Inbox/QC · ads = đo hiệu quả Marketing). Tái dùng cổng FB Ads.
function AdsSourcesSection() {
  const live = !!(window.API && window.API.enabled);
  const [conn, setConn] = useState(null);
  const [tick, setTick] = useState(0);
  const [showConn, setShowConn] = useState(false);
  useEffect(() => { if (live && window.API.adsConn) window.API.adsConn().then(setConn).catch(() => { }); }, [live, tick]);
  const connected = !!(conn && conn.connected);
  const hasModal = typeof FbAdsConnectModal !== 'undefined';
  return (
    <Card title="Nguồn quảng cáo (Ads)" subtitle="Kéo chi phí/hiệu suất ads về Marketing. Tách khỏi kênh chat ở trên — chat = Inbox/QC, ads = đo hiệu quả.">
      {showConn && hasModal && <FbAdsConnectModal conn={conn} onClose={() => setShowConn(false)} onSaved={() => setTick(n => n + 1)} />}
      <table className="tbl">
        <thead><tr><th>Nền tảng</th><th>Trạng thái</th><th>Tài khoản</th><th>Token</th><th></th></tr></thead>
        <tbody>
          <tr>
            <td><div className="row aic g10"><span className="center" style={{ width: 30, height: 30, borderRadius: 7, background: '#0084ff', color: '#fff', fontSize: 12, fontWeight: 700 }}>F</span><div className="t13 fw6">Facebook Ads</div></div></td>
            <td>{connected ? <Badge tone="success" dot>Đã kết nối</Badge> : <Badge tone="neutral">Chưa kết nối</Badge>}</td>
            <td className="t12">{connected ? (conn.accountName || conn.adAccount) : '—'}</td>
            <td className="t12 subtle">{connected ? (conn.tokenMask || '••••') : '—'}</td>
            <td className="num"><Button size="sm" variant={connected ? 'plain' : 'primary'} icon={connected ? 'edit' : 'lock'} onClick={() => setShowConn(true)} disabled={!live}>{connected ? 'Sửa' : 'Kết nối'}</Button></td>
          </tr>
          <tr style={{ opacity: 0.55 }}>
            <td><div className="row aic g10"><span className="center" style={{ width: 30, height: 30, borderRadius: 7, background: '#9aa0a6', color: '#fff', fontSize: 12, fontWeight: 700 }}>G</span><div className="t13 fw6">Google / TikTok Ads</div></div></td>
            <td><Badge tone="neutral">Sắp hỗ trợ</Badge></td>
            <td className="t12">—</td><td className="t12">—</td><td></td>
          </tr>
        </tbody>
      </table>
      <div className="t11 subtle mt8">{live ? 'Cổng này gắn 1 lần (token ads_read + ad account), sống qua restart. Cũng có ở Marketing → Ad Tracking.' : 'Bật LIVE (?api=http://localhost:8080) để kết nối nguồn ads thật.'}</div>
    </Card>
  );
}

/* ───────────────────────── 2 · AI COST (cost_logs) ───────────────────────── */
const COST_LOGS = [
  { t: nowMinus(8), provider: 'claude', model: 'claude-sonnet-4', tin: 18240, tout: 3120, usd: 0.0962 },
  { t: nowMinus(46), provider: 'claude', model: 'claude-sonnet-4', tin: 22150, tout: 4080, usd: 0.1183 },
  { t: nowMinus(92), provider: 'gemini', model: 'gemini-2.5-flash', tin: 31200, tout: 5400, usd: 0.0146 },
  { t: nowMinus(140), provider: 'claude', model: 'claude-haiku-3.5', tin: 12800, tout: 2200, usd: 0.0184 },
  { t: nowMinus(220), provider: 'gemini', model: 'gemini-2.5-pro', tin: 28400, tout: 6100, usd: 0.0712 },
  { t: nowMinus(300), provider: 'claude', model: 'claude-sonnet-4', tin: 19600, tout: 3640, usd: 0.1042 },
];
const COST_BY_DAY = [
  { l: '28/5', v: 1.82, color: '#7c3aed' }, { l: '29/5', v: 2.41, color: '#7c3aed' }, { l: '30/5', v: 1.96, color: '#7c3aed' },
  { l: '31/5', v: 3.12, color: '#7c3aed' }, { l: '01/6', v: 2.74, color: '#7c3aed' }, { l: '02/6', v: 2.18, color: '#0084ff' },
];

function AICost() {
  const [provider, setProvider] = useState('all');
  const rows = COST_LOGS.filter(r => provider === 'all' || r.provider === provider);
  const totalUsd = rows.reduce((s, r) => s + r.usd, 0);
  const totalTok = rows.reduce((s, r) => s + r.tin + r.tout, 0);
  const monthUsd = 14.23;
  return (
    <div className="page wide">
      <PageHead title="AI Cost" subtitle="Chi phí token mỗi lần gọi AI (Claude / Gemini) · backend: cost-logs · nguồn cho dòng “CP Hệ thống & AI” của Finance"
        actions={<Button icon="download">Xuất CSV</Button>} />
      <div className="grid gc4 mb16">
        <KPI label="Chi phí tháng 6" value={'$' + monthUsd.toFixed(2)} sub={AAU.fmtVND(monthUsd * FX_RATE)} icon="dollar" />
        <KPI label="Tổng token" value={(totalTok / 1000).toFixed(0) + 'K'} sub="input + output" icon="sparkles" />
        <KPI label="Số lần gọi" value={rows.length} sub="trong bộ lọc" icon="robot" />
        <KPI label="TB / hội thoại" value="$0,018" sub={'≈ ' + AAU.fmtVND(457)} icon="message" />
      </div>
      <Card title="Chi phí theo ngày" subtitle="USD · 7 ngày gần nhất" className="mb16"><BarChart data={COST_BY_DAY} height={170} /></Card>
      <Card pad={false} title="Nhật ký chi phí AI"
        actions={<div className="row g8 aic">
          <Seg value={provider} onChange={setProvider} options={[{ value: 'all', label: 'Tất cả' }, { value: 'claude', label: 'Claude' }, { value: 'gemini', label: 'Gemini' }]} />
          <Input icon="calendar" value="Tháng 6/2026" onChange={() => {}} style={{ width: 150 }} />
        </div>}>
        <table className="tbl">
          <thead><tr><th>Thời điểm</th><th>Provider</th><th>Model</th><th className="num">Input</th><th className="num">Output</th><th className="num">USD</th><th className="num">VND</th></tr></thead>
          <tbody>
            {rows.map((r, i) => (
              <tr key={i}>
                <td className="t12">{fmtTime(r.t)}</td>
                <td><Badge tone={r.provider === 'claude' ? 'magic' : 'info'}>{r.provider}</Badge></td>
                <td className="t12 muted" style={{ fontFamily: 'var(--p-font-mono)', fontSize: 11 }}>{r.model}</td>
                <td className="num t12">{AAU.fmtNum(r.tin)}</td>
                <td className="num t12">{AAU.fmtNum(r.tout)}</td>
                <td className="num t12 fw6">${r.usd.toFixed(4)}</td>
                <td className="num t12">{AAU.fmtVND(r.usd * FX_RATE)}</td>
              </tr>
            ))}
          </tbody>
          <tfoot><tr style={{ fontWeight: 700, background: 'var(--p-bg-surface-secondary)' }}><td colSpan={5} className="num">Tổng:</td><td className="num">${totalUsd.toFixed(4)}</td><td className="num">{AAU.fmtVND(totalUsd * FX_RATE)}</td></tr></tfoot>
        </table>
      </Card>
    </div>
  );
}

/* ───────────────────────── 3 · NHẬT KÝ HOẠT ĐỘNG (activity_logs) ───────────────────────── */
const ACT_META = {
  'job.run': { tone: 'info', label: 'Chạy job' }, 'job.create': { tone: 'success', label: 'Tạo job' },
  'job.delete': { tone: 'warning', label: 'Xóa job' }, 'ai.error': { tone: 'critical', label: 'Lỗi AI' },
  'notification': { tone: 'info', label: 'Thông báo' }, 'settings': { tone: 'neutral', label: 'Cài đặt' },
  'channel.sync': { tone: 'info', label: 'Đồng bộ kênh' }, 'auth.login': { tone: 'neutral', label: 'Đăng nhập' },
};
const ACT_LOGS = [
  { t: nowMinus(4), action: 'job.run', user: 'system', detail: 'Job "Chấm QC chat ngoài giờ" chạy · 42 hội thoại · 38 PASS / 4 FAIL', err: null },
  { t: nowMinus(18), action: 'channel.sync', user: 'system', detail: 'Đồng bộ Facebook Page · +34 tin nhắn mới', err: null },
  { t: nowMinus(33), action: 'settings', user: 'thu.nguyen@aau.vn', detail: 'Cập nhật model chấm QC: claude-haiku → claude-sonnet-4', err: null },
  { t: nowMinus(70), action: 'ai.error', user: 'system', detail: 'Gọi Gemini thất bại khi chấm batch #1182', err: 'rate_limit_exceeded (429)' },
  { t: nowMinus(95), action: 'channel.sync', user: 'system', detail: 'Đồng bộ Instagram thất bại', err: 'token expired' },
  { t: nowMinus(140), action: 'job.create', user: 'an.le@aau.vn', detail: 'Tạo job "Phân loại chủ đề inbox" (classification)', err: null },
  { t: nowMinus(220), action: 'notification', user: 'system', detail: 'Gửi cảnh báo FAIL qua Telegram → nhóm QC HCM', err: null },
  { t: nowMinus(300), action: 'auth.login', user: 'thu.nguyen@aau.vn', detail: 'Đăng nhập từ IP 14.161.xx.xx', err: null },
  { t: nowMinus(360), action: 'job.delete', user: 'an.le@aau.vn', detail: 'Xóa job test "demo-qc-2"', err: null },
];

function ActivityLog() {
  const [filter, setFilter] = useState('all');
  const opts = [{ value: 'all', label: 'Tất cả hành động' }, ...Object.keys(ACT_META).map(k => ({ value: k, label: ACT_META[k].label }))];
  const rows = ACT_LOGS.filter(r => filter === 'all' || r.action === filter);
  return (
    <div className="page wide">
      <PageHead title="Nhật ký hoạt động" subtitle="Ai · làm gì · khi nào — phục vụ audit & truy vết lỗi · backend: activity-logs"
        actions={<Select value={filter} onChange={setFilter} options={opts} style={{ width: 200 }} />} />
      <Card pad={false}>
        <table className="tbl">
          <thead><tr><th>Thời điểm</th><th>Hành động</th><th>Người</th><th>Chi tiết</th><th>Lỗi</th></tr></thead>
          <tbody>
            {rows.map((r, i) => {
              const m = ACT_META[r.action];
              return (
                <tr key={i}>
                  <td className="t12 subtle" style={{ whiteSpace: 'nowrap' }}>{fmtTime(r.t)}</td>
                  <td><Badge tone={m.tone}>{m.label}</Badge></td>
                  <td className="t12">{r.user === 'system' ? <span className="subtle">system</span> : r.user}</td>
                  <td className="t12 muted" style={{ maxWidth: 440 }}>{r.detail}</td>
                  <td>{r.err && <Badge tone="critical">{r.err}</Badge>}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </Card>
    </div>
  );
}

/* ───────────────────────── 4 · MCP CONNECTIONS (mcp/clients) ───────────────────────── */
function MCPConnections() {
  const [clients, setClients] = useState([
    { id: 'm1', name: 'Claude Web', client_id: 'mcp_a1b2c3d4e5', redirect: ['https://claude.ai/api/mcp/auth_callback'], scopes: ['read', 'write'], created: '2026-05-21T09:12:00' },
    { id: 'm2', name: 'Claude Desktop — máy Thu', client_id: 'mcp_f6g7h8i9j0', redirect: ['http://localhost:5173/callback'], scopes: ['read'], created: '2026-05-28T14:40:00' },
  ]);
  const [modal, setModal] = useState(false);
  const revoke = id => setClients(cs => cs.filter(c => c.id !== id));
  return (
    <div className="page wide">
      <PageHead title="MCP Connections" subtitle="Cho phép Claude Web/Desktop truy vấn dữ liệu qua giao thức MCP · backend: mcp/clients + OAuth 2.0"
        actions={<Button variant="primary" icon="plus" onClick={() => setModal(true)}>Tạo kết nối</Button>} />
      <div className="row g8 mb16" style={{ padding: 14, borderRadius: 12, background: 'var(--p-bg-surface-secondary)' }}>
        <Icon name="externalLink" size={18} color="#7c3aed" />
        <div className="t12 muted">Mỗi kết nối cấp một <b>client_id</b> + <b>secret</b> để nối Claude. Cấu hình Redirect URI khớp với <code style={{ fontSize: 11 }}>claude.ai/api/mcp/auth_callback</code> và scope read/write.</div>
      </div>
      <Card pad={false}>
        <table className="tbl">
          <thead><tr><th>Tên</th><th>Client ID</th><th>Redirect URIs</th><th>Scopes</th><th>Tạo lúc</th><th></th></tr></thead>
          <tbody>
            {clients.map(c => (
              <tr key={c.id}>
                <td className="t13 fw6">{c.name}</td>
                <td style={{ fontFamily: 'var(--p-font-mono)', fontSize: 11 }} className="muted">{c.client_id}</td>
                <td>{c.redirect.map(u => <span key={u} className="tag" style={{ fontSize: 10.5 }}>{u}</span>)}</td>
                <td><div className="row g6">{c.scopes.map(s => <Badge key={s} tone={s === 'write' ? 'magic' : 'info'}>{s}</Badge>)}</div></td>
                <td className="t12 subtle">{AAU.fmtDate(c.created.slice(0, 10))}</td>
                <td className="num"><Button size="sm" variant="plain" icon="trash" onClick={() => revoke(c.id)}>Thu hồi</Button></td>
              </tr>
            ))}
            {clients.length === 0 && <tr><td colSpan={6}><div className="empty" style={{ padding: 28 }}><div className="et">Chưa có kết nối MCP</div><div className="ed">Tạo kết nối để Claude truy vấn dữ liệu CQA.</div></div></td></tr>}
          </tbody>
        </table>
      </Card>
      {modal && <MCPCreateModal onClose={() => setModal(false)} onCreate={c => setClients(cs => [c, ...cs])} />}
    </div>
  );
}

function MCPCreateModal({ onClose, onCreate }) {
  const [name, setName] = useState('');
  const [redirect, setRedirect] = useState('https://claude.ai/api/mcp/auth_callback');
  const [scopes, setScopes] = useState(['read', 'write']);
  const [gen, setGen] = useState(null);
  const toggleScope = s => setScopes(ss => ss.includes(s) ? ss.filter(x => x !== s) : [...ss, s]);
  const generate = () => {
    const cid = 'mcp_' + Math.random().toString(36).slice(2, 12);
    const secret = 'sk_mcp_' + Math.random().toString(36).slice(2, 14) + Math.random().toString(36).slice(2, 10);
    setGen({ client_id: cid, secret });
    onCreate({ id: 'm' + Date.now(), name, client_id: cid, redirect: [redirect], scopes, created: new Date().toISOString() });
  };
  return (
    <Modal title="Tạo kết nối MCP" onClose={onClose} width={560}
      footer={gen ? <Button variant="primary" onClick={onClose}>Đóng</Button> : <><Button onClick={onClose}>Hủy</Button><Button variant="primary" onClick={generate} disabled={!name.trim()}>Tạo kết nối</Button></>}>
      {!gen ? (
        <div className="col g16">
          <Field label="Tên kết nối"><Input value={name} onChange={setName} placeholder="VD: Claude Web" autoFocus /></Field>
          <Field label="Redirect URI"><Input value={redirect} onChange={setRedirect} placeholder="https://claude.ai/api/mcp/auth_callback" /></Field>
          <Field label="Phân quyền (scopes)">
            <div className="col g8">
              {[['read', 'Đọc dữ liệu (hội thoại, điểm QC, vi phạm)'], ['write', 'Ghi / kích hoạt (chạy job, đồng bộ)']].map(([s, d]) => (
                <div key={s} className="row aic g10" style={{ padding: 10, borderRadius: 10, border: '1px solid var(--p-border)' }} onClick={() => toggleScope(s)}>
                  <Checkbox on={scopes.includes(s)} onChange={() => toggleScope(s)} />
                  <div><div className="t13 fw6">{s}</div><div className="t11 subtle">{d}</div></div>
                </div>
              ))}
            </div>
          </Field>
        </div>
      ) : (
        <div className="col g16">
          <div className="row g8" style={{ padding: 12, borderRadius: 10, background: 'var(--p-warning-bg)', color: 'var(--p-warning-text)' }}><Icon name="alert" size={18} /><div className="t12"><b>Secret chỉ hiện 1 lần.</b> Hãy copy ngay — sau khi đóng sẽ không xem lại được.</div></div>
          <Field label="Client ID"><div style={{ fontFamily: 'var(--p-font-mono)', fontSize: 13, padding: '10px 12px', borderRadius: 8, background: 'var(--p-bg-surface-secondary)' }}>{gen.client_id}</div></Field>
          <Field label="Client Secret"><div style={{ fontFamily: 'var(--p-font-mono)', fontSize: 13, padding: '10px 12px', borderRadius: 8, background: 'var(--p-bg-surface-secondary)', color: '#c4320a' }}>{gen.secret}</div></Field>
        </div>
      )}
    </Modal>
  );
}

/* ───────────────────────── 5 · NHẬT KÝ THÔNG BÁO (notification_logs) ───────────────────────── */
const NOTIF_LOGS = [
  { id: 'n1', t: nowMinus(6), channel: 'telegram', to: 'Nhóm QC HCM', status: 'sent', subject: null, body: '⚠️ 4 hội thoại FAIL QC hôm nay. Top vi phạm: "Báo giá khi chưa qualify". Xem chi tiết tại CQA › QC Review.' },
  { id: 'n2', t: nowMinus(70), channel: 'email', to: 'thu.nguyen@aau.vn', status: 'sent', subject: 'Báo cáo QC cuối ngày 02/06', body: 'Tổng 42 hội thoại đã chấm · Pass rate 90% · Điểm TB 7.8. Chi tiết trong file đính kèm.' },
  { id: 'n3', t: nowMinus(190), channel: 'telegram', to: 'Nhóm QC HCM', status: 'error', subject: null, body: 'Cảnh báo job treo', },
  { id: 'n4', t: nowMinus(320), channel: 'email', to: 'an.le@aau.vn', status: 'sent', subject: 'Job hoàn tất', body: 'Job "Phân loại chủ đề inbox" đã chạy xong: 128 hội thoại được gắn thẻ.' },
];

function NotificationLog() {
  const [exp, setExp] = useState(null);
  return (
    <div className="page wide">
      <PageHead title="Nhật ký thông báo" subtitle="Cảnh báo Telegram / Email khi job phát hiện vi phạm · backend: notification-logs" />
      <Card pad={false}>
        <table className="tbl">
          <thead><tr><th>Thời điểm</th><th>Kênh</th><th>Người nhận</th><th className="num">Trạng thái</th><th></th></tr></thead>
          <tbody>
            {NOTIF_LOGS.map(n => (
              <React.Fragment key={n.id}>
                <tr>
                  <td className="t12 subtle" style={{ whiteSpace: 'nowrap' }}>{fmtTime(n.t)}</td>
                  <td><Badge tone={n.channel === 'telegram' ? 'info' : 'warning'}><Icon name={n.channel === 'telegram' ? 'send' : 'mail'} size={12} />{n.channel}</Badge></td>
                  <td className="t12">{n.to}</td>
                  <td className="num">{n.status === 'sent' ? <Badge tone="success" dot>Đã gửi</Badge> : <Badge tone="critical">Lỗi</Badge>}</td>
                  <td className="num"><Button size="sm" variant="plain" icon="eye" onClick={() => setExp(exp === n.id ? null : n.id)}>{exp === n.id ? 'Ẩn' : 'Xem'}</Button></td>
                </tr>
                {exp === n.id && <tr><td colSpan={5} style={{ background: 'var(--p-bg-surface-secondary)' }}>
                  <div style={{ padding: '4px 2px' }}>
                    {n.subject && <div className="t11 subtle mb4">Tiêu đề: <b>{n.subject}</b></div>}
                    <div className="t12" style={{ whiteSpace: 'pre-wrap', padding: 12, borderRadius: 8, background: 'var(--p-bg-surface)', border: '1px solid var(--p-border)' }}>{n.body}</div>
                    {n.status === 'error' && <div className="t12 mt8" style={{ color: '#c4320a' }}>Lỗi: bot không có quyền gửi vào group (chat not found)</div>}
                  </div>
                </td></tr>}
              </React.Fragment>
            ))}
          </tbody>
        </table>
      </Card>
    </div>
  );
}

/* ───────────────────────── 6 · AGENTS CENTER (agents API) ───────────────────────── */
const AGENTS = [
  { name: 'cqa.sync', version: '1.0.0', health: 'healthy', desc: 'Đồng bộ tin nhắn từ kênh ngoài (Zalo OA, Facebook) vào CQA', caps: ['sync_all', 'sync_channel', 'query:conversations', 'query:messages'], lastRun: nowMinus(18), runs: 142 },
  { name: 'cqa.qc', version: '1.0.0', health: 'healthy', desc: 'Chấm chất lượng CSKH theo bộ quy tắc bằng AI', caps: ['analyze_quality', 'query:violations', 'query:scores'], lastRun: nowMinus(4), runs: 388 },
  { name: 'cqa.classify', version: '1.0.0', health: 'idle', desc: 'Phân loại & gắn thẻ hội thoại bằng AI theo luật', caps: ['classify_conversations', 'query:tags', 'query:rules'], lastRun: nowMinus(140), runs: 96 },
];
const AGENT_RUNS = [
  { t: nowMinus(4), agent: 'cqa.qc', action: 'analyze_quality', status: 'success', summary: '42 hội thoại · 4 vi phạm' },
  { t: nowMinus(18), agent: 'cqa.sync', action: 'sync_all', status: 'success', summary: '+67 tin nhắn / 3 kênh' },
  { t: nowMinus(140), agent: 'cqa.classify', action: 'classify_conversations', status: 'partial', summary: '128 gắn thẻ · 2 lỗi' },
];
const HEALTH = { healthy: { tone: 'success', label: 'Healthy', dot: true }, idle: { tone: 'neutral', label: 'Nghỉ' }, error: { tone: 'critical', label: 'Lỗi' } };

function AgentsCenter() {
  return (
    <div className="page wide">
      <PageHead title="Agents Center" subtitle="Cổng tích hợp “Company OS” — chạy & truy vấn năng lực AI của CQA · backend: /agents (run · query · health)"
        actions={<Button icon="book">Tài liệu API</Button>} />
      <div className="grid gc3 mb16">
        {AGENTS.map(a => {
          const h = HEALTH[a.health];
          return (
            <Card key={a.name}>
              <div className="row jcsb aic mb8">
                <div className="row aic g8"><span className="center" style={{ width: 32, height: 32, borderRadius: 8, background: 'var(--p-bg-surface-tertiary)', color: '#7c3aed' }}><Icon name="robot" size={17} /></span>
                  <div><div className="t13 fw7" style={{ fontFamily: 'var(--p-font-mono)' }}>{a.name}</div><div className="t11 subtle">v{a.version}</div></div></div>
                <Badge tone={h.tone} dot={h.dot}>{h.label}</Badge>
              </div>
              <div className="t12 muted" style={{ lineHeight: 1.45, minHeight: 34 }}>{a.desc}</div>
              <div className="t11 fw7 subtle mt12 mb6">CAPABILITIES</div>
              <div className="row g6" style={{ flexWrap: 'wrap' }}>{a.caps.map(c => <span key={c} className="tag" style={{ fontSize: 10.5, fontFamily: 'var(--p-font-mono)' }}>{c}</span>)}</div>
              <div className="row jcsb aic mt12 t11 subtle"><span>{a.runs} lần chạy</span><span>gần nhất {fmtTime(a.lastRun)}</span></div>
              <div className="row g6 mt12"><Button size="sm" variant="primary" icon="play">Run</Button><Button size="sm" variant="plain" icon="search">Query</Button><Button size="sm" variant="plain" icon="checkCircle">Health</Button></div>
            </Card>
          );
        })}
      </div>
      <Card pad={false} title="Nhật ký Run / Query">
        <table className="tbl">
          <thead><tr><th>Thời điểm</th><th>Agent</th><th>Action</th><th className="num">Kết quả</th><th>Tóm tắt</th></tr></thead>
          <tbody>{AGENT_RUNS.map((r, i) => (
            <tr key={i}><td className="t12 subtle">{fmtTime(r.t)}</td>
              <td className="t12" style={{ fontFamily: 'var(--p-font-mono)' }}>{r.agent}</td>
              <td className="t12 muted" style={{ fontFamily: 'var(--p-font-mono)', fontSize: 11 }}>{r.action}</td>
              <td className="num"><Badge tone={r.status === 'success' ? 'success' : r.status === 'partial' ? 'warning' : 'critical'}>{r.status}</Badge></td>
              <td className="t12 muted">{r.summary}</td></tr>
          ))}</tbody>
        </table>
      </Card>
    </div>
  );
}

/* ───────────────────────── 7 · DỮ LIỆU MẪU (demo data) ───────────────────────── */
function DemoData() {
  const [loaded, setLoaded] = useState(true);
  const [busy, setBusy] = useState(false);
  const act = fn => { setBusy(true); setTimeout(() => { fn(); setBusy(false); }, 700); };
  const SAMPLE = [['Hội thoại mẫu', 240], ['Tin nhắn', 3180], ['Kết quả QC', 156], ['Thẻ phân loại', 128], ['Job mẫu', 4]];
  return (
    <div className="page wide">
      <PageHead title="Dữ liệu mẫu" subtitle="Nạp / xóa bộ dữ liệu demo theo tenant để trải nghiệm nhanh · backend: demo (status · import · reset) · chỉ owner/admin" />
      <div className="grid mb16" style={{ gridTemplateColumns: '1fr 1fr', alignItems: 'start' }}>
        <Card title="Trạng thái" actions={loaded ? <Badge tone="success" dot>Đã nạp</Badge> : <Badge tone="neutral">Chưa nạp</Badge>}>
          {loaded ? (
            <div className="col g10">
              <div className="t12 muted">Tenant <b>AAU Academy — HCM</b> đang chứa dữ liệu mẫu:</div>
              <table className="tbl">
                <tbody>{SAMPLE.map(([k, v]) => <tr key={k}><td className="t12">{k}</td><td className="num t12 fw6">{AAU.fmtNum(v)}</td></tr>)}</tbody>
              </table>
            </div>
          ) : <div className="t13 muted">Chưa có dữ liệu mẫu. Nạp bộ demo để xem thử dashboard, QC và inbox với dữ liệu thật.</div>}
        </Card>
        <Card title="Thao tác">
          <div className="col g12">
            <div className="row g8" style={{ padding: 12, borderRadius: 10, background: 'var(--p-warning-bg)', color: 'var(--p-warning-text)' }}><Icon name="alert" size={18} /><div className="t12"><b>Lưu ý:</b> “Xóa & làm lại” sẽ xóa toàn bộ dữ liệu mẫu hiện có rồi nạp lại từ đầu. Không ảnh hưởng dữ liệu thật đã đồng bộ.</div></div>
            <div className="row g8">
              <Button variant="primary" icon="download" disabled={busy || loaded} onClick={() => act(() => setLoaded(true))}>Nạp dữ liệu mẫu</Button>
              <Button icon="refresh" disabled={busy || !loaded} onClick={() => act(() => setLoaded(true))}>Xóa & làm lại</Button>
              <Button variant="plain" icon="trash" disabled={busy || !loaded} onClick={() => act(() => setLoaded(false))}>Xóa dữ liệu mẫu</Button>
            </div>
            {busy && <div className="t12 subtle">Đang xử lý…</div>}
          </div>
        </Card>
      </div>
    </div>
  );
}

Object.assign(window, { ChatChannels, AICost, ActivityLog, MCPConnections, MCPCreateModal, NotificationLog, AgentsCenter, DemoData });

/* ───────────────────────── Nhật ký cập nhật (Changelog) ───────────────────────── */
const CL_META = {
  feature: { icon: 'sparkles', color: '#0a7d4f', bg: 'var(--p-success-bg)', label: 'Tính năng' },
  fix: { icon: 'alert', color: '#c4320a', bg: 'var(--p-critical-bg)', label: 'Sửa lỗi' },
  improve: { icon: 'bolt', color: '#1a4fa3', bg: 'var(--p-info-bg)', label: 'Cải thiện' },
  infra: { icon: 'settings', color: '#6d28d9', bg: 'var(--p-bg-surface-tertiary)', label: 'Hạ tầng' },
};

function ChangelogScreen() {
  const log = (typeof window !== 'undefined' && window.CHANGELOG) || [];
  const totalFeat = log.reduce((s, d) => s + d.entries.filter(e => e.type === 'feature').length, 0);
  const totalFix = log.reduce((s, d) => s + d.entries.filter(e => e.type === 'fix').length, 0);
  return (
    <div className="page wide">
      <PageHead title="Nhật ký cập nhật" subtitle="Mọi thay đổi đã gắn lên hệ thống — tính năng mới, sửa lỗi, cải thiện. Mới nhất ở trên." />
      <div className="grid gc4 mb16">
        <KPI label="Số đợt cập nhật" value={log.length} icon="calendar" />
        <KPI label="Tính năng mới" value={totalFeat} icon="sparkles" />
        <KPI label="Lỗi đã sửa" value={totalFix} icon="checkCircle" />
        <KPI label="Bản mới nhất" value={log[0] ? log[0].date : '—'} sub={log[0] ? log[0].tag : ''} icon="bolt" />
      </div>
      {log.length === 0 && <EmptyState icon="fileText" title="Chưa có bản ghi" desc="changelog.js trống." />}
      {log.map((day, di) => (
        <Card key={di} className="mb16" title={day.date + (day.tag ? ' · ' + day.tag : '')} subtitle={day.entries.length + ' thay đổi'}>
          <div className="col g10">
            {day.entries.map((e, ei) => {
              const m = CL_META[e.type] || CL_META.improve;
              return (
                <div key={ei} className="row g10" style={{ alignItems: 'flex-start', padding: 11, borderRadius: 10, background: 'var(--p-bg-surface-secondary)' }}>
                  <span className="center" style={{ width: 26, height: 26, borderRadius: 7, background: m.bg, color: m.color, flexShrink: 0 }}><Icon name={m.icon} size={14} /></span>
                  <div className="f1" style={{ minWidth: 0 }}>
                    <div className="row aic g6" style={{ flexWrap: 'wrap' }}>
                      <span className="badge" style={{ fontSize: 10, background: m.bg, color: m.color }}>{m.label}</span>
                      {e.area && <span className="badge neutral" style={{ fontSize: 10 }}>{e.area}</span>}
                      <span className="t13 fw7">{e.title}</span>
                    </div>
                    <div className="t12 muted mt4" style={{ lineHeight: 1.5 }}>{e.detail}</div>
                    {e.files && e.files.length > 0 && <div className="t11 subtle mt4" style={{ fontFamily: 'monospace' }}>{e.files.join(' · ')}</div>}
                  </div>
                </div>
              );
            })}
          </div>
        </Card>
      ))}
    </div>
  );
}
window.ChangelogScreen = ChangelogScreen;

/* ───────────────────────── Cấu hình AI (model cho chat + QC scan) ───────────────────────── */
const AI_MODELS = {
  claude: [
    { value: 'claude-opus-4-8', label: 'Claude Opus 4.8 (mạnh nhất)' },
    { value: 'claude-sonnet-4-6', label: 'Claude Sonnet 4.6 (cân bằng)' },
    { value: 'claude-haiku-4-5', label: 'Claude Haiku 4.5 (nhanh/rẻ)' },
  ],
  gemini: [
    { value: 'gemini-2.5-pro', label: 'Gemini 2.5 Pro' },
    { value: 'gemini-2.5-flash', label: 'Gemini 2.5 Flash (rẻ)' },
  ],
};

function AISettings() {
  const live = !!(window.API && window.API.enabled);
  const [cfg, setCfg] = useState(null);
  const [saved, setSaved] = useState(false);
  const [busy, setBusy] = useState(false);
  useEffect(() => { if (live && window.API.aiConfig) window.API.aiConfig().then(setCfg).catch(() => { }); }, [live]);
  const set = (k, v) => { setCfg(c => ({ ...c, [k]: v })); setSaved(false); };
  const setProvider = p => setCfg(c => ({ ...c, provider: p, model: (AI_MODELS[p][0] || {}).value }));
  const save = async () => {
    if (!cfg || busy) return; setBusy(true);
    try { const r = await window.API.saveAiConfig({ provider: cfg.provider, model: cfg.model, qcEngine: cfg.qcEngine, defaultMode: cfg.defaultMode }); setCfg(r); setSaved(true); }
    catch (e) { window.alert('Lưu lỗi: ' + (e && e.message || e)); }
    finally { setBusy(false); }
  };
  const head = <PageHead title="Cấu hình AI" subtitle="Chọn model AI dùng cho QC scan & trợ lý chat — chỉnh & lưu tại đây." />;
  if (!live) return <div className="page wide">{head}<EmptyState icon="robot" title="Cần chế độ LIVE" desc="Mở app qua backend để chỉnh cấu hình." /></div>;
  if (!cfg) return <div className="page wide">{head}<div className="muted t13" style={{ padding: 20 }}>Đang tải cấu hình…</div></div>;
  const models = AI_MODELS[cfg.provider] || AI_MODELS.claude;
  return (
    <div className="page">
      {head}
      <Card title="Model AI" subtitle="Áp dụng cho QC scan (khi chế độ = AI) và trợ lý soạn tin">
        <Field label="Nhà cung cấp">
          <Seg value={cfg.provider} onChange={setProvider} options={[{ value: 'claude', label: 'Claude (Anthropic)' }, { value: 'gemini', label: 'Gemini (Google)' }]} />
        </Field>
        <Field label="Model"><Select value={cfg.model} onChange={v => set('model', v)} options={models} /></Field>
        <Field label="Chế độ chấm QC">
          <Select value={cfg.qcEngine} onChange={v => set('qcEngine', v)} options={[
            { value: 'rule', label: 'Rule-based (miễn phí, theo từ khóa)' },
            { value: 'ai', label: 'AI (dùng model trên — cần API key)' },
          ]} />
        </Field>
        {cfg.qcEngine === 'ai' && <div className="row aic g8 t12 mb12" style={{ padding: '9px 12px', borderRadius: 9, background: 'var(--p-warning-bg)', color: '#7a4d00' }}><Icon name="alert" size={14} /><span>Chế độ AI cần cấu hình API key của {cfg.provider}. Chưa có key → QC vẫn chạy rule-based.</span></div>}
        <Field label="Chế độ trợ lý chat mặc định">
          <Select value={cfg.defaultMode} onChange={v => set('defaultMode', v)} options={[{ value: 'off', label: 'Tắt' }, { value: 'copilot', label: 'Copilot (gợi ý, người duyệt)' }, { value: 'autopilot', label: 'Autopilot (tự trả lời)' }]} />
        </Field>
        <div className="row aic g10 mt8">
          <Button variant="primary" icon="check" onClick={save} disabled={busy}>{busy ? 'Đang lưu…' : 'Lưu cấu hình'}</Button>
          {saved && <span className="badge success" style={{ fontSize: 11 }}><Icon name="checkCircle" size={12} /> Đã lưu</span>}
          <span className="t12 subtle mla">Đang dùng: <b>{cfg.model}</b> · QC {cfg.qcEngine === 'ai' ? 'AI' : 'rule-based'}</span>
        </div>
      </Card>
      <div className="t11 subtle mt12" style={{ lineHeight: 1.5 }}>Model này hiển thị trên QC Report và dùng khi bật chấm AI. Theo dõi chi phí token ở <span className="linkish" onClick={() => navigate('/system/ai-cost')}>AI Cost</span>.</div>
    </div>
  );
}
window.AISettings = AISettings;
