import { useEffect, useRef } from 'react';
import { cn } from '@/lib/utils';

// A range slider the mouse wheel can move.
//
// Dragging a 4-pixel-tall slider to change the power by five watts is a fussy
// gesture; rolling the wheel over it is not, and it is what an operator reaches
// for after using the Flex and Yaesu consoles, which have had it for a while.
//
// React's own onWheel is registered PASSIVE, so preventDefault() inside it is
// ignored and the panel scrolls under the pointer while the value changes. The
// listener therefore has to be attached natively with { passive: false }, and
// the live values read through refs — the listener is installed once and would
// otherwise capture the first render's value for ever.
//
// The Flex and Yaesu panels each grew their own copy of this before it was worth
// sharing. They are left alone deliberately: they work, they are in daily use,
// and their styling differs in small ways that a merge would have to guess at.
export function WheelRange({ value, onChange, min = 0, max = 100, step = 1, disabled, accent = 'var(--primary)', className }: {
  value: number; onChange: (v: number) => void;
  min?: number; max?: number; step?: number; disabled?: boolean; accent?: string; className?: string;
}) {
  const v = Math.max(min, Math.min(max, value));
  const pct = max > min ? ((v - min) / (max - min)) * 100 : 0;
  const ref = useRef<HTMLInputElement>(null);
  const valRef = useRef(v); valRef.current = v;
  const cbRef = useRef(onChange); cbRef.current = onChange;
  const disRef = useRef(disabled); disRef.current = disabled;
  const stepRef = useRef(step); stepRef.current = step;
  const minRef = useRef(min); minRef.current = min;
  const maxRef = useRef(max); maxRef.current = max;

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const onWheel = (e: WheelEvent) => {
      if (disRef.current) return;
      e.preventDefault();
      const d = e.deltaY < 0 ? stepRef.current : -stepRef.current;
      const nv = Math.max(minRef.current, Math.min(maxRef.current, valRef.current + d));
      if (nv !== valRef.current) cbRef.current(nv);
    };
    el.addEventListener('wheel', onWheel, { passive: false });
    return () => el.removeEventListener('wheel', onWheel);
  }, []);

  return (
    <input
      ref={ref}
      type="range" min={min} max={max} step={step} value={v} disabled={disabled}
      onChange={(e) => onChange(parseInt(e.target.value, 10))}
      className={cn('flex-1 h-1.5 rounded-full appearance-none cursor-pointer disabled:opacity-30 disabled:cursor-default',
        '[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-3.5 [&::-webkit-slider-thumb]:rounded-full',
        '[&::-webkit-slider-thumb]:bg-card [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:shadow-sm [&::-webkit-slider-thumb]:cursor-pointer',
        className)}
      style={{
        background: `linear-gradient(to right, ${accent} ${pct}%, color-mix(in srgb, var(--foreground) 18%, transparent) ${pct}%)`,
        borderColor: accent,
      }}
    />
  );
}
