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

interface Props {
  value: string // "HH:MM" 24-hour format
  onChange: (value: string) => void
  disabled?: boolean
}

const SIZE = 240
const CENTER = SIZE / 2
const CLOCK_RADIUS = 108
const NUM_RADIUS = 82
const HAND_RADIUS = 74
const TIP_RADIUS = 16

function polarToXY(angleDeg: number, radius: number) {
  const rad = ((angleDeg - 90) * Math.PI) / 180
  return {
    x: CENTER + radius * Math.cos(rad),
    y: CENTER + radius * Math.sin(rad),
  }
}

function parseValue(v: string): { h: number; m: number } {
  const [h, m] = v.split(':').map(Number)
  return { h: isNaN(h) ? 8 : h, m: isNaN(m) ? 0 : m }
}

export default function ClockTimePicker({ value, onChange, disabled }: Props) {
  const { h: initH, m: initM } = parseValue(value)

  const [mode, setMode] = useState<'hours' | 'minutes'>('hours')
  const [hour24, setHour24] = useState(initH)
  const [minute, setMinute] = useState(initM)
  const svgRef = useRef<SVGSVGElement>(null)
  const isDragging = useRef(false)
  // Keep mutable refs for use inside native event listeners
  const modeRef = useRef(mode)
  const isPMRef = useRef(initH >= 12)
  const hour24Ref = useRef(initH)
  const minuteRef = useRef(initM)

  // Keep refs in sync with state
  useEffect(() => { modeRef.current = mode }, [mode])
  useEffect(() => { isPMRef.current = hour24 >= 12 }, [hour24])
  useEffect(() => { hour24Ref.current = hour24 }, [hour24])
  useEffect(() => { minuteRef.current = minute }, [minute])

  // Sync when value prop changes externally
  useEffect(() => {
    const { h, m } = parseValue(value)
    setHour24(h)
    setMinute(m)
  }, [value])

  const isPM = hour24 >= 12
  const hour12 = hour24 === 0 ? 12 : hour24 > 12 ? hour24 - 12 : hour24

  const emit = useCallback(
    (h24: number, m: number) => {
      onChange(`${h24.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}`)
    },
    [onChange]
  )

  const handleAmPm = (pm: boolean) => {
    if (disabled) return
    let newH = hour24
    if (pm && hour24 < 12) newH = hour24 + 12
    else if (!pm && hour24 >= 12) newH = hour24 - 12
    setHour24(newH)
    emit(newH, minute)
  }

  const applyAngle = useCallback(
    (angle: number, currentMode: 'hours' | 'minutes') => {
      if (currentMode === 'hours') {
        const h12 = Math.round(angle / 30) % 12 || 12
        const pm = isPMRef.current
        const newH24 = pm ? (h12 === 12 ? 12 : h12 + 12) : (h12 === 12 ? 0 : h12)
        setHour24(newH24)
        emit(newH24, minuteRef.current)
      } else {
        const m = Math.round(angle / 6) % 60
        setMinute(m)
        emit(hour24Ref.current, m)
      }
    },
    [emit]
  )

  const getSVGAngle = (clientX: number, clientY: number): number => {
    if (!svgRef.current) return 0
    const rect = svgRef.current.getBoundingClientRect()
    const scale = rect.width / SIZE
    const x = clientX - rect.left - CENTER * scale
    const y = clientY - rect.top - CENTER * scale
    return ((Math.atan2(y, x) * 180) / Math.PI + 90 + 360) % 360
  }

  // Mouse handlers (mouse events don't need passive:false)
  const handleMouseDown = (e: React.MouseEvent<SVGSVGElement>) => {
    if (disabled) return
    isDragging.current = true
    applyAngle(getSVGAngle(e.clientX, e.clientY), modeRef.current)
  }
  const handleMouseMove = (e: React.MouseEvent<SVGSVGElement>) => {
    if (!isDragging.current || disabled) return
    applyAngle(getSVGAngle(e.clientX, e.clientY), modeRef.current)
  }
  const handleMouseUp = (e: React.MouseEvent<SVGSVGElement>) => {
    if (!isDragging.current) return
    isDragging.current = false
    applyAngle(getSVGAngle(e.clientX, e.clientY), modeRef.current)
    if (modeRef.current === 'hours') setTimeout(() => setMode('minutes'), 120)
  }
  const handleMouseLeave = () => { isDragging.current = false }

  // Attach non-passive touch listeners imperatively to avoid the passive warning
  useEffect(() => {
    const svg = svgRef.current
    if (!svg) return

    const onTouchStart = (e: TouchEvent) => {
      if (disabled) return
      e.preventDefault()
      isDragging.current = true
      const t = e.touches[0]
      applyAngle(getSVGAngle(t.clientX, t.clientY), modeRef.current)
    }

    const onTouchMove = (e: TouchEvent) => {
      if (!isDragging.current || disabled) return
      e.preventDefault()
      const t = e.touches[0]
      applyAngle(getSVGAngle(t.clientX, t.clientY), modeRef.current)
    }

    const onTouchEnd = (e: TouchEvent) => {
      if (!isDragging.current) return
      e.preventDefault()
      isDragging.current = false
      const t = e.changedTouches[0]
      applyAngle(getSVGAngle(t.clientX, t.clientY), modeRef.current)
      if (modeRef.current === 'hours') setTimeout(() => setMode('minutes'), 120)
    }

    svg.addEventListener('touchstart', onTouchStart, { passive: false })
    svg.addEventListener('touchmove', onTouchMove, { passive: false })
    svg.addEventListener('touchend', onTouchEnd, { passive: false })

    return () => {
      svg.removeEventListener('touchstart', onTouchStart)
      svg.removeEventListener('touchmove', onTouchMove)
      svg.removeEventListener('touchend', onTouchEnd)
    }
  }, [applyAngle, disabled])

  const handAngle = mode === 'hours' ? (hour12 / 12) * 360 : (minute / 60) * 360
  const handTip = polarToXY(handAngle, HAND_RADIUS)
  const displayH = hour12.toString()
  const displayM = minute.toString().padStart(2, '0')
  const selectedNum = mode === 'hours' ? hour12 : minute

  const hourPositions = Array.from({ length: 12 }, (_, i) => {
    const h = i + 1
    return { h, ...polarToXY((h / 12) * 360, NUM_RADIUS) }
  })

  const minutePositions = Array.from({ length: 12 }, (_, i) => {
    const m = i * 5
    return { m, ...polarToXY((m / 60) * 360, NUM_RADIUS) }
  })

  return (
    <div className="clock-picker">
      {/* Time display */}
      <div className="clock-picker__display">
        <button
          type="button"
          className={`clock-picker__seg${mode === 'hours' ? ' clock-picker__seg--active' : ''}`}
          onClick={() => !disabled && setMode('hours')}
        >
          {displayH}
        </button>
        <span className="clock-picker__colon">:</span>
        <button
          type="button"
          className={`clock-picker__seg${mode === 'minutes' ? ' clock-picker__seg--active' : ''}`}
          onClick={() => !disabled && setMode('minutes')}
        >
          {displayM}
        </button>
        <div className="clock-picker__ampm">
          <button
            type="button"
            className={`clock-picker__ampm-btn${!isPM ? ' clock-picker__ampm-btn--active' : ''}`}
            onClick={() => handleAmPm(false)}
            disabled={disabled}
          >AM</button>
          <button
            type="button"
            className={`clock-picker__ampm-btn${isPM ? ' clock-picker__ampm-btn--active' : ''}`}
            onClick={() => handleAmPm(true)}
            disabled={disabled}
          >PM</button>
        </div>
      </div>

      {/* Clock face */}
      <svg
        ref={svgRef}
        viewBox={`0 0 ${SIZE} ${SIZE}`}
        className="clock-picker__face"
        onMouseDown={handleMouseDown}
        onMouseMove={handleMouseMove}
        onMouseUp={handleMouseUp}
        onMouseLeave={handleMouseLeave}
        style={{ cursor: disabled ? 'default' : 'pointer', touchAction: 'none', userSelect: 'none' }}
      >
        <circle cx={CENTER} cy={CENTER} r={CLOCK_RADIUS} className="clock-picker__bg" />

        {/* Shaded sector */}
        {(() => {
          const start = polarToXY(0, HAND_RADIUS)
          const end = polarToXY(handAngle, HAND_RADIUS)
          const large = handAngle > 180 ? 1 : 0
          return (
            <path
              d={`M ${CENTER} ${CENTER} L ${start.x} ${start.y} A ${HAND_RADIUS} ${HAND_RADIUS} 0 ${large} 1 ${end.x} ${end.y} Z`}
              className="clock-picker__sector"
            />
          )
        })()}

        <line x1={CENTER} y1={CENTER} x2={handTip.x} y2={handTip.y} className="clock-picker__hand" />
        <circle cx={CENTER} cy={CENTER} r={4} className="clock-picker__center-dot" />
        <circle cx={handTip.x} cy={handTip.y} r={TIP_RADIUS} className="clock-picker__hand-tip" />

        {mode === 'hours' && hourPositions.map(({ h, x, y }) => (
          h === selectedNum ? null :
          <text key={h} x={x} y={y} textAnchor="middle" dominantBaseline="central"
            className="clock-picker__num"
          >{h}</text>
        ))}

        {mode === 'minutes' && minutePositions.map(({ m, x, y }) => (
          m === selectedNum ? null :
          <text key={m} x={x} y={y} textAnchor="middle" dominantBaseline="central"
            className="clock-picker__num"
          >{m.toString().padStart(2, '0')}</text>
        ))}

        {/* Selected number rendered at hand tip so it sits centered in the green circle */}
        <text x={handTip.x} y={handTip.y} textAnchor="middle" dominantBaseline="central"
          className="clock-picker__num clock-picker__num--selected"
        >{mode === 'hours' ? selectedNum : selectedNum.toString().padStart(2, '0')}</text>

        {mode === 'minutes' && Array.from({ length: 60 }, (_, i) => {
          if (i % 5 === 0) return null
          const angle = (i / 60) * 360
          const inner = polarToXY(angle, CLOCK_RADIUS - 10)
          const outer = polarToXY(angle, CLOCK_RADIUS - 4)
          return <line key={i} x1={inner.x} y1={inner.y} x2={outer.x} y2={outer.y} className="clock-picker__tick" />
        })}
      </svg>

      {/* Mode pills */}
      <div className="clock-picker__modes">
        <button type="button"
          className={`clock-picker__mode-btn${mode === 'hours' ? ' clock-picker__mode-btn--active' : ''}`}
          onClick={() => !disabled && setMode('hours')}
        >Hours</button>
        <button type="button"
          className={`clock-picker__mode-btn${mode === 'minutes' ? ' clock-picker__mode-btn--active' : ''}`}
          onClick={() => !disabled && setMode('minutes')}
        >Minutes</button>
      </div>
    </div>
  )
}
