import { useMemo, useRef, useLayoutEffect, type InputHTMLAttributes, type FormEvent } from 'react'

const PREFIX = '+7 7'
const PREFIX_LEN = 4

function rawToUserDigits(raw: string): string {
  let d = raw.replace(/\D/g, '')
  if (d[0] === '8') d = d.slice(1)
  if (d[0] === '7') d = d.slice(1)
  if (d[0] === '7') d = d.slice(1)
  return d.slice(0, 9)
}

function userDigitsToDisplay(d: string): string {
  if (d.length === 0) return PREFIX
  if (d.length <= 2) return `${PREFIX}${d}`
  if (d.length <= 5) return `${PREFIX}${d.slice(0, 2)} ${d.slice(2)}`
  if (d.length <= 7) return `${PREFIX}${d.slice(0, 2)} ${d.slice(2, 5)} ${d.slice(5)}`
  return `${PREFIX}${d.slice(0, 2)} ${d.slice(2, 5)} ${d.slice(5, 7)} ${d.slice(7, 9)}`
}

function digitsBeforeCursor(value: string, cursor: number): number {
  let count = 0
  for (let i = 0; i < cursor && i < value.length; i++) {
    if (/\d/.test(value[i])) count++
  }
  return count
}

function cursorAfterNthDigit(value: string, n: number): number {
  if (n <= 0) return 0
  let count = 0
  for (let i = 0; i < value.length; i++) {
    if (/\d/.test(value[i])) {
      count++
      if (count === n) return i + 1
    }
  }
  return value.length
}

interface PhoneInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
  value: string
  onChange: (value: string) => void
}

/** PhoneInput для public — см. food-market.web/components/PhoneInput.tsx. */
export function PhoneInput({ value, onChange, className, disabled, ...rest }: PhoneInputProps) {
  const ref = useRef<HTMLInputElement>(null)
  const userDigits = useMemo(() => rawToUserDigits(value), [value])
  const display = userDigitsToDisplay(userDigits)
  const pendingDigitCountRef = useRef<number | null>(null)

  useLayoutEffect(() => {
    const n = pendingDigitCountRef.current
    pendingDigitCountRef.current = null
    if (n === null) return
    const el = ref.current
    if (!el) return
    const pos = Math.max(PREFIX_LEN, cursorAfterNthDigit(display, n))
    el.setSelectionRange(pos, pos)
  }, [display])

  const handleBeforeInput = (e: FormEvent<HTMLInputElement>) => {
    const native = e.nativeEvent as InputEvent
    if (native.data && /\D/.test(native.data)) {
      e.preventDefault()
    }
  }

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const cursorPos = e.target.selectionStart ?? e.target.value.length
    pendingDigitCountRef.current = digitsBeforeCursor(e.target.value, cursorPos)
    const newDigits = rawToUserDigits(e.target.value)
    onChange(newDigits.length > 0 ? `+77${newDigits}` : '')
  }

  const guardCursor = (el: HTMLInputElement) => {
    const start = el.selectionStart ?? 0
    const end = el.selectionEnd ?? 0
    if (start < PREFIX_LEN || end < PREFIX_LEN) {
      el.setSelectionRange(Math.max(PREFIX_LEN, start), Math.max(PREFIX_LEN, end))
    }
  }

  const handleSelect = (e: React.SyntheticEvent<HTMLInputElement>) => guardCursor(e.currentTarget)
  const handleFocus = () => {
    const el = ref.current
    if (!el) return
    requestAnimationFrame(() => guardCursor(el))
  }

  return (
    <input
      ref={ref}
      type="tel"
      inputMode="tel"
      autoComplete="tel"
      value={display}
      onBeforeInput={handleBeforeInput}
      onChange={handleChange}
      onSelect={handleSelect}
      onFocus={handleFocus}
      disabled={disabled}
      placeholder={PREFIX}
      className={className}
      {...rest}
    />
  )
}
