import type { PerfPoint } from "@/lib/results";

/**
 * Aggregate throughput plotted against concurrency, drawn as a scope sweep.
 *
 * The x axis is logarithmic because concurrency is sampled in octaves
 * (1, 8, 32). On a linear axis the low-concurrency points — the ones that
 * describe what a single user actually feels — collapse against the origin
 * and the most important part of the curve becomes unreadable.
 */
export function ScopeTrace({
  points,
  width = 520,
  height = 150,
  showAxis = true,
}: {
  points: PerfPoint[];
  width?: number;
  height?: number;
  showAxis?: boolean;
}) {
  if (points.length < 2) return null;

  const pad = { top: 14, right: 14, bottom: showAxis ? 22 : 10, left: showAxis ? 46 : 10 };
  const w = width - pad.left - pad.right;
  const h = height - pad.top - pad.bottom;

  const xs = points.map((p) => Math.log2(Math.max(1, p.concurrency)));
  const ys = points.map((p) => p.output_tps_total);
  const xMax = Math.max(...xs) || 1;
  const yMax = Math.max(...ys) * 1.15;

  const px = (i: number) => pad.left + (xs[i] / xMax) * w;
  const py = (v: number) => pad.top + h - (v / yMax) * h;

  const path = points.map((p, i) => `${i === 0 ? "M" : "L"}${px(i)},${py(p.output_tps_total)}`).join(" ");
  const area = `${path} L${px(points.length - 1)},${pad.top + h} L${px(0)},${pad.top + h} Z`;

  // Rough path length so the draw-on animation has a dash offset to work with.
  const traceLen = Math.round(w * 1.6);

  const gridLines = [0, 0.25, 0.5, 0.75, 1];

  return (
    <svg
      viewBox={`0 0 ${width} ${height}`}
      className="w-full"
      role="img"
      aria-label="Aggregate throughput against concurrency"
    >
      <defs>
        <linearGradient id="trace-fill" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="var(--color-signal)" stopOpacity="0.22" />
          <stop offset="100%" stopColor="var(--color-signal)" stopOpacity="0" />
        </linearGradient>
      </defs>

      {gridLines.map((g) => (
        <line
          key={g}
          x1={pad.left}
          x2={pad.left + w}
          y1={pad.top + h - g * h}
          y2={pad.top + h - g * h}
          stroke="var(--color-rule)"
          strokeWidth="1"
        />
      ))}

      {showAxis &&
        gridLines
          .filter((g) => g > 0)
          .map((g) => (
            <text
              key={`l${g}`}
              x={pad.left - 8}
              y={pad.top + h - g * h + 3}
              textAnchor="end"
              className="fill-[var(--color-dimmer)]"
              style={{ fontSize: 9, fontFamily: "var(--font-mono)" }}
            >
              {Math.round(yMax * g)}
            </text>
          ))}

      <path d={area} fill="url(#trace-fill)" />
      <path
        d={path}
        fill="none"
        stroke="var(--color-signal)"
        strokeWidth="1.75"
        strokeLinejoin="round"
        strokeLinecap="round"
        className="trace"
        style={{ ["--trace-len" as string]: traceLen }}
      />

      {points.map((p, i) => (
        <g key={p.concurrency}>
          <circle
            cx={px(i)}
            cy={py(p.output_tps_total)}
            r="3"
            fill="var(--color-void)"
            stroke="var(--color-signal)"
            strokeWidth="1.5"
          />
          {showAxis && (
            <text
              x={px(i)}
              y={height - 6}
              textAnchor="middle"
              className="fill-[var(--color-dimmer)]"
              style={{ fontSize: 9, fontFamily: "var(--font-mono)" }}
            >
              {p.concurrency}
            </text>
          )}
        </g>
      ))}

      {showAxis && (
        <text
          x={pad.left}
          y={11}
          className="fill-[var(--color-dimmer)]"
          style={{ fontSize: 9, letterSpacing: "0.14em", fontFamily: "var(--font-mono)" }}
        >
          TOK/S AGGREGATE ↑ / CONCURRENCY →
        </text>
      )}
    </svg>
  );
}
