'use client';

import { useRef, useCallback, useState } from 'react';

const SIZE = 32;
const RADIUS = 12;
const START_ANGLE = 225;
const END_ANGLE = -45;
const RANGE = 270;

function polarToCart(cx: number, cy: number, r: number, deg: number) {
  const rad = (deg - 90) * Math.PI / 180;
  return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) };
}

function describeArc(cx: number, cy: number, r: number, startDeg: number, endDeg: number) {
  const start = polarToCart(cx, cy, r, endDeg);
  const end = polarToCart(cx, cy, r, startDeg);
  const large = endDeg - startDeg <= 180 ? '0' : '1';
  return `M ${start.x} ${start.y} A ${r} ${r} 0 ${large} 0 ${end.x} ${end.y}`;
}

interface KnobProps {
  value: number;
  min: number;
  max: number;
  onChange: (v: number) => void;
  color?: string;
  modulated?: boolean;
  liveValue?: number;
}

export function Knob({ value, min, max, onChange, color = 'var(--accent, #6366f1)', modulated = false, liveValue }: KnobProps) {
  const ref = useRef<SVGSVGElement>(null);
  const dragRef = useRef<{ startY: number; startValue: number } | null>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const [editing, setEditing] = useState(false);
  const [editText, setEditText] = useState('');

  const displayNum = liveValue !== undefined ? liveValue : value;
  const clampedDisplay = Math.max(min, Math.min(max, displayNum));
  const norm = Math.max(0, Math.min(1, (clampedDisplay - min) / (max - min)));
  const angleDeg = START_ANGLE - norm * RANGE;

  const cx = SIZE / 2, cy = SIZE / 2;
  const trackPath = describeArc(cx, cy, RADIUS, END_ANGLE, START_ANGLE);
  const fillAngle = START_ANGLE - norm * RANGE;
  const fillPath = norm > 0.001 ? describeArc(cx, cy, RADIUS, fillAngle, START_ANGLE) : '';
  const dotPos = polarToCart(cx, cy, RADIUS - 4, angleDeg);

  const baseNorm = Math.max(0, Math.min(1, (value - min) / (max - min)));
  const baseAngle = START_ANGLE - baseNorm * RANGE;
  const baseDotPos = polarToCart(cx, cy, RADIUS - 4, baseAngle);

  const handlePointerDown = useCallback((e: React.PointerEvent) => {
    if (editing) return;
    e.preventDefault(); e.stopPropagation();
    dragRef.current = { startY: e.clientY, startValue: value };
    const handleMove = (me: PointerEvent) => {
      if (!dragRef.current) return;
      const dy = dragRef.current.startY - me.clientY;
      const sensitivity = (max - min) / 200;
      let newVal = dragRef.current.startValue + dy * sensitivity;
      newVal = Math.max(min, Math.min(max, newVal));
      if (max - min > 10 && Number.isInteger(min) && Number.isInteger(max)) {
        newVal = Math.round(newVal);
      }
      onChange(newVal);
    };
    const handleUp = () => {
      window.removeEventListener('pointermove', handleMove);
      window.removeEventListener('pointerup', handleUp);
      dragRef.current = null;
    };
    window.addEventListener('pointermove', handleMove);
    window.addEventListener('pointerup', handleUp);
  }, [value, min, max, onChange, editing]);

  const handleWheel = useCallback((e: React.WheelEvent) => {
    if (editing) return;
    e.preventDefault(); e.stopPropagation();
    const step = (max - min) / 100;
    const newVal = Math.max(min, Math.min(max, value - Math.sign(e.deltaY) * step));
    onChange(newVal);
  }, [value, min, max, onChange, editing]);

  const handleDoubleClick = useCallback((e: React.MouseEvent) => {
    e.preventDefault(); e.stopPropagation();
    setEditText(String(value));
    setEditing(true);
    setTimeout(() => inputRef.current?.focus(), 0);
  }, [value]);

  const commitEdit = useCallback(() => {
    const parsed = parseFloat(editText);
    if (!isNaN(parsed)) {
      onChange(Math.max(min, Math.min(max, parsed)));
    }
    setEditing(false);
  }, [editText, min, max, onChange]);

  if (editing) {
    return (
      <div className="knob-container" onWheel={(e) => e.stopPropagation()} style={{ width: SIZE, height: SIZE, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <input
          ref={inputRef}
          type="text"
          value={editText}
          onChange={(e) => setEditText(e.target.value)}
          onKeyDown={(e) => { e.stopPropagation(); if (e.key === 'Enter') commitEdit(); if (e.key === 'Escape') setEditing(false); }}
          onBlur={commitEdit}
          onPointerDown={(e) => e.stopPropagation()}
          style={{
            width: 48, height: 22, background: 'oklch(0.145 0 0)', border: '1px solid var(--accent, #6366f1)',
            borderRadius: 3, color: 'var(--accent, #6366f1)', fontSize: 10, textAlign: 'center',
            fontFamily: "'JetBrains Mono', monospace", outline: 'none',
          }}
        />
      </div>
    );
  }

  return (
    <div style={{ width: SIZE, height: SIZE, position: 'relative', flexShrink: 0 }} onWheel={handleWheel} onDoubleClick={handleDoubleClick}>
      <svg viewBox={`0 0 ${SIZE} ${SIZE}`} style={{ width: SIZE, height: SIZE, cursor: 'pointer' }}
        onPointerDown={handlePointerDown} ref={ref}>
        {/* Modulation glow ring */}
        {modulated && (
          <circle cx={cx} cy={cy} r={RADIUS + 1} fill="none" stroke={color} strokeWidth="1" strokeDasharray="3 2" opacity="0.7">
            <animateTransform attributeName="transform" type="rotate" from={`0 ${cx} ${cy}`} to={`360 ${cx} ${cy}`} dur="4s" repeatCount="indefinite" />
          </circle>
        )}
        {/* Track */}
        <path d={trackPath} fill="none" stroke="#333" strokeWidth="3" strokeLinecap="round" />
        {/* Fill */}
        {fillPath && <path d={fillPath} fill="none" stroke={color} strokeWidth="3" strokeLinecap="round" />}
        {/* Ghost dot at base value when modulated */}
        {liveValue !== undefined && (
          <circle cx={baseDotPos.x} cy={baseDotPos.y} r={1.5} fill="#fff" opacity="0.3" />
        )}
        {/* Current value dot */}
        <circle cx={dotPos.x} cy={dotPos.y} r={2} fill="#fff" />
      </svg>
    </div>
  );
}
