/* global React, window */
const { SharedMasthead, Breadcrumb, Colophon } = window.cynixShared;
const { useState, useEffect } = React;

// Synthetic 24h response time data per VPS provider (ms)
const PROVIDERS = [
  { name: "ConoHa VPS", color: "var(--vermilion)", baseline: 142, jitter: 18, nightSpike: 0 },
  { name: "Xserver VPS", color: "var(--ink)", baseline: 156, jitter: 14, nightSpike: 22 },
  { name: "さくらVPS", color: "#9c8b6e", baseline: 168, jitter: 22, nightSpike: 14 },
  { name: "WebARENA Indigo", color: "#5e6b73", baseline: 174, jitter: 28, nightSpike: 35 },
];

// 24 hours, hourly bars
const HOURS = Array.from({ length: 24 }, (_, h) => h);
const seedData = (p) => HOURS.map((h) => {
  const isNight = h >= 22 || h < 4;
  const v = p.baseline + (Math.sin(h / 24 * Math.PI * 2) * 6) + (isNight ? p.nightSpike : 0) + (Math.random() - 0.5) * p.jitter;
  return Math.max(80, Math.round(v));
});

// 30-day uptime sparkline data
const sparkSeed = () => Array.from({ length: 30 }, () => 99.85 + Math.random() * 0.14);

// Build SVG path for sparkline
const buildSpark = (data, w, h) => {
  const min = Math.min(...data), max = Math.max(...data);
  const pad = 4;
  const xs = (i) => pad + i * (w - pad * 2) / (data.length - 1);
  const ys = (v) => h - pad - ((v - min) / (max - min || 1)) * (h - pad * 2);
  let line = "M " + data.map((v, i) => `${xs(i).toFixed(1)} ${ys(v).toFixed(1)}`).join(" L ");
  let area = line + ` L ${xs(data.length - 1).toFixed(1)} ${h} L ${xs(0).toFixed(1)} ${h} Z`;
  return { line, area };
};

const App = () => {
  const [tab, setTab] = useState(0);
  const [data, setData] = useState(() => PROVIDERS.map(seedData));
  const [now, setNow] = useState(new Date());

  useEffect(() => {
    const t = setInterval(() => {
      setData(PROVIDERS.map(seedData));
      setNow(new Date());
    }, 4000);
    return () => clearInterval(t);
  }, []);

  const tNow = now.toTimeString().slice(0, 8);
  const cur = data[tab];
  const max = Math.max(...cur);

  const sparks = PROVIDERS.map(() => sparkSeed());

  return (
    <>
      <SharedMasthead section="DATA DASHBOARD" />
      <main className="mod-shell">
        <Breadcrumb items={[{ label: "TOP", href: "index.html" }, { label: "データルーム" }]} />

        <section style={{ borderTop: "4px double var(--ink)", borderBottom: "4px double var(--ink)", padding: "48px 0 56px", margin: "16px 0 48px", textAlign: "center" }}>
          <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 11, letterSpacing: "0.3em", color: "var(--vermilion)", marginBottom: 14 }}>EDITORIAL BENCHMARK / LIVE</div>
          <h1 style={{ fontFamily: "'Crimson Pro', serif", fontSize: 80, fontWeight: 500, lineHeight: 0.95, margin: 0, letterSpacing: "-0.03em" }}>データルーム</h1>
          <div style={{ fontFamily: "'Crimson Pro', serif", fontSize: 22, fontStyle: "italic", marginTop: 6, opacity: 0.7 }}>The Cynix Benchmark</div>
          <p style={{ maxWidth: 660, margin: "20px auto 0", fontSize: 14, lineHeight: 1.85, opacity: 0.85 }}>
            編集部が80日連続で計測しているVPS各社の応答時間を、リアルタイムで公開しています。<br />
            数値は4秒ごとに更新。月次サマリは <a href="/server/vps/vps-best/" style={{ color: "var(--vermilion)", borderBottom: "1px solid currentColor" }}>「夜間VPS比較」</a> 記事に反映されます。
          </p>
        </section>

        {/* KPI tiles */}
        <div className="mod-stats" style={{ marginBottom: 32 }}>
          <div><div className="num">80<span className="unit">日</span></div><div className="lab">CONNECTED DAYS</div><div className="sub">2026-01-19 計測開始</div></div>
          <div><div className="num">99.96<span className="unit">%</span></div><div className="lab">AVG. UPTIME</div><div className="sub">4社平均・直近30日</div></div>
          <div><div className="num">160<span className="unit">ms</span></div><div className="lab">AVG. RESPONSE</div><div className="sub">編集部計測値・東京リージョン</div></div>
          <div><div className="num">82,944</div><div className="lab">DATA POINTS</div><div className="sub">直近24時間×4社×15分</div></div>
        </div>

        {/* LIVE chart panel */}
        <div className="mod-chart-panel" style={{ marginBottom: 32 }}>
          <header>
            <div>
              <h3>応答時間 (ms) — 直近24時間</h3>
              <div style={{ fontSize: 12, opacity: 0.65, marginTop: 4 }}>東京リージョン / 編集部計測ノードより / 平均値</div>
            </div>
            <div className="live">LIVE — {tNow}</div>
          </header>

          {/* Tabs */}
          <div style={{ display: "flex", gap: 4, marginBottom: 18, borderBottom: "1px solid var(--ink)" }}>
            {PROVIDERS.map((p, i) => (
              <button key={p.name} onClick={() => setTab(i)} style={{
                padding: "10px 18px", border: "none",
                background: tab === i ? p.color : "transparent",
                color: tab === i ? "var(--paper)" : "var(--ink)",
                fontFamily: "'JetBrains Mono', monospace", fontSize: 11, letterSpacing: "0.15em",
                cursor: "pointer", textTransform: "uppercase",
                borderTop: tab === i ? `3px solid ${p.color}` : "3px solid transparent",
              }}>{p.name}</button>
            ))}
          </div>

          <div className="mod-vbars" style={{ "--cols": 24 }}>
            {cur.map((v, i) => (
              <div key={i} className={(i >= 22 || i < 4) ? "col v" : "col"} style={{ height: `${(v / max) * 100}%` }} data-v={v}></div>
            ))}
          </div>
          <div className="mod-vbars-labels" style={{ "--cols": 24, marginBottom: 12 }}>
            {HOURS.map(h => <span key={h}>{String(h).padStart(2, "0")}</span>)}
          </div>
          <div style={{ display: "flex", justifyContent: "space-between", fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.1em", textTransform: "uppercase", opacity: 0.7 }}>
            <span>00:00 ─ 23:59 (JST)</span>
            <span>夜間帯 22:00-04:00 をハイライト</span>
            <span>UPDATES EVERY 4s</span>
          </div>
        </div>

        {/* Provider cards */}
        <h2 style={{ fontFamily: "'Crimson Pro', serif", fontSize: 28, fontWeight: 500, margin: "32px 0 16px" }}>30日トレンド — 各社</h2>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 20, marginBottom: 48 }}>
          {PROVIDERS.map((p, i) => {
            const spark = sparks[i];
            const avg = (spark.reduce((a, b) => a + b, 0) / spark.length).toFixed(2);
            const paths = buildSpark(spark, 360, 80);
            return (
              <div key={p.name} style={{ border: "1.5px solid var(--ink)", padding: 20, background: "var(--paper)" }}>
                <header style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
                  <div>
                    <div style={{ width: 10, height: 10, background: p.color, display: "inline-block", marginRight: 8 }}></div>
                    <b style={{ fontFamily: "'Crimson Pro', serif", fontSize: 18 }}>{p.name}</b>
                  </div>
                  <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 12 }}>{avg}<small style={{ fontSize: 10, marginLeft: 4, opacity: 0.6 }}>% UPTIME</small></div>
                </header>
                <svg className="mod-sparkline" viewBox="0 0 360 80" preserveAspectRatio="none">
                  <path className="area" d={paths.area} style={{ fill: p.color, opacity: 0.12 }} />
                  <path className="line" d={paths.line} style={{ stroke: p.color }} />
                </svg>
                <div style={{ display: "flex", justifyContent: "space-between", fontFamily: "'JetBrains Mono', monospace", fontSize: 9, letterSpacing: "0.15em", opacity: 0.55, textTransform: "uppercase", marginTop: 4 }}>
                  <span>30日前</span>
                  <span>本日</span>
                </div>
              </div>
            );
          })}
        </div>

        {/* Methodology */}
        <h2 style={{ fontFamily: "'Crimson Pro', serif", fontSize: 28, fontWeight: 500, margin: "0 0 16px" }}>METHODOLOGY — 計測方法</h2>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", border: "2px solid var(--ink)", marginBottom: 48 }}>
          {[
            { lab: "ノード", v: "東京 / 大阪 / シンガポール 3拠点" },
            { lab: "計測間隔", v: "15分ごと (HEAD request)" },
            { lab: "サンプル数", v: "1社あたり 96 / 日" },
            { lab: "平準化", v: "外れ値5%トリム平均" },
          ].map((m, i) => (
            <div key={i} style={{ padding: "20px 18px", borderRight: i < 3 ? "1px solid var(--ink)" : "none" }}>
              <div style={{ fontFamily: "'JetBrains Mono', monospace", fontSize: 10, letterSpacing: "0.18em", opacity: 0.6 }}>{m.lab}</div>
              <div style={{ fontFamily: "'Crimson Pro', serif", fontSize: 17, fontWeight: 500, marginTop: 6 }}>{m.v}</div>
            </div>
          ))}
        </div>

        <div style={{ background: "var(--cream)", border: "2px solid var(--ink)", padding: "24px 32px", fontSize: 13, lineHeight: 1.85, marginBottom: 48 }}>
          <b style={{ display: "block", marginBottom: 8, fontFamily: "'JetBrains Mono', monospace", letterSpacing: "0.15em", color: "var(--vermilion)" }}>EDITOR'S NOTE</b>
          このダッシュボードはデモ表示として擬似データで動作しています。実装版では編集部独自の計測ノードからリアルタイムに更新されます。広告主からの要望で数値が変更されることはありません (<a href="/pricing.html" style={{ color: "var(--vermilion)", borderBottom: "1px solid currentColor" }}>編集ポリシー</a>)。
        </div>

        <Colophon />
      </main>
    </>
  );
};

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
