<template>
  <div class="treeSelectV2">
    <el-popover placement="bottom" :visible="visiable" @hide="visiable = false" :teleported="false">
      <template #reference>
        <el-input
          v-model="labelName"
          @input="onQueryFilter"
          @mouseenter="mouseHandler(1)"
          @mouseleave="mouseHandler(0)"
          @click="clickHander"
          :disabled="disabled"
          :placeholder="placeholder"
        >
          <template #suffix>
            <el-icon v-if="labelName && isHover">
              <CircleClose @click="clearHandler" />
            </el-icon>
            <el-icon :class="{ rotate: isRotate }" v-else>
              <ArrowDown />
            </el-icon>
          </template>
        </el-input>
      </template>
      <template #default>
        <el-tree-v2
          ref="treeRef"
          highlight-current
          style="width: 100%"
          :filter-method="filterMethod"
          :props="props"
          :data="data"
          :expand-on-click-node="false"
          @node-click="nodeClickHandle"
        >
          <template v-if="$slots.default" #default="{ node }">
            <slot :node="node"></slot>
          </template>
        </el-tree-v2>
      </template>
    </el-popover>
  </div>
</template>

<script setup lang="ts">
import { ElTreeV2 } from 'element-plus'
import { ArrowDown } from '@element-plus/icons-vue'

defineOptions({
  name: 'TreeSelectV2'
})
const $props = withDefaults(
  defineProps<
    Partial<{
      data: any[]
      modelValue: string | number
      props: any
      disabled: boolean
      expend: boolean
      filterMethod: any
      placeholder: string
      labelAll: boolean
    }>
  >(),
  {
    props: {
      label: 'label',
      value: 'value',
      children: 'children'
    },
    expend: true,
    labelAll: false,
    placeholder: '请选择'
  }
)
const $emit = defineEmits<{
  (e: 'update:modelValue', v: any): void
  (e: 'node-click', v: any, t?: string[]): void
}>()
const visiable = ref<boolean>(false)
const isRotate = ref<boolean>(false)
const labelName = ref<string>('')
const isHover = ref<boolean>(false)
const mouseHandler = (type: number) => {
  isHover.value = type === 1 ? true : false
}
const clickHander = () => {
  visiable.value = !visiable.value
}
const clearHandler = () => {
  nodeClickHandle({
    [$props.props['value'] ?? 'value']: '',
    [$props.props['label'] ?? 'label']: ''
  })
  onQueryFilter('')
}
watch(visiable, () => {
  isRotate.value = visiable.value ? true : false
})
const treeRef = ref<InstanceType<typeof ElTreeV2>>()
const onQueryFilter = (query: string) => {
  treeRef.value!.filter(query)
}
const getExpandedIds = (nodes?: any[]) => {
  if (nodes && nodes.length === 0) return []
  const ids: any[] = []
  function getIdByDfs(nodes) {
    for (let i = 0; i < nodes.length; i++) {
      const node = nodes[i]
      if (
        !node[$props.props['children'] ?? 'children'] ||
        node[$props.props['children'] ?? 'children'].length == 0
      )
        break
      ids.push(node[$props.props['value'] ?? 'value'])
      if (
        node[$props.props['children'] ?? 'children'] &&
        node[$props.props['children'] ?? 'children'].length > 0
      ) {
        getIdByDfs(node[$props.props['children'] ?? 'children'])
      }
    }
  }
  getIdByDfs(nodes)
  return ids
}
const setExpandedKeys = async () => {
  await nextTick()
  const allChooseIds = getExpandedIds($props.data)
  treeRef.value?.setExpandedKeys(allChooseIds)
}
const nodeClickHandle = (data) => {
  visiable.value = false
  $emit('update:modelValue', data[$props.props['value'] ?? 'value'])
  //@ts-ignore
  const item = treeRef.value?.getNode($props.modelValue)
  if (item && $props.labelAll) {
    const arrs = initLabelNameAll(item)
    labelName.value = arrs.join('-')
    $emit('node-click', data, arrs)
  } else {
    labelName.value = data[$props.props['label'] ?? 'label']
    $emit('node-click', data, [labelName.value])
  }
}

watchEffect(() => {
  //@ts-ignore
  const item = treeRef.value?.getNode($props.modelValue)
  if (item) {
    if ($props.labelAll) {
      const arrs = initLabelNameAll(item)
      labelName.value = arrs.join('-')
      return
    }
    labelName.value = item['label'] as string
  } else {
    labelName.value = ''
  }
  //默认全部展开
  if ($props.data && $props.expend) {
    setExpandedKeys()
  }
})
const initLabelNameAll = (item): string[] => {
  const arrs: string[] = []
  const recursion = (item) => {
    if (item) {
      arrs.push(item.label)
      if (item.parent) {
        recursion(item.parent)
      }
    }
  }
  recursion(item)
  arrs.reverse()
  return arrs
}
defineExpose({
  labelName
})
</script>

<style lang="scss" scoped>
.treeSelectV2 {
  position: relative;
  :deep(.el-popper) {
    width: 100% !important;
    left: 0px !important;
    right: 0px !important;
  }
  :deep(.el-input__suffix) {
    .el-icon {
      color: var(--el-select-input-color);
      font-size: var(--el-select-input-font-size);
      transition: transform var(--el-transition-duration);
      transform: rotateZ(0);
      cursor: pointer;
    }
  }
  :deep(.is-focus) {
    .el-input__suffix .el-icon {
      cursor: pointer;
      transform: rotateZ(0);
    }
  }
  .rotate {
    transform: rotateZ(-180deg) !important;
  }
  :deep(.el-tree-node__content) {
    .is-leaf {
      flex-shrink: 0;
    }
  }
  // :deep(.el-input__wrapper) {
  //   padding: 0px;
  // }
  :deep(.el-input.is-disabled .el-input__wrapper) {
    background: none !important;
    box-shadow: none !important;
  }
  :deep(.el-input.is-disabled .el-input__inner) {
    color: #333 !important;
    -webkit-text-fill-color: #333 !important;
  }
}
</style>
