<!-- eslint-disable vue/no-unused-vars -->
<template>
    <div class="treeTransfer">
        <!-- 左边 -->
        <div class="leftTree">
            <p class="left_title">{{ props.title[0] }}</p>
            <div class="list">
                <div class="left_lowline">
                    <!-- <el-checkbox
                        v-model="checkedLeft"
                        :disabled="leftTreeData.length < 1"
                        label=""
                        size="large"
                        style="margin-right: 12px"
                        @change="leftAllCheck"
                    /> -->
                </div>
                <!-- 搜索 -->
                <div class="left_input">
                    <el-input
                        v-model="leftSearchText"
                        class="w-50"
                        placeholder="请输入"
                        clearable
                        prefix-icon="el-icon-search"
                        @clear="onSearchLeft"
                        @keyup.enter="onSearchLeft"
                        @change="onSearchLeft"
                    />
                </div>
                <div style="overflow: auto; flex: 1; margin-top: 10px">
                    <el-tree
                        ref="leftTreeRef"
                        :filter-node-method="filterNode"
                        :data="leftTreeData"
                        show-checkbox
                        :node-key="props.nodeKey"
                        :props="props.defaultProps"
                        v-slot="{ node, data }"
                        accordion
                        @check="onCheckLeft"
                        default-expand-all
                    >
                        <div>
                            {{ data.name }}
                        </div>
                    </el-tree>
                </div>
            </div>
        </div>
        <!-- 中间按钮 -->
        <div class="btnDiv">
            <div class="mg10">
                <el-button @click="toRight()" type="primary" :disabled="leftOperation.length < 1">
                    绑定
                    <el-icon><ArrowRight style="width: 20px !important; height: 20px !important" /></el-icon>
                </el-button>
            </div>
            <div class="mg10">
                <el-button @click="toLeft()" type="primary" :disabled="rightOperation.length < 1">
                    <el-icon><ArrowLeft style="width: 20px !important; height: 20px !important" /></el-icon>
                    解绑
                </el-button>
            </div>
        </div>
        <!-- 右边 -->
        <div class="rightTree">
            <div class="list">
                <p class="left_title">{{ props.title[1] }}</p>
                <div class="left_lowline">
                    <!-- <el-checkbox
                        v-model="checkedRight"
                        :disabled="rightTreeData.length < 1"
                        label=""
                        size="large"
                        style="margin-right: 12px"
                        @change="rightAllCheck"
                    /> -->
                </div>
                <!-- 搜索 -->
                <div class="left_input">
                    <el-input
                        v-model="rightSearchText"
                        class="w-50"
                        placeholder="请输入"
                        clearable
                        prefix-icon="el-icon-search"
                        @clear="onSearchRight"
                        @keyup.enter="onSearchRight"
                        @change="onSearchRight"
                    />
                </div>
                <div style="overflow: auto; flex: 1; margin-top: 10px">
                    <el-tree
                        :filter-node-method="filterNode"
                        ref="rightTreeRef"
                        :data="rightTreeData"
                        show-checkbox
                        :node-key="props.nodeKey"
                        :props="props.defaultProps"
                        v-slot="{ node, data }"
                        accordion
                        @check="onCheckRight"
                        default-expand-all
                    >
                        <div>
                            {{ data.name }}
                        </div>
                    </el-tree>
                </div>
            </div>
        </div>
    </div>
</template>
<script setup lang="ts">
//@ts-nocheck    解决ts类型报红
import { ref, onMounted, watch } from 'vue'
import lodash from 'lodash'
const props = defineProps(['nodeKey', 'fromData', 'toData', 'defaultProps', 'title'])
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
const checkedLeft = ref(false)
const checkedRight = ref(false)
const leftSearchText = ref('')
const rightSearchText = ref('')
const leftOperation = ref<any[]>([])
const rightOperation = ref<any[]>([])

// 定义emit
const emits = defineEmits(['change'])
const leftTreeRef = ref()
const rightTreeRef = ref()

// 左侧数据
const leftTreeData = ref([])
// 右侧数据
const rightTreeData = ref([])

watch(
    props,
    newVal => {
        leftTreeData.value = lodash.cloneDeep(newVal.fromData)
        rightTreeData.value = lodash.cloneDeep(newVal.toData)
    },
    { immediate: true }
)
watch(
    () => leftTreeData.value,
    val => {
        if (val) {
            val.map((item: any, index: any) => {
                if (item.pid) {
                    val.splice(index, 1)
                } else {
                    if (!item.children || item.children.length == 0) {
                        val.splice(index, 1)
                    } else {
                        item.children.map((vv: any, indexs: any) => {
                            console.log(vv, '-------------')
                            if (!vv.children || vv.children.length == 0) {
                                item.children.splice(indexs, 1)
                                item.children = [...new Set(item.children)]
                            }
                        })
                    }
                }
            })
        }
    },
    {
        immediate: true,
        deep: true
    }
)
watch(
    () => rightTreeData.value,
    val => {
        if (val) {
            val.map((item: any, index: any) => {
                if (item.pid) {
                    val.splice(index, 1)
                } else {
                    if (!item.children || item.children.length == 0) {
                        val.splice(index, 1)
                    } else {
                        item.children.map((vv: any, indexs: any) => {
                            console.log(vv, '++++++++++')
                            if (!vv.children || vv.children.length == 0) {
                                item.children.splice(indexs, 1)
                                item.children = [...new Set(item.children)]
                            }
                        })
                    }
                }
            })
        }
    },
    {
        immediate: true,
        deep: true
    }
)
watch(leftSearchText, val => {
    leftTreeRef.value?.filter(val)
})
watch(rightSearchText, val => {
    rightTreeRef.value?.filter(val)
})
defineExpose({
    leftTreeData,
    rightTreeData
})

onMounted(() => {
    leftSearchText.value = ''
    rightSearchText.value = ''
})

const removeChecked = (rightList, allCheckedKeys) => {
    rightList.forEach((e, index) => {
        if (allCheckedKeys.indexOf(e.id) == -1) {
            rightList.splice(index, 1)
        }
        if (e.children) {
            removeChecked(e.children, allCheckedKeys)
        }
    })
    return rightList
}
const recursionTree = (parents, allCheckedKeys) => {
    parents.forEach(e => {
        const list = lodash.filter(e.children, child => allCheckedKeys.indexOf(child.id) >= 0)
        e.children = list
        if (e.children.length !== 0) {
            recursionTree(e.children, allCheckedKeys)
        }
    })
    return parents
}
const handleData = (selectedNodes, leftTree, allCheckedKeys, type) => {
    console.log(selectedNodes, '选择的数据')
    //右移动，获取左边选择的数据，添加到右侧
    selectedNodes.map((item: any) => {
        //叶子结点
        //去绑定
        if (item.children && item.children.length != 0 && item.pid && type == 'left') {
            rightTreeData.value.map((vv: any) => {
                if (vv.id == item.pid) {
                    vv.children.push(item)
                }
                vv.children = [...new Set(vv.children)]
            })
        }
        //去解绑
        if (item.children && item.children.length != 0 && item.pid && type == 'right') {
            leftTreeData.value.map((vv: any) => {
                if (vv.id == item.pid) {
                    vv.children.push(item)
                }
                vv.children = [...new Set(vv.children)]
            })
        }
    })
}
// 去右边
const toRight = async () => {
    const leftTree = leftTreeRef.value
    checkedLeft.value = false
    if (!leftTree) {
        return
    }
    const leftNodes = leftTree.getCheckedNodes(false, true)
    //查找到有数据的父节点
    const parents = leftNodes.filter(el => el.children && el.children.length > 0)
    console.log(parents, '找到的父节点')
    // const checkedKeys = [...new Set(leftTree.getCheckedKeys(false))]
    const checkedKeys = leftTree.getCheckedKeys(false)
    const halfCheckedKeys = leftTree.getHalfCheckedKeys()
    const allCheckedKeys = halfCheckedKeys.concat(checkedKeys)
    const rightTree = rightTreeRef.value
    if (!rightTree) {
        let rightList = parents.map(parent => {
            const obj = lodash.omit(parent, ['children'])
            obj.children = lodash.filter(parent.children, child => allCheckedKeys.indexOf(child.id) >= 0)
            console.log(obj, '找到的数据275')
            return obj
        })

        let copyRightList = lodash.cloneDeep(rightList)
        removeChecked(copyRightList, allCheckedKeys)
        rightTreeData.value.push(...copyRightList)
        rightTreeData.value = [...new Set(rightTreeData.value)]
    } else {
        let isExist = false
        rightTree.data.forEach(e => {
            if (parents.length != 0 && parents[0].id === (e as any).id) isExist = true
        })
        console.log(isExist, '88')
        if (!isExist) {
            const overall = lodash.cloneDeep(parents)
            let rightList = await recursionTree(overall, allCheckedKeys)
            let copyRightList = lodash.cloneDeep(rightList)
            removeChecked(copyRightList, allCheckedKeys)
            rightTreeData.value.push(...copyRightList)
            rightTreeData.value = [...new Set(rightTreeData.value)]
        } else {
            handleData(leftNodes, rightTree, allCheckedKeys, 'left')
        }
    }
    // 移过去之后要删除原本的值
    leftNodes.forEach(node => {
        leftTree.setChecked(node, false, false)
        if (checkedKeys.indexOf(node.id) >= 0) {
            leftTree.remove(node)
        }
    })

    leftOperation.value = formatTree(leftTree.getCheckedNodes(false) || [], 'pid', 'id')
    // emits('change', leftTreeData.value, rightTreeData.value)
    emits('change', checkedKeys)
    setTimeout(() => {
        rightTree?.setCheckedNodes(leftNodes)
        rightOperation.value = formatTree(rightTree.getCheckedNodes(false) || [], 'pid', 'id')
        if (lodash.isEqual(rightOperation.value, rightTreeData.value)) {
            checkedRight.value = true
        } else {
            checkedRight.value = false
        }
    }, 500)
}
// // 去左边
const toLeft = async () => {
    checkedRight.value = false
    const rightTree = rightTreeRef.value
    console.log(rightTreeData.value, '++++++++++', leftTreeData.value)
    if (!rightTree) {
        return
    }
    //获取右侧选中已绑定的节点
    const rightNodes = rightTree.getCheckedNodes(false, true)
    const checkedKeys = [...new Set(rightTree.getCheckedKeys(false))]
    const halfCheckedKeys = rightTree.getHalfCheckedKeys()
    const allCheckedKeys = halfCheckedKeys.concat(checkedKeys)
    //获取有数据的节点
    const parents = lodash.filter(rightNodes, item => item.children && item.children.length > 0)
    const leftTree = leftTreeData.value.length ? leftTreeRef.value : null
    //左侧树无数据
    let leftList = parents.map(parent => {
        const obj = lodash.omit(parent, ['children'])
        obj.children = lodash.filter(parent.children, child => allCheckedKeys.indexOf(child.id) >= 0)
        return obj
    })
    let copyLeftList = lodash.cloneDeep(leftList)
    console.log(copyLeftList, 'copyLeftListcopyLeftListcopyLeftListcopyLeftListcopyLeftList')
    copyLeftList.map((item)=>{
        if(!item.pid){
            leftTreeData.value.push(item)
        }
        // leftTreeData.value.map((vv)=>{
        //     if(vv.id==item.pid){

        //     }
        // })
    })
    return
    if (!leftTree) {
        let leftList = parents.map(parent => {
            const obj = lodash.omit(parent, ['children'])
            obj.children = lodash.filter(parent.children, child => allCheckedKeys.indexOf(child.id) >= 0)
            return obj
        })
        let copyLeftList = lodash.cloneDeep(leftList)
        removeChecked(copyLeftList, allCheckedKeys)
        leftTreeData.value.push(...copyLeftList)
        leftTreeData.value = [...new Set(leftTreeData.value)]
    }
    //左侧树有数据
    else {
        let isExist = false
        leftTree.data.forEach(e => {
            if (parents.length != 0 && parents[0].id === (e as any).id) isExist = true
        })
        if (!isExist) {
            const overall = lodash.cloneDeep(parents)
            let leftList = await recursionTree(overall, allCheckedKeys)
            let copyLeftList = lodash.cloneDeep(leftList)
            console.log(copyLeftList, '5555555555555555555')
            // removeChecked(copyLeftList, allCheckedKeys)
            leftTreeData.value.push(...copyLeftList)
            leftTreeData.value = [...new Set(leftTreeData.value)]
        } else {
            handleData(rightNodes, leftTree, allCheckedKeys, 'right')
        }
    }
    console.log(rightTree, '11111111')

    rightNodes.forEach(node => {
        rightTree.setChecked(node, false, false)
        if (checkedKeys.indexOf(node.id) >= 0) {
            rightTree.remove(node)
        }
    })

    console.log(rightTree, '2222222')

    rightOperation.value = formatTree(rightTree.getCheckedNodes(false) || [], 'pid', 'id')
    // emits('change', leftTreeData.value, rightTreeData.value)
    emits('change', checkedKeys)
    console.log(leftTreeData.value, '99999999')
}

//左侧选中（移除原本值用）
const onCheckLeft = () => {
    leftOperation.value = formatTree(leftTreeRef.value?.getCheckedNodes(false) || [], 'pid', 'id')
    if (lodash.isEqual(leftOperation.value, leftTreeData.value)) {
        checkedLeft.value = true
    } else {
        checkedLeft.value = false
    }
}
// 右侧选中
const onCheckRight = () => {
    rightOperation.value = formatTree(rightTreeRef.value!.getCheckedNodes(false) || [], 'pid', 'id')
    if (lodash.isEqual(rightOperation.value, rightTreeData.value)) {
        checkedRight.value = true
    } else {
        checkedRight.value = false
    }
}

const formatTree = (tree: any[], parentKey: string = 'pid', idKey: string = 'id') => {
    // 格式化选择的树：清除全选下面的子节点
    let swap,
        parentIds: string[] = []
    // 先找出有children的id集合，再把所有的数据做对比，只要pid和其中一个对上，就把该数据删除；
    tree.forEach((item, index) => {
        if (item.children) {
            parentIds.push(item[idKey])
        }
    })
    swap = tree.filter((item, index) => {
        if (parentIds.indexOf(item[parentKey]) == -1) {
            return item
        }
    })
    return swap
}

const onSearchLeft = () => {
    leftTreeRef.value?.filter(leftSearchText.value)
}
const leftAllCheck = () => {
    const leftTree = leftTreeRef.value
    if (checkedLeft.value) {
        leftTree?.setCheckedNodes(leftTreeData.value)
        checkedLeft.value = true
    } else {
        leftTree?.setCheckedNodes([])
        checkedLeft.value = false
    }
    onCheckLeft()
}
const rightAllCheck = () => {
    const rightTree = rightTreeRef.value
    if (checkedRight.value) {
        rightTree?.setCheckedNodes(rightTreeData.value)
        checkedRight.value = true
    } else {
        rightTree?.setCheckedNodes([])
        checkedRight.value = false
    }
    onCheckRight()
}
const onSearchRight = () => {
    rightTreeRef.value?.filter(rightSearchText.value)
}
const filterNode = (value: string, data: any) => {
    if (!value) return true
    return data[props.defaultProps.label].includes(value)
}
</script>
<style lang="scss" scoped>
.treeTransfer {
    display: flex;
    height: 400px;
    width: 100%;

    .btnDiv {
        flex: 1;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;

        .mg10 {
            padding: 5px;
            :deep(svg),
            :deep(.el-icon) {
                height: 2em !important;
                width: 2em !important;
            }
        }
    }
    .leftTree {
        width: 45%;
        border: 1px solid rgb(182, 182, 182);
        box-sizing: border-box;
        padding: 5px 10px;
        .list {
            height: 100%;
            display: flex;
            flex-direction: column;
        }
    }
    .rightTree {
        border: 1px solid rgb(182, 182, 182);
        box-sizing: border-box;
        padding: 5px 10px;
        width: 45%;
        .list {
            height: 100%;
            display: flex;
            flex-direction: column;
        }
    }
    .left_lowline {
        display: flex;
        align-items: center;
    }
    .right_lowline {
        display: flex;
        align-items: center;
    }
}
</style>
