<template>
    <div>
        <!-- 搜索框 -->
        <a-input v-model:value="searchValue" placeholder="请输入关键字进行过滤" />
        <!-- 搜索结果列表 -->
        <div class="dropdown-content">
            <div v-if="searchResultList.length">
                <div class="search-select-li" v-for="node in searchResultList" :key="node[fieldNames.key]"
                    @click="onNode(node)">
                    {{ node[fieldNames.title] }}
                </div>
            </div>
            <!-- 树结构 -->
            <div v-else>
                <!-- 等待树数据加载完成后再显示 -->
                <a-tree v-if="isLocalTreeDataLoaded" :tree-data="localTreeData" :fieldNames="fieldNames"
                    :checkable="showCheckbox" :multiple="multiple" v-model:selectedKeys="selectedKeys"
                    v-model:checkedKeys="checkedKeys" v-model:expandedKeys="expandedKeys" @select="onSelect"
                    @expand="onExpand" :load-data="props.isAsync ? onLoadData : null" v-bind="$attrs">
                </a-tree>
                <div v-else>加载中...</div>
            </div>
        </div>
    </div>
</template>

<script setup>
import { isEmpty } from '@/utils/validate'
import { message } from "ant-design-vue";
import { getTreeData } from '@/api/treeDataApi';
import { getAnsKeys, getDscKeys, getWithoutDscKeys, delAnsAndDscKeys, findNodes, searchNodes } from '@/utils/treeUtil'
import { ref, defineProps, defineExpose, defineEmits, onMounted, onBeforeUnmount, watch, nextTick, computed } from 'vue';
// 1.测试复选框树，checked的变化，为啥机构面板需要特殊写个一个方法呢
// 2.本地变量的是直接解构赋值 是否有效，还是放到钩子函数： 答：统一放到钩子函数中处理

// 20250303
// 1. a-select-tree 引用a-tree 通过v-model:value双向绑定了数据, value及时更新了 option还未更新，会影响翻译嘛
// 解: 通过事件的方式将已经选择的节点传递给父组件,就看父组件加载存在先后问题了，父组件通过事件获取已经选择的节点然后赋值给自己optionData
// 2. 异步树时,a-select-tree将默认异步根节点通过prop传递给a-tree后 ,后续异步加载时后，opntion需要给到a-select-后续异步加载时后，opntion需要给到a-select-tree的同时，当关闭弹窗后再次打开已经加载一部分数据会重新再加载一次吗
// 3. 监听不同类型的数据是否需要重新加载数据如汇总关系发生变化重新获取机构， a-select-tree和a-tree都需要处理 但是a-tree需要加一个判断当prop.treeData有数据则不需要处理否则就需要处理，同时获取树数据和默认值方法需要公共起来
// 解：a-select-tree 根本不会将 relationNo、brNos、sobNo传递给 a-tree 所以根据监控不到
// 定义组件接收的 props
const props = defineProps({
    value: {
        type: [String, Array, Number],
        required: true
    },
    treeType: {
        type: String,
        default: ''
    },
    isAsync: {
        type: Boolean,
        default: false
    },
    relationNo: {
        type: String,
        default: ''
    },
    brNos: {
        type: Array,
        default: () => []
    },
    stddNo: {
        type: String,
        default: ''
    },
    sobNo: {
        type: [String, Array],
        default: ''
    },
    treeData: {
        type: Array,
        default: () => []
    },
    formItemProps: {
        type: Object,
        default: () => { }
    },
    multiple: {
        type: Boolean,
        default: false
    },
    showCheckbox: {
        type: Boolean,
        default: false
    },
    isStopPropagation: {
        // 是否阻止冒泡
        type: Boolean,
        default: false
    },
    isClearSearchResult: {
        // 是否自动清空搜索结果
        type: Boolean,
        default: true
    },
    isWithoutDsc: {
        // 是否不包含后代节点返回
        type: Boolean,
        default: false
    },
    fieldNames: {
        type: Object,
        default: () => {
            return {
                key: 'id',
                title: 'name',
                children: 'children'
            }
        }
    }
});
// 定义自定义事件，用于通知父组件
const emits = defineEmits(['update:value', 'update:stddNo', 'get-nodes', 'on-node']);
console.log('wyq:pro-tree-接收参数:', props);
// 定义搜索框的值
const searchValue = ref('');
// 搜索结果列表
const searchResultList = ref([]);
// 树结构数据
const localTreeData = ref([]);
// 标记 localTreeData 是否加载完成
const isLocalTreeDataLoaded = ref(false);
// 
const selectedKeys = computed({
    // 从父组件获取值
    get: getSelectedKeys,
    // 向父组件传递更新
    set: setSelectedKeys
});

const checkedKeys = computed({
    // 从父组件获取值
    get: getCheckedKeys,
    // 向父组件传递更新
    set: setCheckedKeys
});

const expandedKeys = ref([]);


function getSelectedKeys () {
    if (props.showCheckbox === false && !isEmpty(localTreeData.value) && localTreeData.value.length > 0) {
        console.log('wyq:pro-tree-获取selectedKeys值:', props.value);
        //return [...props.value];
        //return Array.isArray(props.value) ? [...props.value] : props.value;
        return Array.isArray(props.value) ? props.value : [props.value];
    }
    return [];
}

function setSelectedKeys (value) {
    if (props.showCheckbox === false) {
        console.log('wyq:pro-tree-更改selectedKeys值:', value);
        const nodes = findNodes(localTreeData.value, props.fieldNames.key, [...value]);
        if (props.treeType === 'sobTree') {
            if (!isEmpty(nodes) && nodes.length > 0) {
                emits('update:stddNo', nodes[0]['pid'].split('@')[0]);
            } else {
                emits('update:stddNo', '');
            }
            emits('update:value', value[0]);
        } else {
            emits('update:value', value);
        }
        console.log('DepartPanel-wyq:pro-tree-更改selectedKeys值:', value, nodes);
        emits('get-nodes', value, nodes);
    }
}

function getCheckedKeys () {
    if (props.showCheckbox === true && !isEmpty(localTreeData.value) && localTreeData.value.length > 0) {
        console.log('wyq:pro-tree-获取checkedKeys值:', props.value);
        //return [...props.value];
        //return Array.isArray(props.value) ? [...props.value] : props.value;
        return Array.isArray(props.value) ? props.value : [props.value];
    }
    return [];
}

function setCheckedKeys (value) {
    if (props.showCheckbox === true) {
        console.log('wyq:pro-tree-更改checkedKeys值:', value);
        if (props.isWithoutDsc === true) {
            const { withoutDesKeys, withoutDesNodes } = getWithoutDscKeys(localTreeData.value, value, props.fieldNames);
            console.log('wyq:pro-tree-获取withoutDesKeys值:', withoutDesKeys, withoutDesNodes);
            emits('get-nodes', value, withoutDesNodes);
            emits('update:value', withoutDesKeys);
        } else {
            const nodes = findNodes(localTreeData.value, props.fieldNames.key, [...value]);
            emits('get-nodes', value, nodes);
            emits('update:value', value);
        }
    }
}

const onSelect = (keys, info) => {
    if (props.showCheckbox === true) {
        const node = { ...info.node };
        const key = node[props.fieldNames.key];
        // 得到被选中的所有节点的 key 值
        console.log('wyq-onSelect-初始', checkedKeys.value);
        // 处理勾选节点:将勾选节点的子、孙节点全部勾选,这个地方调用下是为了下一步判断的当前点击的是否存在
        let dscKeys = getDscKeys(localTreeData.value, checkedKeys.value);
        const index = dscKeys.indexOf(key);
        console.log('wyq-onSelect-处理后', dscKeys);
        if (index > -1) {
            // 如果 key 已存在于 keys 中，则移除
            console.log('wyq-onSelect-已存在移除', key);
            // 调用移除节点的方法: 1.需要将移除的节点上级及上上级节点移除 2.需要将移除的节点子、孙节点移除
            dscKeys = delAnsAndDscKeys(localTreeData.value, key, dscKeys);
        } else {
            // 如果 key 不存在于 checkedKeys 中，则添加
            console.log('wyq-onSelect-不存在添加', key);
            dscKeys.push(key);
            // 这个地方再次调用,是因为如果勾选了父节点,需要将父节点下所有子节点全部勾选,所以需要再次处理勾选节点
            dscKeys = getDscKeys(localTreeData.value, dscKeys);
        }
        checkedKeys.value = dscKeys;
    } else {
        if (props.multiple === false) {
            // 单选模式
            if (props.treeType === 'sobTree') {
                if (info.node.children && info.node.children.length > 0) {
                    message.error('请选择账套信息');
                    nextTick(() => {
                        selectedKeys.value = [];
                    });
                }
            }
        }
    }
};

const onExpand = (expandedKeys, info) => {
    if (props.isAsync === true) {
        // 展开节点时，关闭冒泡不然会影响父组件
        // TODO 这个地方 与 pro-select-tree有冲突
        if (props.isStopPropagation === true) {
            info.nativeEvent.stopPropagation();
        }
    }
}

async function onLoadData (treeNode) {
    return new Promise(async (resolve, reject) => {
        if (treeNode.dataRef.children) {
            resolve();
            return;
        }
        try {
            const { treeData } = await getTreeData(props, { id: treeNode.eventKey });
            // data.children 是从后端获取的子节点数据
            treeNode.dataRef.children = treeData;
            // 更新 localTreeData
            localTreeData.value = [...localTreeData.value];
            resolve();
        } catch (error) {
            reject(error);
        }
    });
}

// TODO : 这个地方点击搜索结果, 通知父组件进行关闭下来弹窗, 那再次触发下拉展示的是树结果还是列表？
function onNode (node) {
    // 勾选当前节点
    console.log('wyq:pro-tree-点击搜索结果', node, props.fieldNames);
    emits('on-node', node);
    if (props.showCheckbox === true) {
        checkedKeys.value = [node[props.fieldNames.key]];
    } else {
        selectedKeys.value = [node[props.fieldNames.key]];
    }
    // 展开父节点和爷节点
    const parentKeys = getAnsKeys(localTreeData.value, node[props.fieldNames.key], props.fieldNames);
    //localExpandedKeys.value = [...new Set([...localExpandedKeys.value, ...parentKeys])];
    expandedKeys.value = [...new Set([...parentKeys])];
    // TODO 这个地方 与 pro-select-tree有冲突
    if (props.isClearSearchResult === true) {
        // 清空搜索框
        searchValue.value = '';
        // 清空搜索结果列表
        searchResultList.value = [];
    }
}

const onClearSearch = () => {
    console.log('wyq:pro-tree-清空搜索结果');
    // 清空搜索框
    searchValue.value = '';
    // 清空搜索结果列表
    searchResultList.value = [];
}
defineExpose({ onClearSearch });


// 监听搜索框的值，过滤列表
watch(searchValue, (value) => {
    if (value) {
        searchResultList.value = searchNodes(localTreeData.value, props.fieldNames.title, value);
    } else {
        searchResultList.value = [];
    }
});

// 监听shuTreeData变化，更新localTreeData
watch(() => props.treeData, (newTreeData) => {
    localTreeData.value = newTreeData;
});

// 根据不同类型的树监听相应参数的变化
if (props.treeType === 'deptTree') {
    console.log('wyq:pro-tree-监听机构汇总关系发生变化1', props.relationNo);

    watch(() => props.relationNo, async () => {
        // 监听机构汇总关系发生变化,重新请求机构树
        console.log('wyq:pro-tree-监听机构汇总关系发生变化');
        await getTreeTypeData();
    });
} else if (props.treeType === 'sobTree') {
    // 监听账套树
    watch(() => props.brNos, async () => {
        // 监听机构发生变化,重新请求账套树
        await getTreeTypeData();
    });
} else if (props.treeType === 'sobItemTree') {
    watch(() => props.sobNo, async () => {
        // 监听账套发生变化,重新请求科目树
        await getTreeTypeData();
    });
}


onMounted(async () => {
    console.log('wyq:pro-tree-挂载');
    await initLocalTreeData();
});

async function initLocalTreeData () {
    console.log('wyq:pro-tree-准备树数据');
    if (!isEmpty(props.treeData)) {
        localTreeData.value = props.treeData;
        if (!isEmpty(props.value)) {
            setDefaultKeys(props, props.value);
        }
    } else if (!isEmpty(props.treeType)) {
        // 如果 props.treeData 不存在，则请求后端接口获取树数据
        await getTreeTypeData();
    }
    if (isLocalTreeDataLoaded.value === false) {
        isLocalTreeDataLoaded.value = true;
    }
}

async function getTreeTypeData () {
    const { treeData, defaultValue, defaultStddNo } = await getTreeData(props, {});
    if (!isEmpty(treeData) && treeData.length > 0) {
        localTreeData.value = treeData;
        if (!isEmpty(defaultValue)) {
            setDefaultKeys(props, defaultValue);
        }
        // if (!isEmpty(defaultStddNo) && props.treeType === 'sobTree') {
        //     emits('update:stddNo', defaultStddNo);
        // }
    }
    console.log('wyq:pro-tree-获取树数据完成', treeData);
}

// 封装设置选中/勾选键值的逻辑
const setDefaultKeys = (props, defaultValue) => {
    if (props.showCheckbox === true) {
        //checkedKeys.value = [...value];
        //checkedKeys.value = Array.isArray(defaultValue) ? [...defaultValue] : defaultValue;
        checkedKeys.value = Array.isArray(defaultValue) ? defaultValue : [defaultValue];
    } else {
        //selectedKeys.value = [...value];
        selectedKeys.value = Array.isArray(defaultValue) ? defaultValue : [defaultValue];
    }
};
</script>

<style scoped>
.dropdown-content {
    /* 设置固定的高度和宽度 */
    max-height: 300px;
    /* width: 500px; */
    /* 设置溢出时显示滚动条 */
    overflow: auto;
    /* 可以根据需要添加其他样式 */
    /* border: 1px solid #ccc; */
    padding: 8px;
}

.dropdown-content2 {
    /* 设置固定的高度和宽度 */
    max-height: 300px;
    /* width: 500px; */
    /* 设置溢出时显示滚动条 */
    overflow: auto;
    /* 防止内容换行 */
    white-space: nowrap;
    /* 当内容宽度超过元素宽度时显示横向滚动条 */
    overflow-x: auto;
    /* 可以根据需要添加其他样式 */
    /* border: 1px solid #ccc; */
    padding: 8px;
}

.search-select-li {
    padding: 3px 10px;
    padding-left: 0px;
    /* 调整内边距 */
    cursor: pointer;
}

.search-select-li:hover {
    background-color: #1890ff;
    /* 使用主题色 */
    color: #fff;
    /* 改变文字颜色 */
}
</style>
