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

export interface BarDatum {
  /** Stable id — React key + accessible label. */
  id: string;
  /** Y-value. Negative values are supported (render below the baseline). */
  value: number;
  /** Optional X-axis tick label (default: `id`). */
  label?: string;
  /** Optional override colour. */
  color?: string;
}

export interface BarChartProps {
  data: BarDatum[];
  /** Chart width in px. Default 480. */
  width?: number;
  /** Chart height in px. Default 240. */
  height?: number;
  /** Bar corner radius (px). Default 4. */
  cornerRadius?: number;
  /** Y baseline value (default 0). Use a custom baseline for diverging
   *  charts (e.g. ±deltas around a target). */
  baseline?: number;
  /** Show subtle Y grid lines (3 ticks). Default true. */
  grid?: boolean;
  /** Accessible label. */
  ariaLabel?: string;
  className?: string;
  style?: CSSProperties;
}

/**
 * `<BarChart>` — vertical bar chart with diverging-baseline support.
 *
 * Wave 9.A.2. Token-tinted via `--bl-accent` with per-bar override.
 */
export function BarChart({
  data,
  width = 480,
  height = 240,
  cornerRadius = 4,
  baseline = 0,
  grid = true,
  ariaLabel,
  className,
  style,
}: BarChartProps) {
  const titleId = useId();
  const padL = 36;
  const padR = 12;
  const padT = 12;
  const padB = 28;
  const innerW = Math.max(0, width - padL - padR);
  const innerH = Math.max(0, height - padT - padB);

  const values = data.map((d) => d.value);
  let [yMin, yMax] = extent(values);
  yMin = Math.min(yMin, baseline);
  yMax = Math.max(yMax, baseline);
  const yScale = linearScale(yMin, yMax, innerH, 0);
  const yBase = yScale(baseline);

  const n = data.length;
  const slot = n > 0 ? innerW / n : 0;
  const barW = Math.max(2, slot * 0.7);

  return (
    <svg
      role="img"
      aria-labelledby={titleId}
      viewBox={`0 0 ${width} ${height}`}
      width={width}
      height={height}
      data-testid="bl-bar-chart"
      className={className}
      style={style}
    >
      <title id={titleId}>{ariaLabel ?? 'Bar chart'}</title>
      <g transform={`translate(${padL} ${padT})`}>
        {grid &&
          [yMin, baseline, yMax].map((t, i) => (
            <g key={`g${i}`}>
              <line
                x1={0}
                x2={innerW}
                y1={yScale(t)}
                y2={yScale(t)}
                stroke="var(--bl-border-subtle, rgba(0,0,0,0.06))"
                strokeWidth={1}
              />
              <text
                x={-6}
                y={yScale(t)}
                textAnchor="end"
                dominantBaseline="middle"
                fontSize={10}
                fill="var(--bl-text-tertiary, #888)"
                fontFamily="ui-sans-serif, system-ui, sans-serif"
              >
                {compactNumber(t)}
              </text>
            </g>
          ))}
        {data.map((d, i) => {
          const cx = slot * i + slot / 2;
          const x = cx - barW / 2;
          const y = Math.min(yBase, yScale(d.value));
          const h = Math.abs(yBase - yScale(d.value));
          const colour = d.color ?? 'var(--bl-accent, #6366f1)';
          return (
            <g key={d.id} data-testid="bl-bar-chart-bar" data-bar-id={d.id}>
              <rect
                x={x}
                y={y}
                width={barW}
                height={Math.max(0.5, h)}
                rx={cornerRadius}
                ry={cornerRadius}
                fill={colour}
                opacity={d.value === baseline ? 0.4 : 0.9}
              />
              <text
                x={cx}
                y={innerH + 14}
                textAnchor="middle"
                fontSize={10}
                fill="var(--bl-text-tertiary, #888)"
                fontFamily="ui-sans-serif, system-ui, sans-serif"
              >
                {d.label ?? d.id}
              </text>
            </g>
          );
        })}
      </g>
    </svg>
  );
}

