import * as React from 'react';
import { useKnobTheme } from '../core/theme';
import { Meter, type MeterProps } from './Meter';

export interface MeterBridgeChannel {
  label: string;
  value: number;
  /** Peak signal for clip detection, when different from `value`. */
  clipValue?: number;
}

export interface MeterBridgeProps
  extends Omit<MeterProps, 'value' | 'clipValue' | 'label' | 'showValue' | 'aria-label'> {
  channels: readonly MeterBridgeChannel[];
  /** Numeric peak-hold text above each bar. Default: true. */
  showPeakText?: boolean;
  /** Decimals for the peak text. Default: 1. */
  peakTextDecimals?: number;
  /** Block caption under the bridge. */
  label?: string;
  'aria-label'?: string;
}

/**
 * A labeled multi-strip meter block — n channels, per-channel peak text, one
 * shared clip LED. The composition every mixer rebuilds, prebuilt.
 */
export const MeterBridge: React.FC<MeterBridgeProps> = ({
  channels,
  showPeakText = true,
  peakTextDecimals = 1,
  label,
  min = 0,
  max = 100,
  breadth = 16,
  peakHold = 1200,
  className,
  style,
  ...meterProps
}) => {
  const theme = useKnobTheme();
  const values = channels.map(c => c.value);
  const clipValues = channels.map(c => c.clipValue ?? c.value);
  const chGap = channels.length > 1 ? 3 : 0;

  // Numeric peak-hold per channel for the text row.
  const [peaks, setPeaks] = React.useState<readonly number[]>(values);
  React.useEffect(() => {
    if (peakHold === false) return;
    setPeaks(prev =>
      prev.length === values.length ? values.map((v, i) => Math.max(v, prev[i] ?? -Infinity)) : values,
    );
    const t = setTimeout(() => setPeaks(values), peakHold);
    return () => clearTimeout(t);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [JSON.stringify(values), peakHold]);

  const cell: React.CSSProperties = {
    width: breadth,
    textAlign: 'center',
    fontFamily: theme.fontMono,
    whiteSpace: 'nowrap',
    overflow: 'visible',
  };

  return (
    <div
      className={className}
      role="group"
      aria-label={meterProps['aria-label' as never] ?? label}
      style={{ display: 'inline-flex', flexDirection: 'column', alignItems: 'center', gap: 4, ...style }}
    >
      {showPeakText && (
        <div style={{ display: 'flex', gap: chGap }}>
          {peaks.map((p, i) => (
            <span key={i} style={{ ...cell, fontSize: 9, color: theme.label }}>
              {Math.max(p, min) <= min ? '—' : Math.min(p, max).toFixed(peakTextDecimals)}
            </span>
          ))}
        </div>
      )}
      <Meter
        {...meterProps}
        min={min}
        max={max}
        breadth={breadth}
        peakHold={peakHold}
        value={values}
        clipValue={clipValues}
        aria-label={undefined}
      />
      <div style={{ display: 'flex', gap: chGap }}>
        {channels.map(c => (
          <span
            key={c.label}
            style={{
              ...cell,
              fontSize: 9.5,
              fontFamily: theme.fontUI,
              letterSpacing: '0.05em',
              textTransform: 'uppercase',
              color: theme.label,
            }}
          >
            {c.label}
          </span>
        ))}
      </div>
      {label && (
        <span
          style={{
            fontFamily: theme.fontUI,
            fontSize: 11,
            letterSpacing: '0.08em',
            textTransform: 'uppercase',
            color: theme.label,
          }}
        >
          {label}
        </span>
      )}
    </div>
  );
};
