<template>
  <div
    class="hover-editor-container"
    @mouseenter="mouseenterHandler()"
    @mouseleave="mouseleaveHandler()"
  >
    <!-- <a-tooltip :content="modelValue"> -->
    <div
      class="hover-editor-content"
      :style="{
        flex: isModify ? '1 1 auto' : ''
      }"
    >
      <span v-if="!isModify" class="hover-editor-text">
        <div
          v-if="props.componentsType === ComponentsType.TEXTAREA"
          v-html="visibleName"
        ></div>
        <span v-else> {{ visibleName }}{{ props.inputSuffix }}</span>
      </span>
      <span
        v-else
        v-focus="true"
        :style="{
          width: [
            ComponentsType.STRINGINPUT,
            ComponentsType.NUMBERINPUT,
            ComponentsType.TEXTAREA,
            ComponentsType.SELECT
          ].includes(props.componentsType)
            ? '100%'
            : ''
        }"
      >
        <a-input
          v-if="props.componentsType === ComponentsType.STRINGINPUT"
          ref="inputRef"
          v-model="editingValue"
          :placeholder="placeholder"
          :allow-clear="!notAllowNull"
          @blur="blur"
          @change="update"
        />
        <a-input-number
          v-if="props.componentsType === ComponentsType.NUMBERINPUT"
          ref="inputRef"
          v-model="editingValue"
          style="width: 100"
          :precision="precision"
          :hide-button="!showNumberButton"
          :placeholder="placeholder"
          :allow-clear="!notAllowNull"
          @blur="blur"
          @change="update"
        >
          <template #suffix>
            {{ props.inputSuffix }}
          </template>
        </a-input-number>
        <a-date-picker
          v-if="props.componentsType === ComponentsType.DATEPICKER"
          ref="inputRef"
          v-model="editingValue"
          :default-popup-visible="true"
          :allow-clear="!notAllowNull"
          :placeholder="placeholder"
          @clear="clear"
          @popup-visible-change="update"
        ></a-date-picker>
        <a-select
          v-if="props.componentsType === ComponentsType.SELECT"
          ref="inputRef"
          v-model="editingValue"
          :default-popup-visible="true"
          :placeholder="placeholder"
          allow-search
          :multiple="multiple"
          :allow-clear="!notAllowNull"
          @clear="clear"
          @popup-visible-change="update"
        >
          <a-option
            v-for="item in options"
            :key="item.id"
            :value="item.id"
            :label="item.name"
          ></a-option>
        </a-select>
        <a-cascader
          v-if="props.componentsType === ComponentsType.CASCADER"
          ref="inputRef"
          v-model="editingValue"
          :default-popup-visible="true"
          :options="props.options"
          :field-names="{
            value: 'id',
            label: 'name'
          }"
          :allow-search="true"
          :allow-clear="!notAllowNull"
          :expand-child="visibleCascader"
          :placeholder="placeholder"
          :check-strictly="!unCheckStrictly"
          @clear="clear"
          @popup-visible-change="update()"
        />
        <a-textarea
          v-if="props.componentsType === ComponentsType.TEXTAREA"
          ref="inputRef"
          v-model="editingValue"
          :auto-size="false"
          :allow-clear="!notAllowNull"
          style="width: 100%"
          :placeholder="placeholder"
          @blur="blur"
          @change="update"
        />

        <!-- @blur="blur"
          @change="update" -->
      </span>
    </div>
    <div
      v-show="
        !isModify && (showEditor || ['', null, undefined].includes(visibleName))
      "
      :style="{
        marginLeft: ['', null, undefined].includes(visibleName) ? '5px' : '5px'
      }"
      class="editor-btn"
    >
      <icon-edit :size="14" @click="showEditorComponents()" />
    </div>
    <!-- </a-tooltip> -->
  </div>
</template>

<script lang="ts" setup>
import { ComponentsType } from '@/enums/api'
import { Message } from '@arco-design/web-vue'
import { watch, computed, ref, shallowRef } from 'vue'

interface DataItem {
  id: string | number
  name: string
  children?: DataItem[]
}

const props = defineProps<{
  modelValue?: any
  oldValue?: any
  disabled?: boolean
  placeholder?: string
  componentsType: ComponentsType
  isInputNumber?: boolean
  inputSuffix?: string
  options?: DataItem[]
  multiple?: boolean
  showNumberButton?: boolean
  unCheckStrictly?: boolean
  notAllowNull?: boolean
  precision?: number
}>()

const emits = defineEmits(['update:modelValue', 'modify'])
const editingValue = ref(
  props.componentsType === ComponentsType.TEXTAREA && props.modelValue
    ? props.modelValue.replace(/<br\/>/g, '\n')
    : props.modelValue
)

const isModify = ref(false)
const showEditor = ref(false)
const inputRef = shallowRef()
const visibleCascader = ref(false)

/**
 * 根据id查找name值，递归则获取路径拼接name
 * @param nodes
 * @param id
 * @param path
 */
function findPathById(
  nodes: DataItem[],
  id: string,
  path: string[] = []
): string | null {
  const result = nodes
    .map(node => {
      if (node.id === id) {
        return [...path, node.name].join(' / ')
      }
      if (node.children) {
        return findPathById(node.children, id, [...path, node.name])
      }
      return null
    })
    .find(p => p !== null)

  return result || null
}

const visibleName = computed(() => {
  if (
    props.componentsType === ComponentsType.STRINGINPUT ||
    props.componentsType === ComponentsType.NUMBERINPUT
  ) {
    return props.modelValue
  }

  if (
    props.componentsType === ComponentsType.SELECT ||
    props.componentsType === ComponentsType.CASCADER
  ) {
    const ids = props.modelValue
    if (props.multiple) {
      const arrName: string[] = []
      ids.map((item: string | number) => {
        const isFind = props.options?.find(p => p.id === item)
        if (isFind) {
          arrName.push(isFind.name)
        }
        return item
      })
      return arrName.join(',')
    }
    return findPathById(props.options!, ids)
  }
  return props.modelValue
})

// const foucs = () => {
//   if (!visibleCascader.value) {
//     visibleCascader.value = true
//   }
// }

const blur = () => {
  console.log(editingValue.value)
  isModify.value = false
}

// const popupVisibleChange = (visible: boolean) => {
//   if (!visible) {
//     isModify.value = false
//   }
// }

// 返显数据
const update = () => {
  const v =
    props.componentsType === ComponentsType.TEXTAREA
      ? editingValue.value.replace(/\n/g, '<br/>')
      : editingValue.value
  if (props.notAllowNull && ['', null, undefined].includes(v)) {
    Message.error('不允许为空')
    return
  }
  // const fValue =
  //   [ComponentsType.CASCADER, ComponentsType.SELECT].includes(
  //     props.componentsType
  //   ) && v === ''
  //     ? null
  //     : v
  if (props.modelValue !== v) {
    emits('update:modelValue', v)
    emits('modify', props.oldValue)
  }
  isModify.value = false
}

// 返显数据
const clear = () => {
  editingValue.value = null
}

watch(
  () => props.modelValue,
  () => {
    const v =
      props.componentsType === ComponentsType.TEXTAREA
        ? props.modelValue.replace(/<br\/>/g, '\n')
        : props.modelValue
    editingValue.value = v
  }
)

const showEditorComponents = () => {
  isModify.value = true
  showEditor.value = false
}

// 鼠标悬浮时显示编辑图标
const mouseenterHandler = () => {
  if (isModify.value) {
    return
  }
  showEditor.value = true
}

// 鼠标离开时隐藏编辑图标
const mouseleaveHandler = () => {
  showEditor.value = false
}
</script>

<style lang="less" scoped>
.hover-editor-container {
  width: 100%;
  display: flex;
  justify-content: start;
  align-items: center;
  position: relative;
  // height: 30px;
  .hover-editor-content {
    display: flex;
    align-items: center;
    position: relative;
    line-clamp: 1;
    max-width: calc(100% - 15px);
    // height: 30px;
    .hover-editor-text {
      position: relative;
      width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }
}
.editor-btn {
  display: flex;
  align-items: center;
  color: rgb(var(--primary-6));
  cursor: pointer;
}
</style>
