/* aux-gauges.jsx
 * Side-panel gauges around the speedometer:
 *   - Odometer (rolling digit counter)
 *   - Latency curve mini chart
 *   - Case checklist
 */

const { useEffect, useState, useRef: useRefAux } = React;

/* ── Odometer ────────────────────────────────────────────────
 * value: integer to display
 * digits: minimum digit count (left-padded with 0)
 * Each digit rolls vertically via translateY through 0..9 stripe.
 */
function Odometer({ value, digits = 6 }) {
  const intVal = Math.max(0, Math.floor(value || 0));
  const str = String(intVal).padStart(digits, "0");
  const chars = str.split("");
  // Each digit reels to the current digit value. Maintain a small persistent
  // offset so transitions feel smooth (not instant snap on each render).
  return (
    <div className="odometer">
      {chars.map((ch, i) => (
        <React.Fragment key={i}>
          <Digit ch={ch} />
          {i === chars.length - 4 && chars.length > 4 ? <span className="sep">,</span> : null}
        </React.Fragment>
      ))}
    </div>
  );
}

function Digit({ ch }) {
  const target = Number.isFinite(Number(ch)) ? Number(ch) : 0;
  // Track cumulative offset so e.g. going 8 → 1 rolls through 9 (not backwards).
  const cumRef = useRefAux(target);
  const lastRef = useRefAux(target);
  if (target !== lastRef.current) {
    let next = cumRef.current;
    const last = lastRef.current;
    // Advance forwards: digits roll +1 each step
    let steps = target - last;
    if (steps <= 0) steps += 10;
    next += steps;
    cumRef.current = next;
    lastRef.current = target;
  }
  const offset = cumRef.current;
  return (
    <span className="digit">
      <span className="roll" style={{ transform: `translateY(-${(offset % 10) * 38}px)` }}>
        {Array.from({ length: 10 }, (_, i) => (
          <span key={i}>{i}</span>
        ))}
      </span>
    </span>
  );
}

/* ── Latency curve ──────────────────────────────────────────
 * Renders the per-case latency as a tiny line chart with status-colored points.
 */
function LatencyMiniChart({ cases }) {
  const total = cases.length;
  const known = cases
    .filter((c) => Number.isFinite(c.latencyMs) && c.latencyMs > 0)
    .map((c) => c.latencyMs);
  const maxLatency = niceMax(Math.max(0, ...known, 1000));

  // byok.icu: per-case OUTPUT token speed (tok/s) plotted as a line on a right axis,
  // overlaid on the per-case latency bars (left axis, ms).
  const speedOf = (c) =>
    Number.isFinite(c.latencyMs) && c.latencyMs > 0 && Number.isFinite(c.outputTokens) && c.outputTokens > 0
      ? c.outputTokens / (c.latencyMs / 1000)
      : null;
  const speeds = cases.map(speedOf).filter((s) => s != null);
  const maxSpeed = niceMaxSpeed(Math.max(1, ...speeds));

  const w = 300;
  const h = 150;
  const pad = { l: 34, r: 30, t: 12, b: 20 }; // r widened for the right (token-rate) axis
  const innerW = w - pad.l - pad.r;
  const innerH = h - pad.t - pad.b;
  const baseY = pad.t + innerH;
  const slot = innerW / Math.max(1, total);
  const barW = Math.min(24, slot * 0.62);
  const xCenter = (i) => pad.l + slot * i + slot / 2;
  const yAt = (lat) => baseY - (Math.min(lat, maxLatency) / maxLatency) * innerH;
  const ySpeed = (s) => baseY - (Math.min(s, maxSpeed) / maxSpeed) * innerH;

  const ticks = [0, maxLatency / 2, maxLatency];
  const sticks = [0, maxSpeed / 2, maxSpeed];
  const fmtMs = (v) =>
    v >= 1000 ? `${(v / 1000).toFixed(v % 1000 === 0 ? 0 : 1)}k` : String(Math.round(v));
  const fmtSpeed = (v) => (v >= 1000 ? `${(v / 1000).toFixed(1)}k` : String(Math.round(v)));

  const linePts = cases
    .map((c, i) => ({ i, s: speedOf(c) }))
    .filter((p) => p.s != null)
    .map((p) => `${xCenter(p.i).toFixed(1)},${ySpeed(p.s).toFixed(1)}`)
    .join(" ");

  return (
    <svg
      className="latency-svg latency-bars"
      viewBox={`0 0 ${w} ${h}`}
      preserveAspectRatio="xMidYMid meet"
      aria-label="Latency per case (bars, ms) and output token rate (line, tok/s)"
    >
      {ticks.map((t, i) => {
        const y = yAt(t);
        return (
          <g key={`tick-${i}`}>
            {i > 0 ? (
              <line className="latency-grid" x1={pad.l} y1={y} x2={pad.l + innerW} y2={y} vectorEffect="non-scaling-stroke" />
            ) : null}
            <text className="latency-tlabel" x={pad.l - 5} y={y + 3} textAnchor="end">{fmtMs(t)}</text>
          </g>
        );
      })}
      {/* right axis: output token rate (tok/s) */}
      {sticks.map((s, i) => (
        <text key={`stick-${i}`} className="latency-tlabel speed" x={pad.l + innerW + 5} y={ySpeed(s) + 3} textAnchor="start">{fmtSpeed(s)}</text>
      ))}

      <line className="latency-axis" x1={pad.l} y1={pad.t} x2={pad.l} y2={baseY} vectorEffect="non-scaling-stroke" />
      <line className="latency-axis" x1={pad.l} y1={baseY} x2={pad.l + innerW} y2={baseY} vectorEffect="non-scaling-stroke" />
      <line className="latency-axis speed" x1={pad.l + innerW} y1={pad.t} x2={pad.l + innerW} y2={baseY} vectorEffect="non-scaling-stroke" />

      {cases.map((c, i) => {
        const hasVal = Number.isFinite(c.latencyMs) && c.latencyMs > 0;
        const cx = xCenter(i);
        const statusCls = c.status === "failed" ? "failed" : c.status === "completed" ? "completed" : "pending";
        const barH = hasVal ? Math.max(1.5, baseY - yAt(c.latencyMs)) : 2;
        return (
          <g key={c.id}>
            <rect className={`latency-bar ${statusCls}`} x={cx - barW / 2} y={baseY - barH} width={barW} height={barH} rx="1.5" />
            {hasVal ? (
              <text className="latency-bar-val" x={cx} y={baseY - barH - 3} textAnchor="middle">{fmtMs(c.latencyMs)}</text>
            ) : null}
            <text className="latency-tlabel" x={cx} y={baseY + 13} textAnchor="middle">{i + 1}</text>
          </g>
        );
      })}

      {/* token-rate line + points */}
      {linePts ? (
        <polyline className="latency-speed-line" points={linePts} vectorEffect="non-scaling-stroke" fill="none" />
      ) : null}
      {cases.map((c, i) => {
        const s = speedOf(c);
        return s != null ? (
          <circle key={`sp-${c.id}`} className="latency-speed-dot" cx={xCenter(i)} cy={ySpeed(s)} r="2.3" />
        ) : null;
      })}
    </svg>
  );
}

function niceMax(value) {
  if (!Number.isFinite(value) || value <= 0) return 1000;
  if (value <= 1000) return 1000;
  if (value <= 2000) return 2000;
  if (value <= 4000) return 4000;
  return Math.ceil(value / 1000) * 1000;
}

function niceMaxSpeed(value) {
  if (!Number.isFinite(value) || value <= 0) return 50;
  var steps = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000];
  for (var i = 0; i < steps.length; i++) { if (value <= steps[i]) return steps[i]; }
  return Math.ceil(value / 1000) * 1000;
}

/* ── Case checklist ─────────────────────────────────────────
 * Sidebar list of all 7 cases with status, used in the cockpit "right" panel.
 */
function CaseChecklist({ cases, currentCaseIdx }) {
  return (
    <div className="case-list">
      {cases.map((c, i) => {
        const isCurrent = i === currentCaseIdx;
        const cls = isCurrent && c.status === "pending" ? "running" : c.status;
        return (
          <div key={c.id} className={`case-row ${cls}`}>
            <span className="badge">{String(i + 1).padStart(2, "0")}</span>
            {/* Card 92-10: case label via the global i18n helper (window.byokicuTr / app.jsx). */}
            <span>{tr("case." + c.id + ".short")}</span>
            <span className="ms">
              {Number.isFinite(c.latencyMs) ? `${Math.round(c.latencyMs)}ms` : isCurrent ? "…" : ""}
            </span>
          </div>
        );
      })}
    </div>
  );
}

Object.assign(window, { Odometer, LatencyMiniChart, CaseChecklist });
