import { useCallback, useState } from 'react'

import type { CounterMessageSetter, TextLengthChangeHandler } from '../../types'

type Props = {
  minLength?: number
  maxLength?: number
  minLengthMessage?: CounterMessageSetter
  maxLengthMessage?: CounterMessageSetter
}

const CLOSE_TO_LIMIT = 10
const defaultMinLengthMessage: CounterMessageSetter = (
  minLength,
  currLength,
  isError
) => {
  if (isError) {
    return `${minLength} characters required, current count is ${currLength}`
  }

  return `${currLength} characters entered`
}

const defaultMaxLengthMessage: CounterMessageSetter = (
  maxLength,
  currLength,
  isError
) => {
  if (isError) {
    return `${currLength - maxLength} over the limit`
  }

  return `${maxLength - currLength} characters left`
}

const getInitialCounterMessage = ({
  minLength,
  maxLength,
  minLengthMessage = defaultMinLengthMessage,
  maxLengthMessage = defaultMaxLengthMessage,
}: Props) => {
  if (minLength) {
    return minLengthMessage(minLength, 0, true)
  }

  if (maxLength) {
    return maxLengthMessage(maxLength, 0, false)
  }

  return ''
}

const useCounter = ({
  minLength,
  maxLength,
  minLengthMessage = defaultMinLengthMessage,
  maxLengthMessage = defaultMaxLengthMessage,
}: Props) => {
  const [message, setMesssage] = useState(() =>
    getInitialCounterMessage({
      minLength,
      maxLength,
      minLengthMessage,
      maxLengthMessage,
    })
  )
  const [isError, setIsError] = useState(!!minLength)

  const handleCounterMessage: TextLengthChangeHandler = useCallback(
    currLength => {
      if (minLength) {
        if (currLength < minLength) {
          setMesssage(minLengthMessage(minLength, currLength, true))
          setIsError(true)

          return
        } else if (!maxLength) {
          setMesssage(minLengthMessage(minLength, currLength, false))
          setIsError(false)

          return
        }
      }

      if (maxLength) {
        if (
          maxLength - currLength <= CLOSE_TO_LIMIT &&
          maxLength - currLength >= 0
        ) {
          setMesssage(maxLengthMessage(maxLength, currLength, false))
          setIsError(true)

          return
        }

        if (currLength < maxLength) {
          setMesssage(maxLengthMessage(maxLength, currLength, false))
          setIsError(false)

          return
        }

        setMesssage(maxLengthMessage(maxLength, currLength, true))
        setIsError(true)
      }
    },
    [minLength, maxLength, minLengthMessage, maxLengthMessage]
  )

  return {
    counterMessage: message,
    counterError: isError,
    handleCounterMessage,
  }
}

export default useCounter
