import { useId, type CSSProperties } from 'react';
import { compactNumber, extent, filterFinite, linearScale, smoothPath } from './utils.js';

export interface AreaChartProps {
  /** Series Y-values. */
  values: number[];
  /** Chart width in px. Default 480. */
  width?: number;
  /** Chart height in px. Default 240. */
  height?: number;
  /** Smooth (catmull-rom) vs straight polyline. Default smooth. */
  smooth?: boolean;
  /** Override stroke + fill base colour. */
  color?: string;
  /** Accessible label. */
  ariaLabel?: string;
  className?: string;
  style?: CSSProperties;
}

/**
 * `<AreaChart>` — single-series filled area chart with gradient.
 *
 * Wave 9.A.3.
 */
export function AreaChart({
  values,
  width = 480,
  height = 240,
  smooth = true,
  color = 'var(--bl-accent, #6366f1)',
  ariaLabel,
  className,
  style,
}: AreaChartProps) {
  const titleId = useId();
  const gradId = useId();
  const padL = 36;
  const padR = 12;
  const padT = 12;
  const padB = 24;
  const innerW = Math.max(0, width - padL - padR);
  const innerH = Math.max(0, height - padT - padB);

  const finitePairs = filterFinite(values);
  const finiteValues = finitePairs.map(([, v]) => v);
  const [yMin, yMax] = extent(finiteValues);
  const yMinDisplay = Math.min(0, yMin);
  const yScale = linearScale(yMinDisplay, yMax, innerH, 0);
  const xScale = (i: number) =>
    values.length > 1 ? (i / (values.length - 1)) * innerW : innerW / 2;

  const points: Array<[number, number]> = finitePairs.map(([i, v]) => [
    xScale(i),
    yScale(v),
  ]);
  const linePath = smooth
    ? smoothPath(points)
    : `M ${points.map(([x, y]) => `${x} ${y}`).join(' L ')}`;
  const closeY = yScale(yMinDisplay);
  const areaPath = points.length
    ? `${linePath} L ${points[points.length - 1]![0]} ${closeY} L ${points[0]![0]} ${closeY} Z`
    : '';

  return (
    <svg
      role="img"
      aria-labelledby={titleId}
      viewBox={`0 0 ${width} ${height}`}
      width={width}
      height={height}
      data-testid="bl-area-chart"
      className={className}
      style={style}
    >
      <title id={titleId}>{ariaLabel ?? 'Area chart'}</title>
      <defs>
        <linearGradient id={gradId} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity={0.35} />
          <stop offset="100%" stopColor={color} stopOpacity={0} />
        </linearGradient>
      </defs>
      <g transform={`translate(${padL} ${padT})`}>
        <line
          x1={0}
          x2={innerW}
          y1={closeY}
          y2={closeY}
          stroke="var(--bl-border-subtle, rgba(0,0,0,0.06))"
          strokeWidth={1}
        />
        <path d={areaPath} fill={`url(#${gradId})`} stroke="none" />
        <path d={linePath} fill="none" stroke={color} strokeWidth={2} />
        {/* baseline + max labels */}
        <text
          x={-6}
          y={closeY}
          textAnchor="end"
          dominantBaseline="middle"
          fontSize={10}
          fill="var(--bl-text-tertiary, #888)"
        >
          {compactNumber(yMinDisplay)}
        </text>
        <text
          x={-6}
          y={yScale(yMax)}
          textAnchor="end"
          dominantBaseline="middle"
          fontSize={10}
          fill="var(--bl-text-tertiary, #888)"
        >
          {compactNumber(yMax)}
        </text>
      </g>
    </svg>
  );
}

