'use client';

import * as React from 'react';
import { cn } from '@/lib/utils/cn';

export interface VerticalFaderProps {
  value: number; // 0.0 to 1.0
  level?: number; // 0.0 to 1.0 (for level meter display)
  onChange: (value: number) => void;
  min?: number;
  max?: number;
  step?: number;
  className?: string;
  showDb?: boolean;
  onTouchStart?: () => void;
  onTouchEnd?: () => void;
}

export function VerticalFader({
  value,
  level = 0,
  onChange,
  min = 0,
  max = 1,
  step = 0.01,
  className,
  showDb = true,
  onTouchStart,
  onTouchEnd,
}: VerticalFaderProps) {
  const trackRef = React.useRef<HTMLDivElement>(null);
  const [isDragging, setIsDragging] = React.useState(false);

  const updateValue = React.useCallback(
    (clientY: number) => {
      if (!trackRef.current) return;

      const rect = trackRef.current.getBoundingClientRect();
      const height = rect.height;
      const y = Math.max(0, Math.min(height, clientY - rect.top));

      // Invert Y (top = max, bottom = min)
      const percentage = 1 - y / height;
      const range = max - min;
      let newValue = min + percentage * range;

      // Snap to step
      if (step) {
        newValue = Math.round(newValue / step) * step;
      }

      // Clamp to range
      newValue = Math.max(min, Math.min(max, newValue));

      onChange(newValue);
    },
    [min, max, step, onChange]
  );

  const handleMouseDown = React.useCallback(
    (e: React.MouseEvent) => {
      e.preventDefault();
      setIsDragging(true);
      updateValue(e.clientY);
      onTouchStart?.();
    },
    [updateValue, onTouchStart]
  );

  const handleMouseMove = React.useCallback(
    (e: MouseEvent) => {
      if (isDragging) {
        updateValue(e.clientY);
      }
    },
    [isDragging, updateValue]
  );

  const handleMouseUp = React.useCallback(() => {
    setIsDragging(false);
    onTouchEnd?.();
  }, [onTouchEnd]);

  React.useEffect(() => {
    if (isDragging) {
      window.addEventListener('mousemove', handleMouseMove);
      window.addEventListener('mouseup', handleMouseUp);

      return () => {
        window.removeEventListener('mousemove', handleMouseMove);
        window.removeEventListener('mouseup', handleMouseUp);
      };
    }
  }, [isDragging, handleMouseMove, handleMouseUp]);

  // Convert value to percentage (0-100)
  const valuePercentage = ((value - min) / (max - min)) * 100;

  // Convert level to dB for display
  const db = value === 0 ? -Infinity : 20 * Math.log10(value);
  const levelDb = level === 0 ? -Infinity : (level * 60) - 60;

  return (
    <div className={cn('flex flex-col items-center gap-1', className)}>
      {/* dB Display */}
      {showDb && (
        <div className="text-[10px] font-mono text-muted-foreground min-w-[32px] text-center">
          {db === -Infinity ? '-∞' : `${db.toFixed(1)}`}
        </div>
      )}

      {/* Fader Track */}
      <div
        ref={trackRef}
        onMouseDown={handleMouseDown}
        className="relative w-8 flex-1 min-h-[80px] max-h-[140px] bg-background/50 border border-border rounded cursor-pointer select-none overflow-hidden"
      >
        {/* Volume Level Overlay - subtle fill up to fader handle */}
        <div
          className="absolute bottom-0 left-0 right-0 bg-primary/10"
          style={{ height: `${valuePercentage}%` }}
        />

        {/* Level Meter (actual level) - capped at fader handle position */}
        <div
          className="absolute bottom-0 left-0 right-0 transition-all duration-75"
          style={{
            height: `${Math.min(level * 100, valuePercentage)}%`,
            background: 'linear-gradient(to top, rgb(34, 197, 94) 0%, rgb(34, 197, 94) 70%, rgb(234, 179, 8) 85%, rgb(239, 68, 68) 100%)',
            opacity: 0.6,
          }}
        />

        {/* Volume Value Fill - Removed to show gradient spectrum */}

        {/* Fader Handle */}
        <div
          className="absolute left-0 right-0 h-3 -ml-1 -mr-1 bg-primary/70 border-2 border-primary rounded-sm shadow-lg cursor-grab active:cursor-grabbing backdrop-blur-sm"
          style={{
            bottom: `calc(${valuePercentage}% - 6px)`,
            width: 'calc(100% + 8px)',
          }}
        />

        {/* Scale Marks */}
        <div className="absolute inset-0 pointer-events-none">
          {[0.25, 0.5, 0.75].map((mark) => (
            <div
              key={mark}
              className="absolute left-0 right-0 h-px bg-background/50"
              style={{ bottom: `${mark * 100}%` }}
            />
          ))}
        </div>
      </div>

      {/* Level dB Display */}
      {showDb && (
        <div className="text-[10px] font-mono text-muted-foreground min-w-[32px] text-center">
          {levelDb === -Infinity ? '-∞' : `${levelDb.toFixed(0)}`}
        </div>
      )}
    </div>
  );
}
