<template>
  <Cascader
    style="width: 100%"
    allowClear
    labelInValue
    :getPopupContainer="(node) => node.parentNode"
    :dropdownStyle="dropdownStyle"
    :placeholder="placeholder"
    :value="treeValue"
    :options="treeData"
    :multiple="multiple"
    :loadData="asyncLoadTreeData"
    v-bind="attrs"
    :show-search="{ filter: filterTreeNode }"
    change-on-select
    @change="onChange"
    @search="searchDebounced"
  />
</template>

<script lang="ts" setup>
  import { Cascader } from 'ant-design-vue';
  import { ref, unref, watch } from 'vue';
  import { useAttrs } from '/@/hooks/core/useAttrs';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { useDebounceFn } from '@vueuse/core';
  import { defHttp } from '/@/utils/http/axios';
  import { propTypes } from '/@/utils/propTypes';

  enum Api {
    url = '/sys/dict/loadTreeData',
    view = '/sys/dict/loadDictItem/',
  }

  const props = defineProps({
    value: propTypes.string.def(''),
    placeholder: propTypes.string.def('请选择'),
    dict: propTypes.string.def('id'),
    parentCode: propTypes.string.def(''),
    pidField: propTypes.string.def('pid'),
    maxHeight: propTypes.string.def('250px'),
    pidValue: propTypes.string.def(''),
    hasChildField: propTypes.string.def(''),
    converIsLeafVal: propTypes.integer.def(1),
    condition: propTypes.string.def(''),
    onlyLevel: propTypes.string.def('0'),
    multiple: propTypes.bool.def(false),
    loadTriggleChange: propTypes.bool.def(false),
    reload: propTypes.number.def(1),
  });

  const attrs = useAttrs();
  const emit = defineEmits(['change', 'update:value']);
  const { createMessage } = useMessage();

  // 响应式数据
  const treeData = ref<any[]>([]);
  const treeValue = ref<any>(null);
  const searchValue = ref('');
  const initialized = ref(false);

  // 非响应式数据
  const loadingMap = new Map();
  const childrenCache = new Map<string, any[]>();
  let tableName = '';
  let text = '';
  let code = '';

  // 计算属性
  const dropdownStyle = {
    maxHeight: props.maxHeight,
    overflow: 'auto',
    'virtual-scroll': true,
    'item-size': 32,
  };

  // 防抖搜索
  const searchDebounced = useDebounceFn(onSearch, 300);

  // 合并初始化逻辑的watch
  watch(
    [() => props.dict, () => props.reload],
    async () => {
      if (!initialized.value) {
        await validateProp();
        initDictInfo();
        initialized.value = true;
      }
      await loadRoot();
      await loadItemByCode();
    },
    { immediate: true }
  );

  // 优化后的value watch
  watch(
    () => props.value,
    (newVal) => {
      if (newVal !== unref(treeValue)?.value) {
        loadItemByCode();
      }
    }
  );

  /**
   * 根据code获取下拉数据并回显
   */
  async function loadItemByCode() {
    if (!props.value || props.value === '0') {
      treeValue.value = props.multiple ? [] : null;
      return;
    }

    const params = { key: props.value };
    const result = await defHttp.get({ url: `${Api.view}${props.dict}`, params }, { isTransformResponse: false });

    if (result.success && result.result?.length > 0) {
      console.log(result, 'result');
      console.log(result.result, 'result.result');
      console.log(props, 'props');
      const values = props.value;
      console.log(values, 'values');
      const length = values.length;
      console.log(length, 'length');
      if (length === 2) {
        treeValue.value = [values];
        console.log(treeValue.value, 'treeValue.value2');
      } else if (length === 4) {
        treeValue.value = [values.substring(0, 2), values];
        console.log(treeValue.value, 'treeValue.value4');
      } else if (length === 6) {
        treeValue.value = [values.substring(0, 2), values.substring(0, 4), values];
        console.log(treeValue.value, 'treeValue.value6');
      }

      onLoadTriggleChange(result.result[0]);
    }
  }

  function onLoadTriggleChange(text) {
    if (!props.multiple && props.loadTriggleChange) {
      emit('change', props.value, text);
    }
  }

  /**
   * 初始化数据字典信息
   */
  function initDictInfo() {
    const arr = props.dict?.split(',');
    tableName = arr[0];
    text = arr[1];
    code = arr[2];
  }

  /**
   * 加载根节点数据
   */
  async function loadRoot() {
    const params = {
      pid: props.pidValue,
      pidField: props.pidField,
      hasChildField: props.hasChildField,
      converIsLeafVal: props.converIsLeafVal,
      condition: props.condition,
      tableName,
      text,
      code,
      // 尝试让后端一次性返回完整树（若后端不支持会忽略该参数）
      loadAll: 1,
    };

    const res = await defHttp.get({ url: Api.url, params }, { isTransformResponse: false });

    if (res.success && res.result) {
      treeData.value = normalizeNodes(res.result);
    } else {
      console.warn('树根节点查询结果异常', res);
    }
  }

  /**
   * 规范化节点字段（后端字段 -> Cascader 所需字段）
   */
  function normalizeNodes(nodes: any[]): any[] {
    if (!Array.isArray(nodes)) return [];
    return nodes.map((n) => {
      const node = { ...n };
      // 后端返回一般包含：key/title/leaf/children
      node.value = node.key;
      node.label = node.title;
      node.isLeaf = !!node.leaf;

      if (Array.isArray(node.children) && node.children.length > 0) {
        node.children = normalizeNodes(node.children);
      } else {
        // 未返回 children 时，靠懒加载展开
        node.children = undefined;
      }
      return node;
    });
  }

  /**
   * 加载单个树节点数据
   */
  async function loadTreeNodeData(pid) {
    const params = {
      pid,
      pidField: props.pidField,
      hasChildField: props.hasChildField,
      converIsLeafVal: props.converIsLeafVal,
      condition: props.condition,
      tableName,
      text,
      code,
    };
    return defHttp.get({ url: Api.url, params }, { isTransformResponse: false });
  }

  /**
   * Cascader 懒加载子节点（展开时触发）
   */
  async function asyncLoadTreeData(selectedOptions: any[]) {
    const targetOption = selectedOptions?.[selectedOptions.length - 1];
    if (!targetOption) return;

    const pid = String(targetOption.key ?? targetOption.value ?? '');
    if (!pid) return;

    // 已经加载过
    if (Array.isArray(targetOption.children) && targetOption.children.length > 0) return;

    // 命中缓存
    const cached = childrenCache.get(pid);
    if (cached) {
      targetOption.children = cached;
      treeData.value = treeData.value.slice();
      return;
    }

    if (loadingMap.has(pid)) {
      await loadingMap.get(pid);
      return;
    }

    targetOption.loading = true;
    const promise = (async () => {
      try {
        const res = await loadTreeNodeData(pid);
        if (res?.success && Array.isArray(res.result)) {
          const children = normalizeNodes(res.result);
          childrenCache.set(pid, children);
          targetOption.children = children;
        } else {
          targetOption.children = [];
          targetOption.isLeaf = true;
        }
        treeData.value = treeData.value.slice();
      } finally {
        targetOption.loading = false;
        loadingMap.delete(pid);
      }
    })();

    loadingMap.set(pid, promise);
    await promise;
  }

  function filterTreeNode(inputValue, path) {
    return path.some((option) => option.label.toLowerCase().includes(inputValue.toLowerCase()));
  }

  /**
   * 选中树节点事件
   */
  function onChange(value, _selectedOptions) {
    if (!value) {
      emitValue('');
    } else if (Array.isArray(value)) {
      emitValue(value.slice(-1));
    } else {
      emitValue(value);
    }
    treeValue.value = value;
  }

  function emitValue(value) {
    emit('change', value);
    emit('update:value', value);
  }

  /**
   * 搜索事件
   */
  function onSearch(val) {
    searchValue.value = val;
    // 可以在这里添加实际的搜索逻辑
  }

  /**
   * 校验条件配置
   */
  async function validateProp() {
    const mycondition = props.condition;
    if (!mycondition) return;

    try {
      const test = JSON.parse(mycondition);
      if (typeof test !== 'object' || !test) {
        throw new Error();
      }
    } catch (e) {
      createMessage.error('组件JTreeSelect-condition传值有误，需要一个json字符串!');
      throw e;
    }
  }
</script>

<style lang="less"></style>
