import { useId, type CSSProperties, type ReactNode } from 'react';

export interface GaugeProps {
  /** Current value (clamped to `[min, max]`). */
  value: number;
  /** Domain minimum. Default 0. */
  min?: number;
  /** Domain maximum. Default 100. */
  max?: number;
  /** SVG size in px (gauge is a half-circle). Default 200. */
  size?: number;
  /** Ring track thickness in px. Default 12. */
  thickness?: number;
  /** Optional override colour. */
  color?: string;
  /** Slot rendered below the gauge dial. */
  caption?: ReactNode;
  /** Accessible label. */
  ariaLabel?: string;
  className?: string;
  style?: CSSProperties;
}

/**
 * `<Gauge>` — half-circle dial for single-metric "fuel-tank" surfaces
 * (battery state, capacity used, NPS, etc.).
 *
 * Wave 9.A.4. Tinted by `--bl-accent`. Out-of-range / non-finite
 * values clamp safely.
 */
export function Gauge({
  value,
  min = 0,
  max = 100,
  size = 200,
  thickness = 12,
  color = 'var(--bl-accent, #6366f1)',
  caption,
  ariaLabel,
  className,
  style,
}: GaugeProps) {
  const titleId = useId();
  const safeValue = Number.isFinite(value) ? value : min;
  const clamped = Math.max(min, Math.min(max, safeValue));
  const pct = max > min ? (clamped - min) / (max - min) : 0;

  const cx = size / 2;
  const cy = size * 0.7;
  const r = Math.min(size / 2 - thickness, size * 0.4);
  // Half-circle: angle goes from π (left) to 0 (right), i.e. 180° → 0°.
  const startAngle = Math.PI;
  const endAngle = Math.PI - pct * Math.PI;
  const x0 = cx + r * Math.cos(startAngle);
  const y0 = cy + r * Math.sin(startAngle);
  const x1 = cx + r * Math.cos(endAngle);
  const y1 = cy + r * Math.sin(endAngle);
  const trackD = [
    `M ${cx - r} ${cy}`,
    `A ${r} ${r} 0 0 1 ${cx + r} ${cy}`,
  ].join(' ');
  const fillD =
    pct === 0
      ? ''
      : [
          `M ${x0} ${y0}`,
          `A ${r} ${r} 0 0 1 ${x1} ${y1}`,
        ].join(' ');

  return (
    <svg
      role="img"
      aria-labelledby={titleId}
      viewBox={`0 0 ${size} ${size * 0.85}`}
      width={size}
      height={size * 0.85}
      data-testid="bl-gauge"
      data-value={clamped}
      className={className}
      style={style}
    >
      <title id={titleId}>{ariaLabel ?? `Gauge ${clamped} of ${max}`}</title>
      <path
        d={trackD}
        fill="none"
        stroke="var(--bl-surface-muted, rgba(0,0,0,0.08))"
        strokeWidth={thickness}
        strokeLinecap="round"
      />
      {fillD && (
        <path
          d={fillD}
          fill="none"
          stroke={color}
          strokeWidth={thickness}
          strokeLinecap="round"
        />
      )}
      <text
        x={cx}
        y={cy - 4}
        textAnchor="middle"
        fontSize={Math.round(size * 0.18)}
        fontWeight={700}
        fill="var(--bl-text-primary, #111)"
        fontFamily="ui-sans-serif, system-ui, sans-serif"
        style={{ fontVariantNumeric: 'tabular-nums' }}
      >
        {Math.round(clamped)}
      </text>
      {caption && (
        <foreignObject x={0} y={cy + 4} width={size} height={28}>
          <div
            style={{
              textAlign: 'center',
              fontSize: 11,
              color: 'var(--bl-text-tertiary, #888)',
              fontFamily: 'ui-sans-serif, system-ui, sans-serif',
            }}
          >
            {caption}
          </div>
        </foreignObject>
      )}
    </svg>
  );
}
