<template>
  <Cascader
    style="width: 100%"
    allowClear
    labelInValue
    :getPopupContainer="(node) => node.parentNode"
    :dropdownStyle="dropdownStyle"
    :placeholder="placeholder"
    :value="treeValue"
    :options="treeData"
    :multiple="multiple"
    v-bind="attrs"
    :show-search="{ 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();
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) {
    const values = props.value;
    const length = values.length;
    
    if (length === 2) {
      treeValue.value = [values];
    } else if (length === 4) {
      treeValue.value = [values.substring(0, 2), values];
    } else if (length === 6) {
      treeValue.value = [
        values.substring(0, 2),
        values.substring(0, 4),
        values,
      ];
    }

    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,
  };

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

  if (res.success && res.result) {
    res.result.forEach(i => {
      i.value = i.key;
      if (props.onlyLevel !== '1') {
        i.isLeaf = !!i.leaf;
        i.label = i.title;
        loadTreeData(i);
      }
    });
    
    treeData.value = res.result;
  } else {
    console.warn('树根节点查询结果异常', res);
  }
}

/**
 * 加载树节点数据
 */
async function loadTreeData(treeNode) {
  if (treeNode.children) return;
  
  const pid = treeNode.key;
  if (loadingMap.has(pid)) return loadingMap.get(pid);
  
  const promise = loadTreeNodeData(pid);
  loadingMap.set(pid, promise);
  
  try {
    const res = await promise;
    if (res.success) {
      res.result.forEach(i => {
        i.value = i.key;
        if (props.onlyLevel !== '2') {
          i.isLeaf = !!i.leaf;
          i.label = i.title;
          loadTreeData(i);
        }
      });
      
      addChildren(pid, res.result, treeData.value);
      updateTreeData();
    }
  } finally {
    loadingMap.delete(pid);
  }
}

/**
 * 加载单个树节点数据
 */
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 });
}

/**
 * 更新树数据（轻量级更新）
 */
function updateTreeData() {
  treeData.value = treeData.value.slice();
}

/**
 * 添加子节点（非递归实现）
 */
function addChildren(pid, children, treeArray) {
  if (!treeArray || treeArray.length === 0) return;
  
  const stack = [...treeArray];
  while (stack.length) {
    const item = stack.pop();
    if (item.key === pid) {
      if (!children || children.length === 0) {
        item.isLeaf = true;
      } else {
        item.children = children;
      }
      break;
    }
    if (item.children) {
      stack.push(...item.children);
    }
  }
}

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>