type Series = {
  x: number[] | Float64Array | Float32Array;
  y: number[] | Float64Array | Float32Array;
  color: string;
  label: string;
};

type Props = {
  series: Series[];
  width?: number;
  height?: number;
  xLabel?: string;
  yLabel?: string;
};

// Minimal dependency-free line plot rendered as SVG.
export const LinePlot = ({
  series,
  width = 560,
  height = 220,
  xLabel,
  yLabel,
}: Props) => {
  const padL = 48;
  const padR = 12;
  const padT = 10;
  const padB = 34;
  const innerW = width - padL - padR;
  const innerH = height - padT - padB;

  let xMin = Infinity;
  let xMax = -Infinity;
  let yMin = Infinity;
  let yMax = -Infinity;
  for (const s of series) {
    for (let i = 0; i < s.x.length; i++) {
      const xv = s.x[i];
      const yv = s.y[i];
      if (xv < xMin) xMin = xv;
      if (xv > xMax) xMax = xv;
      if (yv < yMin) yMin = yv;
      if (yv > yMax) yMax = yv;
    }
  }
  if (!isFinite(xMin)) {
    xMin = 0;
    xMax = 1;
    yMin = 0;
    yMax = 1;
  }
  if (xMax === xMin) xMax = xMin + 1;
  if (yMax === yMin) yMax = yMin + 1;

  const sx = (x: number) => padL + ((x - xMin) / (xMax - xMin)) * innerW;
  const sy = (y: number) => padT + innerH - ((y - yMin) / (yMax - yMin)) * innerH;

  const pathFor = (s: Series) => {
    let d = "";
    for (let i = 0; i < s.x.length; i++) {
      d += `${i === 0 ? "M" : "L"}${sx(s.x[i]).toFixed(1)},${sy(s.y[i]).toFixed(1)} `;
    }
    return d;
  };

  const fmt = (v: number) =>
    Math.abs(v) >= 1000 || (v !== 0 && Math.abs(v) < 0.01)
      ? v.toExponential(1)
      : v.toFixed(2);

  return (
    <svg
      width={width}
      height={height}
      style={{ background: "#fff", border: "1px solid #e2e2e2" }}
    >
      {/* axes */}
      <line x1={padL} y1={padT} x2={padL} y2={padT + innerH} stroke="#999" />
      <line
        x1={padL}
        y1={padT + innerH}
        x2={padL + innerW}
        y2={padT + innerH}
        stroke="#999"
      />
      {/* y ticks */}
      <text x={padL - 6} y={padT + 4} textAnchor="end" fontSize={10} fill="#555">
        {fmt(yMax)}
      </text>
      <text
        x={padL - 6}
        y={padT + innerH}
        textAnchor="end"
        fontSize={10}
        fill="#555"
      >
        {fmt(yMin)}
      </text>
      {/* x ticks */}
      <text
        x={padL}
        y={padT + innerH + 14}
        textAnchor="start"
        fontSize={10}
        fill="#555"
      >
        {fmt(xMin)}
      </text>
      <text
        x={padL + innerW}
        y={padT + innerH + 14}
        textAnchor="end"
        fontSize={10}
        fill="#555"
      >
        {fmt(xMax)}
      </text>
      {/* axis labels */}
      {xLabel && (
        <text
          x={padL + innerW / 2}
          y={height - 4}
          textAnchor="middle"
          fontSize={11}
          fill="#333"
        >
          {xLabel}
        </text>
      )}
      {yLabel && (
        <text
          x={12}
          y={padT + innerH / 2}
          textAnchor="middle"
          fontSize={11}
          fill="#333"
          transform={`rotate(-90 12 ${padT + innerH / 2})`}
        >
          {yLabel}
        </text>
      )}
      {/* data */}
      {series.map((s, i) => (
        <path key={i} d={pathFor(s)} fill="none" stroke={s.color} strokeWidth={1} />
      ))}
      {/* legend */}
      {series.map((s, i) => (
        <g key={`l${i}`}>
          <rect x={padL + 8} y={padT + 6 + i * 14} width={10} height={3} fill={s.color} />
          <text x={padL + 22} y={padT + 10 + i * 14} fontSize={10} fill="#333">
            {s.label}
          </text>
        </g>
      ))}
    </svg>
  );
};
