/* ================ AD RADAR ================
 * Competitor / category ad-monitoring off the Meta Ad Library.
 * Reads snapshots written daily by the fb-ad-radar edge function.
 *
 * What it shows:
 *   · Watchlist manager (pages + keyword groups)
 *   · Market Heat Index (total ads/day across keyword targets) with our
 *     own daily ROAS overlaid — the ⭐ cross-check: "is it us or the market?"
 *   · Per-target trend cards + spike/drop anomaly badges
 *   · New creatives feed + long-running "winning" creatives
 *
 * Limits (by API design): commercial ads expose no spend/impressions;
 * only currently-active ads are returned. We measure count / creative /
 * duration, snapshotted daily so trends survive.
 * ========================================================= */
(function () {
  const R = React;
  const SERIES_COLORS = ['#3b6ef5', '#7c3aed', '#ea7c0c', '#0f766e', '#e11d48', '#0891b2', '#65a30d', '#c026d3'];

  const ymd = (d) => d.toISOString().slice(0, 10);
  const bkkToday = () => ymd(new Date(Date.now() + 7 * 3600e3));
  const addDays = (s, n) => ymd(new Date(new Date(s + 'T00:00:00Z').getTime() + n * 86400e3));
  // Inclusive list of YYYY-MM-DD between since..until (guarded).
  const axisBetween = (since, until) => {
    const out = []; let d = since, guard = 0;
    while (d <= until && guard++ < 400) { out.push(d); d = addDays(d, 1); }
    return out.length ? out : [until];
  };
  // Range presets mirroring the Overview page.
  const PRESET_DAYS = { '7d': 7, '14d': 14, '30d': 30, '60d': 60, '90d': 90, '6m': 180 };
  const windowOf = (range, applied, cs, cu) => {
    if (applied && cs && cu) return { since: cs, until: cu };
    const until = bkkToday();
    const n = PRESET_DAYS[range] ?? 30;
    return { since: ymd(new Date(Date.now() + 7 * 3600e3 - (n - 1) * 86400e3)), until };
  };
  const fmtDay = (s) => { const [, m, d] = s.split('-'); return `${+d}/${+m}`; };

  // ── Multi-series line chart (dual-axis capable), pure SVG ──
  function LineChart({ labels, series, height = 150, yLabel = '', y2Label = '' }) {
    const W = 720, H = height, padL = 40, padR = series.some(s => s.axis === 'right') ? 44 : 12, padT = 12, padB = 22;
    const iw = W - padL - padR, ih = H - padT - padB;
    const n = labels.length;
    const xOf = (i) => padL + (n <= 1 ? iw / 2 : (i / (n - 1)) * iw);
    const left = series.filter(s => (s.axis || 'left') === 'left');
    const right = series.filter(s => s.axis === 'right');
    const maxOf = (arr) => Math.max(1, ...arr.flatMap(s => s.values.filter(v => v != null)));
    const maxL = maxOf(left.length ? left : series);
    const maxR = right.length ? maxOf(right) : 1;
    const yL = (v) => padT + ih - (v / maxL) * ih;
    const yR = (v) => padT + ih - (v / maxR) * ih;
    const path = (s) => {
      const yf = s.axis === 'right' ? yR : yL;
      let d = '', started = false;
      s.values.forEach((v, i) => {
        if (v == null) { started = false; return; }
        d += `${started ? 'L' : 'M'}${xOf(i).toFixed(1)},${yf(v).toFixed(1)} `;
        started = true;
      });
      return d.trim();
    };
    const ticks = [0, 0.5, 1].map(f => Math.round(maxL * f));
    const step = Math.max(1, Math.floor(n / 6));
    return (
      <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', height: 'auto', display: 'block' }}>
        {ticks.map((t, i) => {
          const y = yL(t);
          return (
            <g key={i}>
              <line x1={padL} y1={y} x2={W - padR} y2={y} stroke="var(--border)" strokeWidth="1" strokeDasharray={i === 0 ? '' : '3 3'} />
              <text x={padL - 6} y={y + 3} textAnchor="end" fontSize="9" fill="var(--ink-faint)" fontFamily="var(--mono)">{t}</text>
            </g>
          );
        })}
        {right.length > 0 && [0, 0.5, 1].map((f, i) => {
          const v = maxR * f, y = yR(v);
          return <text key={i} x={W - padR + 6} y={y + 3} textAnchor="start" fontSize="9" fill="var(--ink-faint)" fontFamily="var(--mono)">{v.toFixed(v < 10 ? 1 : 0)}</text>;
        })}
        {labels.map((l, i) => i % step === 0 && (
          <text key={i} x={xOf(i)} y={H - 6} textAnchor="middle" fontSize="9" fill="var(--ink-faint)">{fmtDay(l)}</text>
        ))}
        {series.map((s, si) => (
          <g key={si}>
            {s.area && (
              <path d={`${path(s)} L${xOf(n - 1)},${yL(0)} L${xOf(0)},${yL(0)} Z`} fill={s.color} opacity="0.08" stroke="none" />
            )}
            <path d={path(s)} fill="none" stroke={s.color} strokeWidth={s.axis === 'right' ? 1.6 : 2} strokeDasharray={s.dash || ''} strokeLinejoin="round" />
          </g>
        ))}
      </svg>
    );
  }

  function Legend({ items }) {
    return (
      <div style={{ display: 'flex', gap: 14, flexWrap: 'wrap', marginTop: 6 }}>
        {items.map((it, i) => (
          <span key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11, color: 'var(--ink-soft)' }}>
            <span style={{ width: 14, height: 3, borderRadius: 2, background: it.color, borderTop: it.dash ? `2px dashed ${it.color}` : 'none' }} />
            {it.label}
          </span>
        ))}
      </div>
    );
  }

  // ── Add-target form ──
  function AddTargetForm({ onAdd }) {
    const [kind, setKind] = R.useState('page');
    const [value, setValue] = R.useState('');
    const [label, setLabel] = R.useState('');
    const [group, setGroup] = R.useState('');
    const [busy, setBusy] = R.useState(false);
    const submit = async () => {
      if (!value.trim()) return;
      setBusy(true);
      await onAdd({ kind, value: value.trim(), label: label.trim() || value.trim(), groupName: group.trim() || null });
      setValue(''); setLabel(''); setGroup(''); setBusy(false);
    };
    const inp = { padding: '7px 10px', border: '1px solid var(--border)', borderRadius: 6, background: 'var(--panel-2)', fontSize: 13, color: 'var(--ink)' };
    return (
      <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
        <div className="seg">
          <button className={kind === 'page' ? 'active' : ''} onClick={() => setKind('page')}>Page ID</button>
          <button className={kind === 'keyword' ? 'active' : ''} onClick={() => setKind('keyword')}>Keyword</button>
        </div>
        <input style={{ ...inp, flex: 1, minWidth: 160 }} placeholder={kind === 'page' ? 'เลข Page ID (เช่น 162026164)' : 'คำค้น (เช่น "ซื้อ | รองเท้า")'}
          value={value} onChange={e => setValue(e.target.value)} onKeyDown={e => e.key === 'Enter' && submit()} />
        <input style={{ ...inp, width: 140 }} placeholder="ป้ายชื่อ (label)" value={label} onChange={e => setLabel(e.target.value)} />
        <input style={{ ...inp, width: 120 }} placeholder="กลุ่ม (เช่น รองเท้า)" value={group} onChange={e => setGroup(e.target.value)} />
        <button className="btn-primary-sm" disabled={busy || !value.trim()} onClick={submit} style={{ opacity: busy || !value.trim() ? 0.6 : 1 }}>
          {busy ? '...' : '+ เพิ่ม'}
        </button>
      </div>
    );
  }

  // trailing-avg helper for anomaly badge
  const trend = (vals) => {
    const nn = vals.filter(v => v != null);
    if (nn.length < 4) return null;
    const today = nn[nn.length - 1];
    const prior = nn.slice(Math.max(0, nn.length - 8), nn.length - 1);
    const avg = prior.reduce((a, b) => a + b, 0) / prior.length;
    if (avg < 5 && today < 5) return null;
    const pct = avg > 0 ? (today - avg) / avg : 0;
    if (Math.abs(pct) < 0.5) return null;
    return { pct: Math.round(pct * 100), dir: pct > 0 ? 'spike' : 'drop', today, avg: +avg.toFixed(1) };
  };

  function AnomalyBadge({ t }) {
    if (!t) return null;
    const up = t.dir === 'spike';
    return (
      <span style={{
        fontSize: 10, fontWeight: 700, padding: '2px 7px', borderRadius: 4,
        background: up ? 'var(--warning-bg)' : 'var(--danger-bg)', color: up ? 'var(--warning)' : 'var(--danger)',
      }}>
        {up ? '📈 พุ่ง' : '📉 ดิ่ง'} {t.pct > 0 ? '+' : ''}{t.pct}%
      </span>
    );
  }

  // ── Main screen ──
  function AdRadarScreen() {
    const [targets, setTargets] = R.useState([]);
    const [snaps, setSnaps] = R.useState(new Map());
    const [ourDaily, setOurDaily] = R.useState([]);
    const [newAds, setNewAds] = R.useState([]);
    const [winAds, setWinAds] = R.useState([]);
    const [loading, setLoading] = R.useState(true);
    const [running, setRunning] = R.useState(false);
    const [range, setRange] = R.useState('30d');
    const [customSince, setCustomSince] = R.useState('');
    const [customUntil, setCustomUntil] = R.useState('');
    const [customApplied, setCustomApplied] = R.useState(false);
    const [showCustom, setShowCustom] = R.useState(false);
    const [toast, setToast] = R.useState('');
    const [tab, setTab] = R.useState('overview'); // overview | watchlist | creatives

    const flash = (m) => { setToast(m); setTimeout(() => setToast(''), 2600); };

    const { since, until } = React.useMemo(
      () => windowOf(range, customApplied, customSince, customUntil),
      [range, customApplied, customSince, customUntil]);

    const load = R.useCallback(async () => {
      if (!window.DB) return;
      setLoading(true);
      try {
        const [tg, sn, od, na, wa] = await Promise.all([
          window.DB.getRadarTargets(),
          window.DB.getRadarSnapshots(since, until),
          window.DB.getOurDailyMetrics(since, until),
          window.DB.getRadarNewAds(3, 40),
          window.DB.getRadarWinningAds(14, 30),
        ]);
        setTargets(tg); setSnaps(sn); setOurDaily(od); setNewAds(na); setWinAds(wa);
      } catch (e) { console.error('[radar] load', e); }
      setLoading(false);
    }, [since, until]);
    R.useEffect(() => { load(); }, [load]);

    const axis = React.useMemo(() => axisBetween(since, until), [since, until]);
    // align a target's snapshots to the shared date axis (missing → null)
    const seriesFor = (targetId) => {
      const rows = snaps.get(targetId) || [];
      const byDate = new Map(rows.map(r => [r.date, r.active]));
      return axis.map(d => byDate.has(d) ? byDate.get(d) : null);
    };
    const labelOf = (id) => targets.find(t => t.id === id)?.label || '?';

    const keywordTargets = targets.filter(t => t.kind === 'keyword');
    const pageTargets = targets.filter(t => t.kind === 'page');

    // Market Heat = sum of active ads across keyword targets per day
    const heat = React.useMemo(() => axis.map((d, i) => {
      let sum = 0, any = false;
      for (const t of keywordTargets) {
        const v = seriesFor(t.id)[i];
        if (v != null) { sum += v; any = true; }
      }
      return any ? sum : null;
    }), [axis, snaps, targets]);
    const ourRoas = React.useMemo(() => {
      const byDate = new Map(ourDaily.map(r => [r.date, r.roas]));
      return axis.map(d => byDate.has(d) ? +byDate.get(d).toFixed(2) : null);
    }, [axis, ourDaily]);

    // KPIs
    const totalActive = targets.reduce((s, t) => {
      const v = seriesFor(t.id).filter(x => x != null);
      return s + (v.length ? v[v.length - 1] : 0);
    }, 0);
    const anomalyCount = targets.filter(t => trend(seriesFor(t.id))).length;
    const hasData = [...snaps.values()].some(a => a.length);

    const runNow = async () => {
      setRunning(true);
      const r = await window.DB.runAdRadar();
      setRunning(false);
      if (r?.ok) { flash(`✓ สแกนแล้ว ${r.targets || 0} target`); load(); }
      else flash(`✗ ${r?.error || 'ล้มเหลว'}`);
    };

    const addTarget = async (t) => {
      const r = await window.DB.addRadarTarget(t);
      if (r.ok) { flash('✓ เพิ่ม target แล้ว'); load(); } else flash(`✗ ${r.error}`);
    };
    const toggleTarget = async (t) => { await window.DB.updateRadarTarget(t.id, { enabled: !t.enabled }); load(); };
    const delTarget = async (t) => { if (confirm(`ลบ "${t.label}" ?`)) { await window.DB.deleteRadarTarget(t.id); load(); } };

    const card = { background: 'var(--panel)', border: '1px solid var(--border)', borderRadius: 'var(--radius)', padding: 16 };

    return (
      <div className="screen">
        <div className="screen-head">
          <div>
            <div className="breadcrumb">Wandee · Intelligence</div>
            <h1 className="page-title">📡 Ad Radar</h1>
            <p className="page-sub">จับทิศทางการยิงแอดของคู่แข่งและอุณหภูมิตลาด จาก Meta Ad Library — นับจำนวน ad, creative ใหม่, ตัวที่รันนาน และเทียบกับ ROAS ของเราเอง</p>
          </div>
          <div className="head-actions" style={{ flexWrap: 'wrap', gap: 6 }}>
            <div className="range-tabs">
              {[['7d', '7 วัน'], ['14d', '14 วัน'], ['30d', '30 วัน'], ['60d', '60 วัน'], ['90d', '90 วัน'], ['6m', '6 เดือน']].map(([k, l]) => (
                <button key={k} className={range === k && !customApplied ? 'active' : ''}
                  onClick={() => { setRange(k); setCustomApplied(false); setShowCustom(false); }}>{l}</button>
              ))}
              <div style={{ position: 'relative' }}>
                <button className={showCustom || customApplied ? 'active' : ''}
                  onClick={() => setShowCustom(v => !v)}
                  style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                  <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="4" width="18" height="18" rx="2" /><path d="M16 2V6M8 2V6M3 10H21" /></svg>
                  {customApplied && customSince && customUntil
                    ? `${new Date(customSince + 'T00:00:00').toLocaleDateString('th-TH', { day: 'numeric', month: 'short' })} – ${new Date(customUntil + 'T00:00:00').toLocaleDateString('th-TH', { day: 'numeric', month: 'short' })}`
                    : 'กำหนดเอง'}
                </button>
                {showCustom && window.DateRangePicker && (
                  <window.DateRangePicker since={customSince} until={customUntil}
                    onChange={(s, e) => { if (s && e) { setCustomSince(s); setCustomUntil(e); setCustomApplied(true); } }}
                    onClose={() => setShowCustom(false)} />
                )}
              </div>
            </div>
            <button className="btn-primary" onClick={runNow} disabled={running}>
              {running ? (
                <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" style={{ animation: 'spin 1s linear infinite' }}><path d="M21 12A9 9 0 1112 3" /></svg>
                  กำลังสแกน...
                </span>
              ) : '▶ สแกนตอนนี้'}
            </button>
          </div>
        </div>

        {/* Tabs */}
        <div style={{ display: 'flex', gap: 4, marginBottom: 18, borderBottom: '1px solid var(--border)' }}>
          {[['overview', '📊 ภาพรวม'], ['watchlist', '🎯 Watchlist'], ['creatives', '🖼️ Creative']].map(([k, l]) => (
            <button key={k} onClick={() => setTab(k)}
              style={{ padding: '8px 14px', fontSize: 13, fontWeight: tab === k ? 600 : 400, color: tab === k ? 'var(--accent)' : 'var(--ink-soft)', borderBottom: `2px solid ${tab === k ? 'var(--accent)' : 'transparent'}`, marginBottom: -1 }}>
              {l}
            </button>
          ))}
        </div>

        {loading ? (
          <div style={{ padding: 60, textAlign: 'center', color: 'var(--ink-faint)' }}>
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" strokeWidth="2.5" style={{ animation: 'spin 0.8s linear infinite' }}><path d="M21 12A9 9 0 1112 3" /></svg>
          </div>
        ) : !targets.length ? (
          <div style={{ ...card, textAlign: 'center', padding: 40 }}>
            <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 6 }}>ยังไม่มี target ที่จับตา</div>
            <div style={{ fontSize: 13, color: 'var(--ink-soft)', marginBottom: 16 }}>เพิ่มเพจคู่แข่ง (Page ID) หรือกลุ่มคำค้น แล้วกด "สแกนตอนนี้" เพื่อเก็บ snapshot แรก</div>
            <div style={{ maxWidth: 720, margin: '0 auto' }}><AddTargetForm onAdd={addTarget} /></div>
          </div>
        ) : (
          <>
            {/* ===== OVERVIEW ===== */}
            {tab === 'overview' && (
              <>
                <div className="kpi-grid" style={{ gridTemplateColumns: 'repeat(4,1fr)' }}>
                  <div className="kpi-card"><div className="kpi-head"><span className="kpi-label">Target ที่จับตา</span></div><div className="kpi-value">{targets.length}</div><div className="kpi-foot kpi-sub">{pageTargets.length} เพจ · {keywordTargets.length} คำค้น</div></div>
                  <div className="kpi-card"><div className="kpi-head"><span className="kpi-label">Ads active วันนี้ (รวม)</span></div><div className="kpi-value">{totalActive}</div><div className="kpi-foot kpi-sub">ทุก target</div></div>
                  <div className="kpi-card"><div className="kpi-head"><span className="kpi-label">Creative ใหม่ (3 วัน)</span></div><div className="kpi-value">{newAds.length}</div><div className="kpi-foot kpi-sub">เพิ่งเห็นครั้งแรก</div></div>
                  <div className="kpi-card"><div className="kpi-head"><span className="kpi-label">สัญญาณผิดปกติ</span></div><div className="kpi-value" style={{ color: anomalyCount ? 'var(--warning)' : 'var(--ink)' }}>{anomalyCount}</div><div className="kpi-foot kpi-sub">พุ่ง/ดิ่ง วันนี้</div></div>
                </div>

                {!hasData && (
                  <div style={{ ...card, marginBottom: 16, borderColor: 'var(--warning)', background: 'var(--warning-bg)', color: 'var(--warning)', fontSize: 13 }}>
                    ยังไม่มีข้อมูล snapshot — กด <strong>"สแกนตอนนี้"</strong> เพื่อเก็บวันแรก แล้วรอ cron รายวันสะสมเทรนด์ (เทรนด์จะชัดหลังมีข้อมูล ≥ 3–4 วัน)
                  </div>
                )}

                {/* ⭐ Market Heat vs our ROAS */}
                {keywordTargets.length > 0 && (
                  <div style={{ ...card, marginBottom: 16 }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 4 }}>
                      <h3 style={{ margin: 0, fontSize: 14, fontWeight: 600 }}>🌡️ Market Heat Index vs ROAS เรา</h3>
                      <span className="small muted">อุณหภูมิตลาด = จำนวน ad รวมของกลุ่มคำค้น · เทียบ ROAS เราแต่ละวัน</span>
                    </div>
                    <p style={{ fontSize: 12, color: 'var(--ink-soft)', margin: '0 0 8px' }}>วันที่ heat ดิ่งพร้อม ROAS เราดิ่ง = ทั้งตลาดแย่ (ไม่ใช่แค่เรา) · heat ปกติแต่ ROAS เราดิ่ง = ปัญหาที่แอดเราเอง</p>
                    <LineChart labels={axis} series={[
                      { label: 'Market Heat', color: '#ea7c0c', values: heat, area: true, axis: 'left' },
                      { label: 'ROAS เรา', color: '#3b6ef5', values: ourRoas, axis: 'right', dash: '4 3' },
                    ]} height={170} />
                    <Legend items={[{ label: 'Market Heat (ads/วัน)', color: '#ea7c0c' }, { label: 'ROAS เรา', color: '#3b6ef5', dash: true }]} />
                  </div>
                )}

                {/* Per-target trend cards */}
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(340px,1fr))', gap: 14 }}>
                  {targets.map((t, i) => {
                    const vals = seriesFor(t.id);
                    const tr = trend(vals);
                    const last = [...vals].reverse().find(v => v != null);
                    return (
                      <div key={t.id} style={card}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 8, gap: 8 }}>
                          <div style={{ minWidth: 0 }}>
                            <div style={{ fontWeight: 600, fontSize: 13, display: 'flex', alignItems: 'center', gap: 6 }}>
                              <span style={{ fontSize: 10, padding: '1px 6px', borderRadius: 4, background: 'var(--neutral-bg)', color: 'var(--ink-soft)' }}>{t.kind === 'page' ? 'เพจ' : 'คำค้น'}</span>
                              <span className="truncate">{t.label}</span>
                            </div>
                            {t.group_name && <div className="small muted" style={{ marginTop: 2 }}>กลุ่ม: {t.group_name}</div>}
                          </div>
                          <div style={{ textAlign: 'right', flexShrink: 0 }}>
                            <div style={{ fontSize: 22, fontWeight: 700, fontFamily: 'var(--mono)', lineHeight: 1 }}>{last != null ? last : '—'}</div>
                            <div className="small muted">ads active</div>
                          </div>
                        </div>
                        <LineChart labels={axis} series={[{ label: t.label, color: SERIES_COLORS[i % SERIES_COLORS.length], values: vals, area: true }]} height={90} />
                        <div style={{ marginTop: 6, minHeight: 20 }}>
                          {tr ? <AnomalyBadge t={tr} /> : <span className="small muted">อยู่ในช่วงปกติ{tr === null && !last ? ' · ยังไม่มีข้อมูล' : ''}</span>}
                        </div>
                      </div>
                    );
                  })}
                </div>
              </>
            )}

            {/* ===== WATCHLIST ===== */}
            {tab === 'watchlist' && (
              <>
                <div style={{ ...card, marginBottom: 16 }}>
                  <h3 style={{ margin: '0 0 10px', fontSize: 14, fontWeight: 600 }}>เพิ่ม target</h3>
                  <AddTargetForm onAdd={addTarget} />
                  <p style={{ fontSize: 12, color: 'var(--ink-soft)', margin: '10px 0 0' }}>
                    <strong>Page ID</strong> = ดู ad ที่เพจนั้นกำลังรัน (ชัวร์สุด) · <strong>Keyword</strong> = นับ ad ทั้งตลาดที่ตรงคำ (ขึ้นกับ Ad Library เปิดค้นในไทย — เทสด้วยปุ่ม "สแกนตอนนี้")
                  </p>
                </div>
                <div className="table-card">
                  <table className="data-table">
                    <thead><tr><th>ประเภท</th><th>Target</th><th>กลุ่ม</th><th className="right">Ads วันนี้</th><th className="center">สถานะ</th><th></th></tr></thead>
                    <tbody>
                      {targets.map(t => {
                        const vals = seriesFor(t.id); const last = [...vals].reverse().find(v => v != null);
                        return (
                          <tr key={t.id}>
                            <td><span style={{ fontSize: 11, padding: '1px 6px', borderRadius: 4, background: 'var(--neutral-bg)', color: 'var(--ink-soft)' }}>{t.kind === 'page' ? 'เพจ' : 'คำค้น'}</span></td>
                            <td><div style={{ fontWeight: 500 }}>{t.label}</div><div className="small muted mono">{t.value}</div></td>
                            <td className="muted">{t.group_name || '—'}</td>
                            <td className="right mono">{last != null ? last : '—'}</td>
                            <td className="center">
                              <button onClick={() => toggleTarget(t)} title={t.enabled ? 'กำลังจับตา — คลิกเพื่อหยุด' : 'หยุดอยู่ — คลิกเพื่อเปิด'}
                                style={{ fontSize: 11, padding: '3px 10px', borderRadius: 12, fontWeight: 600, background: t.enabled ? 'var(--success-bg)' : 'var(--neutral-bg)', color: t.enabled ? 'var(--success)' : 'var(--ink-faint)' }}>
                                {t.enabled ? '● จับตา' : '○ หยุด'}
                              </button>
                            </td>
                            <td className="right">
                              <button className="icon-btn-sm" onClick={() => delTarget(t)} title="ลบ">
                                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 6H21M8 6V4A2 2 0 0110 2H14A2 2 0 0116 4V6M19 6V20A2 2 0 0117 22H7A2 2 0 015 20V6" /></svg>
                              </button>
                            </td>
                          </tr>
                        );
                      })}
                    </tbody>
                  </table>
                </div>
              </>
            )}

            {/* ===== CREATIVES ===== */}
            {tab === 'creatives' && (
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
                <div style={card}>
                  <h3 style={{ margin: '0 0 4px', fontSize: 14, fontWeight: 600 }}>🆕 Creative ใหม่ (3 วันล่าสุด)</h3>
                  <p className="small muted" style={{ margin: '0 0 12px' }}>โฆษณาที่เพิ่งเห็นครั้งแรก — คู่แข่งกำลังดันอะไรใหม่</p>
                  {!newAds.length ? <div className="muted small">ยังไม่มี</div> : newAds.map((a, i) => (
                    <AdRow key={i} a={a} label={labelOf(a.target_id)} tag={a.first_seen} />
                  ))}
                </div>
                <div style={card}>
                  <h3 style={{ margin: '0 0 4px', fontSize: 14, fontWeight: 600 }}>🏆 Winning creative (รันนาน ≥14 วัน)</h3>
                  <p className="small muted" style={{ margin: '0 0 12px' }}>ยังactive + รันมานาน = น่าจะเวิร์ค เอามาศึกษา angle</p>
                  {!winAds.length ? <div className="muted small">ยังไม่มี</div> : winAds.map((a, i) => (
                    <AdRow key={i} a={a} label={labelOf(a.target_id)} tag={`เริ่ม ${a.ad_start_time || '?'}`} />
                  ))}
                </div>
              </div>
            )}
          </>
        )}

        {toast && <div className="toast">{toast}</div>}
      </div>
    );
  }

  function AdRow({ a, label, tag }) {
    return (
      <div style={{ padding: '8px 0', borderBottom: '1px solid var(--border)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, marginBottom: 2 }}>
          <span style={{ fontSize: 11, color: 'var(--accent)', fontWeight: 600 }} className="truncate">{a.page_name || label}</span>
          <span className="small muted" style={{ flexShrink: 0 }}>{tag}</span>
        </div>
        <div style={{ fontSize: 12, color: 'var(--ink-soft)', lineHeight: 1.45, display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>
          {a.body || <span className="muted">(ไม่มีข้อความ)</span>}
        </div>
        {a.snapshot_url && (
          <a href={a.snapshot_url} target="_blank" rel="noopener" style={{ fontSize: 11, color: 'var(--accent)', textDecoration: 'none' }}>ดูใน Ad Library ↗</a>
        )}
      </div>
    );
  }

  window.AdRadarScreen = AdRadarScreen;
})();
