// Usage analytics screen
const ANALYTICS_COLORS = {
  chain: "var(--green)", quotes: "var(--cyan)",
  expirations: "var(--amber)", lookup: "var(--violet)",
};

function Analytics() {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [usage, setUsage] = useState(null);
  const [range, setRange] = useState("30d");

  // Guard against setState after unmount — see dashboard.jsx for the pattern.
  const mountedRef = useRef(true);
  useEffect(() => () => { mountedRef.current = false; }, []);
  const load = () => {
    if (!usage) setLoading(true);
    setError("");
    API.cached("/usage", 15 * 1000)
      .then((data) => {
        if (!mountedRef.current) return;
        setUsage(data);
        setLoading(false);
      })
      .catch((err) => {
        if (!mountedRef.current) return;
        setError(err.message || "Could not load analytics.");
        setLoading(false);
      });
  };

  useEffect(load, []);

  if (loading) return <LoadingScreen crumbs={["Console", "Usage"]} />;
  if (error) return <ErrorScreen crumbs={["Console", "Usage"]} message={error} onRetry={load} />;

  const totals = usage.totals;
  const rl = usage.rate_limit;
  const isUnlimitedDaily = rl.limit === null || rl.limit === undefined;
  const quotaPct = isUnlimitedDaily ? 0 : (rl.limit > 0 ? Math.round((rl.used / rl.limit) * 100) : 0);

  if (totals.total === 0) {
    return (
      <>
        <TopBar crumbs={["Console", "Production", "Usage"]} />
        <div className="page">
          <div className="page-head">
            <span className="eyebrow">Last 30 days</span>
            <h1 className="page-title">Usage analytics</h1>
          </div>
          <div className="card">
            <div className="card-body" style={{ textAlign: "center", padding: "56px 20px" }}>
              <Icon.Chart style={{ width: 30, height: 30, color: "var(--muted)" }} />
              <div style={{ fontWeight: 500, marginTop: 14 }}>No usage data yet</div>
              <div className="text-sm muted" style={{ marginTop: 4 }}>
                Send calls through the gateway and your analytics will appear here.
              </div>
            </div>
          </div>
        </div>
      </>
    );
  }

  const daysToShow = range === "24h" ? 2 : range === "7d" ? 7 : 30;
  const daily = (usage.daily || []).slice(-daysToShow);
  const latencyDaily = (usage.latency_daily || []).slice(-daysToShow);

  const series = {
    chain: daily.map((d) => d.chain),
    quotes: daily.map((d) => d.quotes),
    expirations: daily.map((d) => d.expirations),
    lookup: daily.map((d) => d.lookup),
  };
  const stackedMax = Math.max(1, ...daily.map((d) => d.total));

  const latency = {
    p50: sparkData(latencyDaily.map((d) => d.p50)),
    p95: sparkData(latencyDaily.map((d) => d.p95)),
    p99: sparkData(latencyDaily.map((d) => d.p99)),
  };

  // 7×24 rate-limit heatmap grid (dow 0=Sun .. 6=Sat).
  const hmMax = Math.max(1, ...usage.heatmap.map((h) => h.count));
  const grid = Array.from({ length: 7 }, () => Array.from({ length: 24 }, () => 0));
  usage.heatmap.forEach((h) => {
    if (h.dow >= 0 && h.dow < 7 && h.hour >= 0 && h.hour < 24) {
      grid[h.dow][h.hour] = h.count / hmMax;
    }
  });

  // HTTP status mix.
  const statusGroups = { ok: 0, ratelimited: 0, client: 0, server: 0 };
  usage.by_status.forEach((s) => {
    if (s.status_code === 429) statusGroups.ratelimited += s.count;
    else if (s.status_code >= 500) statusGroups.server += s.count;
    else if (s.status_code >= 400) statusGroups.client += s.count;
    else statusGroups.ok += s.count;
  });
  const statusRows = [
    ["2xx · Success", statusGroups.ok, "var(--green)"],
    ["429 · Rate limited", statusGroups.ratelimited, "var(--amber)"],
    ["4xx · Client error", statusGroups.client, "var(--cyan)"],
    ["5xx · Server error", statusGroups.server, "var(--red)"],
  ];

  const exportCsv = () => {
    const rows = [["date", "total", "chain", "quotes", "expirations", "lookup"]];
    (usage.daily || []).forEach((d) => rows.push([d.date, d.total, d.chain, d.quotes, d.expirations, d.lookup]));
    const csv = rows.map((r) => r.join(",")).join("\n");
    const blob = new Blob([csv], { type: "text/csv" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "market-options-usage.csv";
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  return (
    <>
      <TopBar crumbs={["Console", "Production", "Usage"]} />
      <div className="page">
        <div className="page-head row" style={{ alignItems: "flex-end", justifyContent: "space-between" }}>
          <div>
            <span className="eyebrow">Last 30 days</span>
            <h1 className="page-title">Usage analytics</h1>
            <p className="page-sub">Where your traffic goes, how fast it returns, and how close to the limit you are.</p>
          </div>
          <div className="row gap-6">
            {["24h", "7d", "30d"].map((r) => (
              <button key={r} className="btn"
                style={r === range ? { background: "var(--panel-2)", color: "var(--text)" } : null}
                onClick={() => setRange(r)}>{r}</button>
            ))}
            <button className="btn" onClick={exportCsv}><Icon.Docs style={{ width: 13, height: 13 }} /> Export CSV</button>
          </div>
        </div>

        {/* KPI tiles */}
        <div className="grid g-4" style={{ marginBottom: 20 }}>
          <KPI label="Total calls" value={Fmt.num(totals.total)} delta={Fmt.num(totals.today) + " today"} tone="up" />
          <KPI label="p95 latency" value={totals.p95_latency_ms + " ms"} delta={totals.avg_latency_ms + " ms average"} tone="up" />
          <KPI label="Error rate" value={(totals.error_rate * 100).toFixed(2) + "%"} delta={Fmt.num(totals.errors) + " errors total"} tone={totals.error_rate > 0.05 ? "down" : "up"} />
          <KPI
            label="Used of quota"
            value={isUnlimitedDaily ? "—" : quotaPct + "%"}
            delta={isUnlimitedDaily
              ? Fmt.num(rl.used) + " today · unlimited daily"
              : Fmt.num(rl.used) + " / " + Fmt.num(rl.limit) + " today"}
            tone="flat"
          />
        </div>

        {/* Stacked bars + legend */}
        <div className="card" style={{ marginBottom: 20 }}>
          <div className="card-head">
            <span>Calls by endpoint</span>
            <div className="legend" style={{ marginLeft: 16 }}>
              <span><i style={{ background: "var(--green)" }} />chain</span>
              <span><i style={{ background: "var(--cyan)" }} />quotes</span>
              <span><i style={{ background: "var(--amber)" }} />expirations</span>
              <span><i style={{ background: "var(--violet)" }} />lookup</span>
            </div>
            <span className="mono text-xs muted" style={{ marginLeft: "auto" }}>granularity: daily</span>
          </div>
          <div className="card-body" style={{ paddingTop: 14 }}>
            <StackedBarChart series={series} max={stackedMax} />
          </div>
        </div>

        {/* Latency line + breakdown table */}
        <div className="grid" style={{ gridTemplateColumns: "1.2fr 1fr", gap: 20, marginBottom: 20 }}>
          <div className="card">
            <div className="card-head">
              <span>Latency · p50 / p95 / p99</span>
              <span className="mono text-xs muted" style={{ marginLeft: "auto" }}>milliseconds</span>
            </div>
            <div className="card-body">
              <LatencyChart p50={latency.p50} p95={latency.p95} p99={latency.p99} />
            </div>
          </div>

          <div className="card">
            <div className="card-head"><span>Endpoint breakdown</span></div>
            <div className="card-body" style={{ padding: 0 }}>
              <table className="tbl">
                <thead>
                  <tr>
                    <th>Endpoint</th>
                    <th>Calls</th>
                    <th>Share</th>
                    <th>p95</th>
                  </tr>
                </thead>
                <tbody>
                  {usage.by_endpoint.length === 0 && (
                    <tr><td colSpan="4" className="text-sm muted" style={{ padding: "16px 12px" }}>No calls yet.</td></tr>
                  )}
                  {usage.by_endpoint.map((r) => {
                    const family = r.endpoint.split("/")[1] || r.endpoint;
                    const color = ANALYTICS_COLORS[family] || "var(--muted)";
                    const share = totals.total > 0 ? r.count / totals.total : 0;
                    return (
                      <tr key={r.endpoint}>
                        <td>
                          <div className="row gap-10">
                            <i style={{ width: 8, height: 8, borderRadius: 2, background: color }} />
                            <span className="mono">/{family}</span>
                          </div>
                        </td>
                        <td className="mono">{Fmt.num(r.count)}</td>
                        <td style={{ width: 140 }}>
                          <div className="meter"><i style={{ width: (share * 100) + "%", background: color }} /></div>
                          <span className="mono text-xs muted" style={{ marginTop: 4, display: "inline-block" }}>{(share * 100).toFixed(0)}%</span>
                        </td>
                        <td className="mono">{r.p95_latency_ms}ms</td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </div>
        </div>

        {/* Rate limit heatmap + status mix */}
        <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", gap: 20 }}>
          <div className="card">
            <div className="card-head">
              <span>Call volume heatmap</span>
              <span className="mono text-xs muted" style={{ marginLeft: "auto" }}>last 7 days</span>
            </div>
            <div className="card-body">
              <RateHeatmap grid={grid} />
              <div className="row mono text-xs muted" style={{ marginTop: 12, justifyContent: "space-between" }}>
                <span>00:00</span><span>06:00</span><span>12:00</span><span>18:00</span><span>24:00</span>
              </div>
              <div className="row gap-10" style={{ marginTop: 14, alignItems: "center" }}>
                <span className="text-xs muted">low</span>
                <div style={{ flex: 1, height: 8, borderRadius: 4, background: "linear-gradient(90deg, oklch(0.205 0.014 240), var(--green) 40%, var(--amber) 80%, var(--red))" }} />
                <span className="text-xs muted">high</span>
              </div>
            </div>
          </div>

          <div className="card">
            <div className="card-head"><span>HTTP status mix</span></div>
            <div className="card-body">
              <div style={{ display: "flex", height: 36, borderRadius: 6, overflow: "hidden", border: "1px solid var(--border-soft)" }}>
                {statusRows.map((r, i) => {
                  const pct = totals.total > 0 ? (r[1] / totals.total) * 100 : 0;
                  return pct > 0 ? <div key={i} style={{ width: pct + "%", background: r[2] }} title={r[0]} /> : null;
                })}
              </div>
              <div style={{ display: "flex", flexDirection: "column", gap: 10, marginTop: 18 }}>
                {statusRows.map((r, i) => {
                  const pct = totals.total > 0 ? (r[1] / totals.total) * 100 : 0;
                  return (
                    <div key={i} className="row" style={{ gap: 12 }}>
                      <i style={{ width: 8, height: 8, borderRadius: 2, background: r[2], flex: "0 0 8px" }} />
                      <span className="mono text-sm" style={{ flex: 1 }}>{r[0]}</span>
                      <span className="mono text-sm muted">{Fmt.num(r[1])}</span>
                      <span className="mono text-xs muted" style={{ width: 50, textAlign: "right" }}>{pct.toFixed(1)}%</span>
                    </div>
                  );
                })}
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

function KPI({ label, value, delta, tone = "up" }) {
  return (
    <div className="stat">
      <span className="label">{label}</span>
      <div className="value">{value}</div>
      <div className={`trend ${tone}`}>
        {tone === "up" && <span>▲</span>}
        {tone === "down" && <span style={{ color: "var(--red)" }}>▼</span>}
        {delta}
      </div>
    </div>
  );
}

function StackedBarChart({ series, max }) {
  const W = 900, H = 260, P = 32;
  const n = Math.max(1, series.chain.length);
  const bw = (W - P * 2) / n - 2;
  const colors = ANALYTICS_COLORS;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="chart" style={{ height: 280 }} preserveAspectRatio="none">
      {[0.25, 0.5, 0.75, 1].map((g, i) => (
        <g key={i}>
          <line x1={P} x2={W - P} y1={H - P - (H - P * 2) * g} y2={H - P - (H - P * 2) * g} className="chart-grid" />
          <text x={P - 6} y={H - P - (H - P * 2) * g + 3} className="chart-label" textAnchor="end">{Math.round(max * g)}</text>
        </g>
      ))}
      {series.chain.map((_, i) => {
        const x = P + i * ((W - P * 2) / n) + 1;
        let cy = H - P;
        const stacks = ["lookup", "expirations", "quotes", "chain"].map((k) => {
          const v = series[k][i] || 0;
          const h = ((H - P * 2) * v) / max;
          cy -= h;
          return <rect key={k} x={x} y={cy} width={Math.max(1, bw)} height={h} fill={colors[k]} opacity={k === "chain" ? 1 : 0.85} />;
        });
        return <g key={i}>{stacks}</g>;
      })}
      {[0, 5, 10, 15, 20, 25, 29].filter((i) => i < n).map((i) => (
        <text key={i} x={P + i * ((W - P * 2) / n) + bw / 2} y={H - 10} className="chart-label" textAnchor="middle">d{i + 1}</text>
      ))}
      <line x1={P} x2={W - P} y1={H - P} y2={H - P} className="chart-axis" />
    </svg>
  );
}

function LatencyChart({ p50, p95, p99 }) {
  const W = 700, H = 240, P = 32;
  const max = Math.max(120, ...p99) * 1.1;
  const min = 0;
  const toPath = (data) => data.map((v, i) => {
    const x = P + (i / Math.max(1, data.length - 1)) * (W - P * 2);
    const y = H - P - ((v - min) / (max - min)) * (H - P * 2);
    return `${i === 0 ? "M" : "L"}${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(" ");
  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="chart" preserveAspectRatio="none">
      {[0.25, 0.5, 0.75, 1].map((g, i) => (
        <g key={i}>
          <line x1={P} x2={W - P} y1={H - P - (H - P * 2) * g} y2={H - P - (H - P * 2) * g} className="chart-grid" />
          <text x={P - 6} y={H - P - (H - P * 2) * g + 3} className="chart-label" textAnchor="end">{Math.round(max * g)}</text>
        </g>
      ))}
      <path d={toPath(p99)} stroke="var(--red)" strokeWidth="1.5" fill="none" opacity="0.7" />
      <path d={toPath(p95)} stroke="var(--amber)" strokeWidth="1.8" fill="none" />
      <path d={toPath(p50)} stroke="var(--green)" strokeWidth="2" fill="none" />
      <line x1={P} x2={W - P} y1={H - P} y2={H - P} className="chart-axis" />
      <g transform={`translate(${P + 8}, ${P - 16})`}>
        {[["p50", "var(--green)"], ["p95", "var(--amber)"], ["p99", "var(--red)"]].map((it, i) => (
          <g key={i} transform={`translate(${i * 64}, 0)`}>
            <rect width="9" height="9" fill={it[1]} rx="1.5" />
            <text x="14" y="9" className="chart-label" style={{ fill: "var(--text-dim)" }}>{it[0]}</text>
          </g>
        ))}
      </g>
    </svg>
  );
}

function RateHeatmap({ grid }) {
  const cellW = 16, cellH = 16, gap = 2;
  const W = 24 * (cellW + gap), H = 7 * (cellH + gap);
  const days = ["S", "M", "T", "W", "T", "F", "S"];
  return (
    <svg viewBox={`0 0 ${W + 18} ${H}`} style={{ width: "100%", height: H }}>
      {grid.map((row, d) => (
        <g key={d}>
          <text x="0" y={d * (cellH + gap) + cellH - 4} className="chart-label">{days[d]}</text>
          {row.map((v, h) => {
            const color = v < 0.3 ? "var(--green)" : v < 0.6 ? "var(--cyan)" : v < 0.85 ? "var(--amber)" : "var(--red)";
            return (
              <rect key={h}
                x={18 + h * (cellW + gap)} y={d * (cellH + gap)}
                width={cellW} height={cellH}
                rx={3} fill={color} opacity={0.15 + v * 0.85}
              />
            );
          })}
        </g>
      ))}
    </svg>
  );
}

Object.assign(window, { Analytics });
