<template>
  <div class="select-tree">
    <div class="left">
      <el-input
        v-model="queryStr"
        :style="{ width: '300px', height: '30px' }"
        placeholder="请输入搜索内容"
        :prefix-icon="Search"
        @input="onSearch"
        clearable
      />
      <el-tree
        ref="treeRef"
        :data="filterData"
        show-checkbox
        node-key="id"
        :props="defaultProps"
        :default-expand-all="true"
        @node-click="handleNodeClick"
        @check-change="handleCheckChange"
      />
    </div>
    <el-divider direction="vertical" style="height: auto" />
    <div class="right" style="margin-left: 16px">
      <div class="head" style="margin-bottom: 22px">
        <span
          style="font-weight: 400; font-size: 16px; color: rgba(0, 0, 0, 0.88); line-height: 22px"
          >已选择（{{ selected }}</span
        >
        <span
          style="
            margin-left: 4px;
            font-size: 10px;
            font-weight: 400;
            color: rgba(0, 0, 0, 0.45);
            line-height: 22px;
          "
          >/&nbsp;{{ total }})</span
        >
      </div>
      <div class="selected">
        <el-tag
          v-for="(person, index) in selectedPeople"
          :key="index"
          closable
          @close="handleTagClose(person.id)"
        >
          {{ person.name }}
        </el-tag>
      </div>
      <div class="footer">
        <el-button @click="handleCancle"> 取消 </el-button>
        <el-button type="primary" @click="handleSubmit">提交</el-button>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, ref, watch } from 'vue';
import { Search } from '@element-plus/icons-vue';
import type { ElTree } from 'element-plus';
import { treeSelected, TreeNode, FormattedNode } from '../type';
import { countLeafNodes, formatTree } from '../hook/index';
import { queryUserTree } from '../api/index';
import { cloneDeep } from 'lodash-es';
const queryStr = ref<string>('');
const defaultProps = {
  children: 'children',
  label: 'name',
};
const treeData = ref<TreeNode[]>();
const nodeData = ref<FormattedNode[]>();
const filterData = ref<FormattedNode[]>();

const filterTree = (nodes: FormattedNode[], keyword: string): FormattedNode[] => {
  const filteredNodes: FormattedNode[] = [];
  const traverse = (node) => {
    let includeNode = false;
    if (node.name.includes(keyword)) {
      includeNode = true;
    }
    if (node.children) {
      const filteredChildren = node.children
        .map((child) => traverse(child))
        .filter((child) => child !== null);
      if (filteredChildren.length > 0) {
        includeNode = true;
        node = { ...node, children: filteredChildren };
      }
    }
    return includeNode ? node : null;
  };
  nodes.forEach((node) => {
    const result = traverse(node);
    if (result !== null) {
      filteredNodes.push(result);
    }
  });
  return filteredNodes;
};

const onSearch = () => {
  if (queryStr.value) {
    filterData.value = filterTree(nodeData.value!, queryStr.value);
  } else {
    filterData.value = nodeData.value;
  }
};
const total = ref<number>(0);
const selected = ref<number>(0);
const selectedPeople = ref<treeSelected[]>([]);
const handleCheckChange = (node, checked) => {
  if (!node.children || (node.children.length === 0 && node.userId)) {
    if (checked) {
      selectedPeople.value.push({
        id: node.id,
        name: node.name,
        userId: node.userId,
      });
    } else {
      const index = selectedPeople.value.findIndex((item) => item.id === node.id);
      if (index !== -1) {
        selectedPeople.value.splice(index, 1);
      }
    }
    selected.value = selectedPeople.value.length;
  }
};
const treeRef = ref<InstanceType<typeof ElTree>>();
const handleTagClose = (id) => {
  const index = selectedPeople.value.findIndex((item) => item.id === id);
  if (index !== -1) {
    selectedPeople.value.splice(index, 1);
    selected.value = selectedPeople.value.length;
    treeRef.value!.setChecked(id, false, true);
  }
};
const emit = defineEmits(['cancel', 'submit']);
const handleCancle = () => {
  emit('cancel');
};
const handleSubmit = () => {
  emit('submit', selectedPeople.value);
};
const handleNodeClick = (node) => {
  const isChecked = treeRef.value!.getCheckedKeys().includes(node.id);
  treeRef.value!.setChecked(node.id,!isChecked,true);
};
const props = defineProps<{
  selectedUser: treeSelected[];
}>();
onMounted(() => {
  queryUserTree().then((res) => {
    treeData.value = res;
    nodeData.value = formatTree(treeData.value!);
    filterData.value = nodeData.value;
    total.value = countLeafNodes(nodeData.value);
    const selectedIds: string[] = selectedPeople.value.map((item) => item.id as string);
    treeRef.value!.setCheckedKeys(selectedIds);
  });
});
watch(
  () => props.selectedUser,
  (newSelected) => {
    selectedPeople.value = cloneDeep(newSelected);
    selected.value = selectedPeople.value.length;
  },
  { immediate: true },
);
</script>

<style lang="scss" scoped>
.select-tree {
  display: flex;
  width: 100%;
  height: 100%;
  .left {
    display: flex;
    flex-direction: column;
    width: 50%;
    height: 100%;
    .el-tree {
      width: 100%;
      margin-top: 20px;
      font-weight: 500;
      font-size: 14px;
      color: #303133;
      line-height: 22px;
      overflow-y: auto;
      max-height: calc(100% - 80px);
    }
  }
  .right {
    display: flex;
    flex-direction: column;
    width: 50%;
    height: 100%;
    position: relative;
    .head {
      display: flex;
      align-items: center;
      font-weight: 400;
      font-size: 16px;
      color: rgba(0, 0, 0, 0.88);
      line-height: 22px;
    }
    .selected {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      overflow-y: auto;
      max-height: calc(100% - 120px);
    }
    .footer {
      display: flex;
      gap: 6px;
      position: absolute;
      right: 24px;
      bottom: 20px;
    }
  }
}
</style>