import { useEffect, useMemo, useState } from 'react'

import './DurationPicker.scss'

type DurationValue = {
  days: number
  hours: number
  minutes: number
  totalMinutes: number
}

type DurationPickerValue = Pick<DurationValue, 'days' | 'hours' | 'minutes'>
type DurationPickerDraftValue = Record<keyof DurationPickerValue, number | ''>

type DurationPickerProps = {
  value?: DurationPickerValue
  initialDays?: number
  initialHours?: number
  initialMinutes?: number
  isEditing?: boolean
  disabled?: boolean
  onChange?: (value: DurationValue) => void
  className?: string
}

function getTotalMinutes(value: DurationPickerValue) {
  return value.days * 24 * 60 + value.hours * 60 + value.minutes
}

export function DurationPicker({
  value,
  initialDays = 0,
  initialHours = 2,
  initialMinutes = 30,
  isEditing = false,
  disabled,
  onChange,
  className = '',
}: DurationPickerProps) {
  const currentValue = useMemo<DurationPickerValue>(
    () => ({
      days: value?.days ?? initialDays,
      hours: value?.hours ?? initialHours,
      minutes: value?.minutes ?? initialMinutes,
    }),
    [
      initialDays,
      initialHours,
      initialMinutes,
      value?.days,
      value?.hours,
      value?.minutes,
    ],
  )
  const [days, setDays] = useState<number | ''>(currentValue.days)
  const [hours, setHours] = useState<number | ''>(currentValue.hours)
  const [minutes, setMinutes] = useState<number | ''>(currentValue.minutes)
  const isEditable = isEditing && !disabled

  const rootClassName = [
    'duration-picker',
    isEditable && 'duration-picker--open',
    !isEditable && 'is-disabled',
    className,
  ]
    .filter(Boolean)
    .join(' ')

  useEffect(() => {
    if (isEditable) return

    setDays(currentValue.days)
    setHours(currentValue.hours)
    setMinutes(currentValue.minutes)
  }, [currentValue, isEditable])

  function normalizeNumber(value: string, max: number): number | '' {
    const digits = value.replace(/\D/g, '')

    if (!digits) {
      return ''
    }

    return Math.min(Number(digits), max)
  }

  function emitChange(value: DurationPickerDraftValue) {
    const nextValue = {
      days: Number(value.days) || 0,
      hours: Number(value.hours) || 0,
      minutes: Number(value.minutes) || 0,
    }

    onChange?.({
      ...nextValue,
      totalMinutes: getTotalMinutes(nextValue),
    })
  }

  return (
    <div
      className={rootClassName}
      role="group"
      aria-label="Время до блокировки без сети"
      aria-disabled={!isEditable}
    >
      <label className="duration-picker__segment duration-picker__segment--days">
        <input
          className="duration-picker__input"
          value={days}
          inputMode="numeric"
          aria-label="Дни"
          disabled={!isEditable}
          onChange={(event) => {
            const nextDays = normalizeNumber(event.target.value, 365)

            setDays(nextDays)
            emitChange({
              days: nextDays,
              hours,
              minutes,
            })
          }}
          onFocus={(event) => {
            event.target.select()
          }}
        />

        <span className="duration-picker__unit">д</span>
      </label>

      <label className="duration-picker__segment duration-picker__segment--hours">
        <input
          className="duration-picker__input"
          value={hours}
          inputMode="numeric"
          aria-label="Часы"
          disabled={!isEditable}
          onChange={(event) => {
            const nextHours = normalizeNumber(event.target.value, 23)

            setHours(nextHours)
            emitChange({
              days,
              hours: nextHours,
              minutes,
            })
          }}
          onFocus={(event) => {
            event.target.select()
          }}
        />

        <span className="duration-picker__unit">ч</span>
      </label>

      <label className="duration-picker__segment duration-picker__segment--minutes">
        <input
          className="duration-picker__input"
          value={minutes}
          inputMode="numeric"
          aria-label="Минуты"
          disabled={!isEditable}
          onChange={(event) => {
            const nextMinutes = normalizeNumber(event.target.value, 59)

            setMinutes(nextMinutes)
            emitChange({
              days,
              hours,
              minutes: nextMinutes,
            })
          }}
          onFocus={(event) => {
            event.target.select()
          }}
        />

        <span className="duration-picker__unit">мин</span>
      </label>
    </div>
  )
}
