// ───────── 主に見る3つの数字（2026-11-06。集計は worker/kpi.js）─────────
async function kpiStats(request, env, url) {
  if (request.method !== 'GET') return new Response('Method Not Allowed', { status: 405 });
  const day = (k, d) => (/^\d{4}-\d{2}-\d{2}$/.test(url.searchParams.get(k) || '') ? url.searchParams.get(k) : d);
  const today = todayJst();
  // ?sc=refresh で Search Console からサイト名の検索の数を取り直す（?since= の週から。最初の埋め戻し用）
  if (url.searchParams.get('sc') === 'refresh') {
    try { return json(await gscRefresh(env, { since: day('since', '') })); } catch (e) { return json({ ok: false, error: e.message }, 500); }
  }
  const data = await kpiRange(env, day('since', addDays(today, -28)), day('until', today));
  if (url.searchParams.get('format') === 'json') {
    return new Response(JSON.stringify(data), { headers: { 'content-type': 'application/json; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' } });
  }
  const esc = (s) => String(s).replace(/[&<>"]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[ch]));
  const kv = (o) => Object.entries(o || {}).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k} ${v}`).join('、');
  const table = (cols, list) => list.length
    ? `<div class="wrap"><table><tr>${cols.map(([, h]) => `<th>${h}</th>`).join('')}</tr>${list.map((r) => `<tr>${cols.map(([k, , f]) => `<td>${esc(f ? f(r[k], r) : (r[k] ?? '-'))}</td>`).join('')}</tr>`).join('')}</table></div>`
    : '<p>まだ記録がありません。</p>';
  const html = `<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex">
<title>3つの数字</title><style>body{font:14px/1.7 -apple-system,'Noto Sans JP',sans-serif;margin:24px;color:#242424;background:#f7f7f7}
h1{font-size:20px}h2{font-size:16px;margin-top:28px}.wrap{overflow-x:auto}table{border-collapse:collapse;background:#fff}th,td{border:1px solid #ddd;padding:6px 10px;text-align:left;white-space:nowrap}th{background:#eee}p{color:#555}</style></head><body>
<h1>3つの数字</h1><p>AI に調べられることで、人の来訪や知名度がいつ増えはじめるかを見るための数。日付は日本時間、週は月曜はじまり。${esc(data.since)} 〜 ${esc(data.until)}（?since=・?until= で変える）。${data.pendingDays.length ? ` 集計がまだの日が ${data.pendingDays.length} 日ある（開き直すと作る）。` : ''}</p>
<p>AI の依頼読み：ChatGPT-User・Claude-User・Perplexity-User などが読んだページの数（「AIで読む」ボタン経由はエイイチ・Claude の試しが混ざりうる）。AI のリンクから：chatgpt.com などのリンクから来た、人の操作があった表示。サイト名の検索：Search Console から週ごとに記録したクリック数。</p>
<h2>週ごと</h2>${table([['week', '週（月曜）'], ['days', '日数'], ['aiReads', 'AI の依頼読み'], ['aiReadsViaButton', 'うちボタン経由'], ['aiReferrals', 'AI のリンクから来た人'], ['nameSearch', 'サイト名の検索（クリック）'], ['humanViews', '人の表示（参考）'], ['aiReadsByBot', '依頼読みの内訳', kv], ['aiReferralsBySource', 'リンクの内訳', kv]], [...data.byWeek].reverse())}
<h2>日ごと</h2>${table([['day', '日付', (v, r) => v + (r.partial ? '（途中）' : '')], ['aiReads', 'AI の依頼読み'], ['aiReadsViaButton', 'うちボタン経由'], ['aiReferrals', 'AI のリンクから来た人'], ['humanViews', '人の表示（参考）'], ['aiReadsByBot', '依頼読みの内訳', kv], ['aiReferralsBySource', 'リンクの内訳', kv]], [...data.byDay].reverse())}
</body></html>`;
  return new Response(html, { headers: { 'content-type': 'text/html; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' } });
}
