<template>
  <el-cascader
    ref="cascaderRef"
    :model-value="value"
    :options="multiple ? treeData : treeAllData"
    :filterable="filterable"
    :filter-method="filterNode"
    :clearable="clearable"
    :props="defaultProps"
    @change="handleNodeClick"
  />
</template>

<script setup lang="ts" name="TreeFilter">
import { ref, watch, onBeforeMount, nextTick } from "vue";
import { ElTree, ElCascader } from "element-plus";
import { Search } from "@element-plus/icons-vue";
import { pinyinFilter } from "@/utils/pinyin";
import type { CascaderNode } from "element-plus";

// 接收父组件参数并设置默认值
interface TreeFilterProps {
  requestApi?: (data?: any) => Promise<any>; // 请求分类数据的 api ==> 非必传
  dataCallback?: (data?: any) => any; // 返回的数据进行处理的方法 ==> 非必传
  data?: { [key: string]: any }[]; // 分类数据，如果有分类数据，则不会执行 api 请求 ==> 非必传
  value?: any;
  // selected?: any; // 选择的值
  // title?: string; // treeFilter 标题 ==> 非必传
  // id?: string; // 选择的id ==> 非必传，默认为 “id”
  label?: string; // 显示的label ==> 非必传，默认为 “label”
  valueText?: string; // 显示的value ==> 非必传，默认为 “value”
  multiple?: boolean; // 是否为多选 ==> 非必传，默认为 false
  // defaultValue?: any; // 默认选中的值 ==> 非必传
  // expandOnClickNode?: boolean; // 是否在点击节点的时候展开或者收缩节点， 默认值为 false false，则只有点箭头图标的时候才会展开或者收缩节点。
  // wrapperCls?: string; // 外层类名 ==> 非必传
  // searchable?: boolean; // 是否可搜索 ==> 非必传，默认为 true
  // searchText?: string;
  // defaultExpandAll?: boolean; // 是否默认展开所有节点 ==> 非必传，默认为 false

  /**
   * @description 该选项是否可以被搜索  ==> 非必传，默认为 false
   */
  filterable?: boolean;
  /**
   * @description 自定义搜索逻辑，第一个参数是node，第二个参数是keyword，返回的布尔值表示是否保留该选项
   * @function (node: CascaderNode, keyword: string) => boolean
   */
  filterMethod?: (node: CascaderNode, keyword: string) => boolean;
  /**
   * @description 是否支持清空选项==> 非必传，默认为 false
   */
  clearable?: boolean;
}
const props = withDefaults(defineProps<TreeFilterProps>(), {
  id: "id",
  label: "label",
  valueText: "value",
  multiple: false,
  expandOnClickNode: false,
  wrapperCls: "card",
  searchable: true,
  searchText: "",
  defaultExpandAll: true,

  filterable: false,
  clearable: true
});

const defaultProps: any = {
  children: "children",
  label: props.label,
  value: props.valueText,
  expandTrigger: "hover",
  multiple: props.multiple,
  checkStrictly: true,
  emitPath: false
};

const emit = defineEmits(["update:value", "change"]);

const cascaderRef = ref<InstanceType<typeof ElCascader>>();
const treeData = ref<{ [key: string]: any }[]>([]);
const treeAllData = ref<{ [key: string]: any }[]>([]);

const selected = ref();
// const setSelected = () => {
//   if (props.multiple) selected.value = Array.isArray(props.defaultValue) ? props.defaultValue : [props.defaultValue];
//   else selected.value = typeof props.defaultValue === "string" ? props.defaultValue : "";
// };

onBeforeMount(async () => {
  // setSelected();
  if (props.requestApi) {
    let data = await props.requestApi!();
    props.dataCallback && (data = props.dataCallback(data));
    treeData.value = data;
    treeAllData.value = [{ value: -1, [props.label]: "全部" }, ...data];
  }
});

// // 使用 nextTick 防止打包后赋值不生效，开发环境是正常的
// watch(
//   () => props.defaultValue,
//   () => nextTick(() => setSelected()),
//   { deep: true, immediate: true }
// );

watch(
  () => props.data,
  () => {
    if (props.data?.length) {
      treeData.value = props.data;
      treeAllData.value = [{ value: -1, [props.label]: "全部" }, ...props.data];
    }
  },
  { deep: true, immediate: true }
);

// const filterText = ref("");
// watch(filterText, val => {
//   console.log(" filterText val :>> ", val);
//   cascaderRef.value!.filter(val);
// });
// watch(
//   () => props.searchText,
//   val => {
//     console.log(" filterText val :>> ", val);
//     cascaderRef.value!.filter(val);
//   }
// );

// 过滤
const filterNode = (node: CascaderNode, keyword: string) => {
  if (props.filterMethod) {
    return props.filterMethod(node, keyword);
  }
  if (!keyword) return true;

  let parentNode = node!.parent,
    labels = [{ label: node.label }],
    level = 1;
  console.log("filterNode parentNode :>> ", parentNode);
  while (level < node.level) {
    labels.push({
      label: parentNode!.label
    });
    parentNode = parentNode!.parent;
    level++;
  }
  return pinyinFilter(keyword, labels, ["label"]).length > 0;
  // return labels.some(label => label.indexOf(value) !== -1);
};

// interface FilterEmits {
//   (e: "change", value: any, valueArr: any): void;
// }
// const emit = defineEmits<FilterEmits>();

/**
 * @description 访问当前选中节点的下级节点数值
 * @param nodes 当前节点
 * @returns 获取当前节点的所有子节点value
 */
const getChildNode = (nodes: any) => {
  console.log("getChildNode nodes :>> ", nodes);
  let arr: any = [];
  nodes.value && arr.push(nodes.value);
  if (nodes.children) {
    console.log("nodes.children :>> ", nodes.children);
    nodes.children.map((item: any) => {
      if (item.children) {
        let arr1 = getChildNode(item);
        arr = arr.concat(arr1);
      } else {
        arr.push(item.value);
      }
    });
  }
  console.log("arr :>> ", arr);
  return arr;
};

// 单选
const handleNodeClick = (value: any) => {
  if (props.multiple) return;
  console.log("handleNodeClick data :>>", value, cascaderRef.value?.getCheckedNodes(false));

  let arr = cascaderRef.value?.getCheckedNodes(false) ?? [];
  if (arr.length) {
    arr = getChildNode(arr[0]);
  }

  emit("change", value, arr);
};

// // 多选
// const handleCheckChange = () => {
//   emit("change", cascaderRef.value?.getCheckedNodes(false), []);
// };

// 暴露给父组件使用
defineExpose({ treeData, treeAllData, cascaderRef });
</script>

<style scoped lang="scss">
@import "./index.scss";
</style>
