import { computed, nextTick, ref, watch } from 'vue'
import { trim } from '../../../../libs/lodash'
import {
  CHANGE_EVENT,
  INPUT_EVENT,
  UPDATE_MODEL_EVENT,
} from '../../../../constants'
import {
  FormValidateIconsMap,
  debugWarn,
  isEmptyVariableInDefault,
} from '../../../../utils'
import { useToggle } from '../../../../hooks'
import { useFormDisabled, useFormItem } from '../../../form'

import type { SetupContext } from 'vue'
import type { FormItemValidateStates } from '../../../form'
import type { InputEmit, InputProps } from '../input'

export const useInput = (
  props: InputProps,
  emits: SetupContext<InputEmit>['emit']
) => {
  const { form, formItem } = useFormItem()

  // 输入框内容
  const inputText = ref<string>(
    String(isEmptyVariableInDefault(props.modelValue, ''))
  )
  watch(
    () => props.modelValue,
    (val) => {
      inputText.value = String(isEmptyVariableInDefault(val, ''))
      if (props.validateEvent) {
        formItem?.validate?.('change').catch((err) => {
          debugWarn(err)
        })
      }
    }
  )

  // 显示/隐藏密码状态
  const [passwordVisible, togglePasswordVisible] = useToggle(false)

  // 是否显示状态图标
  const needStatusIcon = computed(() =>
    isEmptyVariableInDefault(form?.statusIcon, false)
  )
  // 校验状态
  const validateState = computed(() =>
    isEmptyVariableInDefault<FormItemValidateStates>(
      formItem?.validateState,
      ''
    )
  )
  // 校验状态图标
  const validateIcon = computed(
    () => validateState.value && FormValidateIconsMap[validateState.value]
  )

  // 密码显示密码图标
  const passwordIcon = computed(() =>
    passwordVisible.value ? 'eye-hide' : 'eye'
  )

  // 是否显示图标
  const showIcon = computed(() => {
    let status = false
    if (validateState.value && needStatusIcon.value && validateIcon.value)
      status = true
    if (props.showPassword) status = true
    if (props.rightIcon) status = true
    if (props.clearable) status = true
    return status
  })

  // 输入框禁止事件
  const disabled = useFormDisabled(props.disabled)

  // 是否显示字数统计
  const showWordLimit = computed<boolean>(
    () =>
      props.type === 'textarea' && !!props?.maxlength && !!props?.showWordLimit
  )
  // 当前的字数
  const currentWordCount = computed<number>(() => {
    if (props.showWordLimit && props.type === 'textarea') {
      return inputText.value?.length || 0
    }
    return 0
  })

  // 内容输入触发事件
  const inputInputEvent = (event: any) => {
    const { value } = event.detail
    _updateInputText(value)
  }

  // 输入框聚焦事件
  const inputFocusEvent = (event: any) => {
    emits('focus', event)
  }

  // 输入框失去焦点事件
  const inputBlurEvent = (event: any) => {
    emits('blur', event)
    if (props.validateEvent) {
      // eslint-disable-next-line @typescript-eslint/no-empty-function
      formItem?.validate?.('blur').catch((err) => {
        debugWarn(err)
      })
    }
  }

  // 点击完成时触发事件
  const confirmEvent = (event: any) => {
    const { value } = event.detail
    emits('confirm', _formatInputText(value))
  }

  // 点击清除按钮
  const clearClickEvent = () => {
    if (disabled.value) return
    _updateInputText('')
    emits('clear')
  }

  // 更新输入框内容
  const _updateInputText = (value: string) => {
    value = props.trim ? trim(value) : value
    // inputText.value = value
    emits(UPDATE_MODEL_EVENT, _formatInputText(value))
    nextTick(() => {
      emits(INPUT_EVENT, _formatInputText(value))
      emits(CHANGE_EVENT, _formatInputText(value))
    })
  }

  // 输入框点击事件
  const inputClickEvent = () => {
    if (props.type === 'select') {
      emits('click')
    }
  }

  const _formatInputText = (value: string) => {
    if (value === '') return ''
    if (props.type === 'number' || props.type === 'digit')
      return Number.parseFloat(value)
    return value
  }

  return {
    inputText,
    needStatusIcon,
    validateState,
    validateIcon,
    passwordVisible,
    passwordIcon,
    showIcon,
    disabled,
    showWordLimit,
    currentWordCount,
    togglePasswordVisible,
    inputInputEvent,
    inputFocusEvent,
    inputBlurEvent,
    clearClickEvent,
    confirmEvent,
    inputClickEvent,
  }
}
