import { useEffect, useMemo, useRef } from "react"

const OTP_LENGTH = 5

const normalizeDigits = (value: string) =>
  value
    .replace(/[۰-۹]/g, (digit) => String("۰۱۲۳۴۵۶۷۸۹".indexOf(digit)))
    .replace(/[٠-٩]/g, (digit) => String("٠١٢٣٤٥٦٧٨٩".indexOf(digit)))

const sanitizeOtp = (value: string) => normalizeDigits(value).replace(/\D/g, "").slice(0, OTP_LENGTH)

export function AuthOtpInput({
  id,
  value,
  disabled,
  onChange,
  onComplete,
}: {
  id: string
  value: string
  disabled?: boolean
  onChange: (value: string) => void
  onComplete?: (value: string) => void
}) {
  const inputRefs = useRef<Array<HTMLInputElement | null>>([])
  const lastCompletedValueRef = useRef("")
  const normalizedValue = useMemo(() => sanitizeOtp(value), [value])
  const digits = useMemo(
    () => Array.from({ length: OTP_LENGTH }, (_, index) => normalizedValue[index] ?? ""),
    [normalizedValue],
  )

  useEffect(() => {
    if (normalizedValue.length !== OTP_LENGTH) {
      lastCompletedValueRef.current = ""
      return
    }

    if (normalizedValue !== lastCompletedValueRef.current) {
      lastCompletedValueRef.current = normalizedValue
      onComplete?.(normalizedValue)
    }
  }, [normalizedValue, onComplete])

  const focusIndex = (index: number) => {
    inputRefs.current[index]?.focus()
    inputRefs.current[index]?.select()
  }

  const handleSlotChange = (index: number, nextRawValue: string) => {
    const nextValue = sanitizeOtp(nextRawValue)
    if (!nextValue) {
      const updated = digits.slice()
      updated[index] = ""
      onChange(updated.join(""))
      return
    }

    if (nextValue.length > 1) {
      onChange(nextValue)
      const focusTarget = Math.min(nextValue.length, OTP_LENGTH - 1)
      focusIndex(focusTarget)
      return
    }

    const updated = digits.slice()
    updated[index] = nextValue
    const combined = updated.join("")
    onChange(combined)

    if (index < OTP_LENGTH - 1) {
      focusIndex(index + 1)
    }
  }

  const handleKeyDown = (index: number, event: React.KeyboardEvent<HTMLInputElement>) => {
    if (event.key === "Backspace" && !digits[index] && index > 0) {
      const updated = digits.slice()
      updated[index - 1] = ""
      onChange(updated.join(""))
      focusIndex(index - 1)
      event.preventDefault()
      return
    }

    if (event.key === "ArrowLeft" && index > 0) {
      focusIndex(index - 1)
      event.preventDefault()
      return
    }

    if (event.key === "ArrowRight" && index < OTP_LENGTH - 1) {
      focusIndex(index + 1)
      event.preventDefault()
    }
  }

  const handlePaste = (event: React.ClipboardEvent<HTMLInputElement>) => {
    event.preventDefault()
    const pasted = sanitizeOtp(event.clipboardData.getData("text"))
    if (!pasted) {
      return
    }
    onChange(pasted)
    focusIndex(Math.min(pasted.length, OTP_LENGTH - 1))
  }

  return (
    <div className="flex items-center justify-center gap-2 sm:gap-3" dir="ltr">
      {digits.map((digit, index) => (
        <input
          key={`${id}-${index}`}
          ref={(element) => {
            inputRefs.current[index] = element
          }}
          id={index === 0 ? id : undefined}
          type="text"
          inputMode="numeric"
          autoComplete="one-time-code"
          pattern="[0-9]*"
          maxLength={OTP_LENGTH}
          disabled={disabled}
          value={digit}
          onChange={(event) => handleSlotChange(index, event.target.value)}
          onKeyDown={(event) => handleKeyDown(index, event)}
          onPaste={handlePaste}
          className="h-12 w-12 rounded-2xl border border-slate-200 bg-white text-center text-lg font-semibold tracking-[0.18em] text-slate-900 outline-none transition focus:border-sky-500 focus:ring-2 focus:ring-sky-200 dark:border-slate-700 dark:bg-slate-900 dark:text-white dark:focus:ring-sky-500/20 sm:h-14 sm:w-14"
        />
      ))}
    </div>
  )
}
