<template>
  <el-input-number
    :model-value="displayValue"
    controls-position="right"
    v-bind="$attrs"
    @focus="onFocus"
    @blur="onBlur"
    @change="onChange"
  >
    <template #prefix>
      <slot name="prefix"></slot>
    </template>
    <template #suffix>
      <slot name="suffix"></slot>
    </template>
  </el-input-number>
</template>

<script setup lang="ts">
import { computed, useAttrs, ref } from 'vue'
import { isNumber } from 'lodash-es'

const modelValue = defineModel<number>('modelValue')
const props = withDefaults(
  defineProps<{
    allowDecimal?: boolean
  }>(),
  {
    allowDecimal: false
  }
)

defineOptions({
  name: 'InputNumber'
})

const attrs = useAttrs()
const beforeVal = ref<number>()
const getValue = (value?: number | null) => {
  if (value === undefined || value === null) {
    return value
  }
  return props.allowDecimal ? value : Math.trunc(value)
}
const displayValue = computed(() => getValue(modelValue.value))

const onFocus = () => {
  beforeVal.value = modelValue.value
}

const onBlur = () => {
  if (modelValue.value === undefined || modelValue.value === null) {
    // 输入框为空时，恢复之前值
    modelValue.value = beforeVal.value
  }
}
const onChange = (value?: number) => {
  // 处理数字边界问题
  if (value === undefined || value === null) {
    return
  }
  const normalizedValue = getValue(value)
  const { min, max } = attrs
  if (isNumber(min) && normalizedValue! < min) {
    modelValue.value = min as number
  } else if (isNumber(max) && normalizedValue! > max) {
    modelValue.value = max as number
  } else {
    modelValue.value = normalizedValue as number
  }
}
</script>

<style scoped></style>
