<template>
    <div class="hc-project-wbs-log relative h-full">
        <div v-loading="isLoading" class="hc-flex-center relative mb-14px">
            <span>选择WBS：</span>
            <el-select
                v-model="wbsId"
                placeholder="请选择WBS"
                class="w-500px"
                size="large"
                :disabled="isDisabled"
                @change="wbsChange"
            >
                <el-option-group
                    v-for="group in wbsTreeList"
                    :key="group.label"
                    :label="group.label"
                >
                    <el-option
                        v-for="item in group.data"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                    />
                </el-option-group>
            </el-select>
        </div>
        <div class="wbs-template-body">
            <div v-loading="leftLoading" class="left">
                <hc-card-item scrollbar :title="`${leftNum}项`">
                    <template #extra>
                        <el-checkbox
                            v-model="allChecked"
                            label="默认全部引用"
                            size="large"
                            @change="checkChang"
                        />
                    </template>
                    <el-tree
                        ref="leftTreeRef"
                        :data="leftTreeData"
                        show-checkbox
                        node-key="id"
                        :props="treeProps"
                        highlight-current
                        :expand-on-click-node="false"
                        @node-expand="nodeLeftTreeExpand"
                        @check-change="checkLeftTreeChange"
                    />
                </hc-card-item>
            </div>
            <div class="action">
                <div class="relative">
                    <div class="relative">
                        <el-button
                            hc-btn
                            :type="leftNum <= 0 ? '' : 'primary'"
                            :disabled="leftNum <= 0"
                            @click="addTreeClick"
                        >
                            <i class="i-ri-arrow-right-line" />
                        </el-button>
                    </div>
                    <div class="relative mt-14px">
                        <el-button
                            hc-btn
                            :type="rightNum <= 0 ? '' : 'primary'"
                            :disabled="rightNum <= 0"
                            @click="delTreeClick"
                        >
                            <i class="i-ri-arrow-left-line" />
                        </el-button>
                    </div>
                </div>
            </div>
            <div v-loading="rightLoading" class="right">
                <hc-card-item scrollbar :title="`${rightNum}项`">
                    <el-tree
                        ref="rightTreeRef"
                        :data="rightTreeData"
                        show-checkbox
                        node-key="id"
                        :props="treeProps"
                        highlight-current
                        :expand-on-click-node="false"
                        :default-expanded-keys="rightExpands"
                        @check-change="checkRightTreeChange"
                    />
                </hc-card-item>
            </div>
        </div>
    </div>
</template>

<script setup>
import { nextTick, onMounted, ref, watch } from "vue";
import { useAppStore } from "~src/store";
import { deepClone, getArrValue, getObjValue, isNullES } from "js-fast-way";
import mainApi from "~api/project/project";
import treeApi from "~api/wbs/tree";

//缓存
const store = useAppStore();

//双向绑定
const modelData = defineModel("modelValue", {
    default: {},
});

//监听数据
const formModel = ref({});
watch(
    () => modelData.value,
    (data) => {
        formModel.value = data;
    },
    { immediate: true, deep: true }
);

//监听
const userInfo = ref(store.getUserInfo);
watch(
    () => store.getUserInfo,
    (info) => {
        userInfo.value = info;
    },
    { immediate: true, deep: true }
);

//渲染完成
onMounted(() => {
    getWbsTreeList();
});

//树配置
const leftTreeRef = ref(null);
const rightTreeRef = ref(null);
const treeProps = {
    children: "children",
    label: "title",
};

//获取WBS树列表
const wbsId = ref("");
const wbsTreeList = ref([]);
const isLoading = ref(false);
const getWbsTreeList = async () => {
    isLoading.value = true;
    const { data } = await mainApi.findLogWbsTreeList();
    // 格式化数据
    let arr = [{ label: "公有库", data: [] }],
        res = getArrValue(data);
    // 公有库
    res.forEach((item) => {
        item.value = item.id;
        item.label = item.wbsName;
    });
    arr[0].data = res;
    wbsTreeList.value = arr;
    //处理选中
    const form = getObjValue(formModel.value);
    let refId = form.referenceLogWbsTemplateId;
    if (isNullES(refId) || refId <= 0 || Number(form.wbsType) <= 0) {
        wbsId.value = "";
        isLoading.value = false;
        return;
    }
    wbsId.value = refId;
    isLoading.value = false;
    await getLeftTreeData();
    await getRightTreeApi();
    setRightTree();
};

//左边树
const leftLoading = ref(false);
const leftTreeData = ref([]);
const getLeftTreeData = async () => {
    if (isNullES(wbsId.value)) return;
    leftLoading.value = true;
    const { tenant_id } = getObjValue(userInfo.value);
    const { data } = await treeApi.getAlltree({
        tenantId: tenant_id,
        type: "1",
        wbsId: wbsId.value,
    });
    leftTreeData.value = getArrValue(data);
    leftLoading.value = false;
};

//切换wbs树
const isDisabled = ref(false);
const wbsChange = () => {
    getLeftTreeData();
};

//获取右边数据
const rightLoading = ref(false);
const rightTreeData = ref([]);
const getRightTreeApi = async () => {
    if (isNullES(wbsId.value)) return;
    rightLoading.value = true;
    const form = getObjValue(formModel.value);
    const { data } = await mainApi.findProjectTree({
        projectId: form.id,
        wbsId: wbsId.value,
    });
    rightTreeData.value = getArrValue(data);
    rightLoading.value = false;
};

//默认全部引用
const allChecked = ref(false);
const checkChang = () => {
    setCheckTreeChange();
};

//左边树被展开
const rightExpands = ref([]);
const nodeLeftTreeExpand = (data) => {
    rightExpands.value = rightExpands.value.concat([data.id]);
};

//左边树复选框被点击
const leftNum = ref(0);
const checkLeftTreeChange = () => {
    const e = leftTreeRef.value;
    let checkNum = e.getCheckedKeys().length;
    let halfNum = e.getHalfCheckedKeys().length;
    leftNum.value = checkNum + halfNum;
};

//右边树复选框被点击
const rightNum = ref(0);
const checkRightTreeChange = () => {
    const e = rightTreeRef.value;
    let checkNum = e.getCheckedKeys().length;
    let halfNum = e.getHalfCheckedKeys().length;
    rightNum.value = checkNum + halfNum;
};

//左边树新增到右边
const addTreeClick = () => {
    const left = leftTreeRef.value,
        right = rightTreeRef.value;
    if (rightTreeData.value.length <= 0) {
        //直接把左边勾选的树复制到右侧
        let allTree = JSON.parse(JSON.stringify(leftTreeData.value));
        const halfKeys = left.getHalfCheckedKeys();
        const keys = left.getCheckedKeys().concat(halfKeys);
        getRightTree(allTree, keys);
        console.log(allTree, "allTree");

        rightTreeData.value = allTree;
    } else {
        //只增加右侧树没有的节点，不会覆盖右侧树多余的节点
        let checkNodes = left.getCheckedNodes(false, true);
        let rIdMap = new Map();
        checkNodes.forEach((data) => {
            rIdMap.set(data.id, data);
        });

        let lIdSet = new Set();
        getRightTreeData(lIdSet, rightTreeData.value);

        //在右侧id减去左侧有的id，剩下的就是新增的id
        lIdSet.forEach((id) => {
            rIdMap.delete(id);
        });

        let addMap = new Map();
        rIdMap.forEach((data) => {
            if (data.parentId !== "0" && data.parentId !== 0) {
                //在左侧树能找到父节点的，新增
                let lNode = right.getNode(data.parentId);
                if (lNode) addMap.set(data, lNode.data.id);
            }
        });

        //把半选和选中的数组key合并
        const halfKeys = left.getHalfCheckedKeys();
        const keys = left.getCheckedKeys().concat(halfKeys);
        const myArray = Array.from(addMap.keys());
        let myright = deepClone(myArray);
        getRightTree(myright, keys);
        myright.forEach((data) => {
            right.append(data, data.parentId);
        });
    }
};

//获取右边树
const getRightTree = (arr, keys) => {
    //对比所有的node和选中的key
    for (let i = arr.length - 1; i >= 0; i--) {
        let isIn = false;
        for (let j = keys.length - 1; j >= 0; j--) {
            if (keys[j] === arr[i].id) {
                isIn = true;
                //已经匹配到的key移除，节省性能
                keys.splice(j, 1);
                break;
            }
        }
        if (isIn) {
            //包含在选中的节点，如果有childer继续递归判断
            if (arr[i].children && arr[i].children.length) {
                getRightTree(arr[i].children, keys);
            }
        } else {
            //不包含在选中key的node删除
            arr.splice(i, 1);
        }
    }
};

const getRightTreeData = (set, arr) => {
    arr.forEach((data) => {
        set.add(data.id);
        if (data.children && data.children.length) {
            getRightTreeData(set, data.children);
        }
    });
};

//右边树移除
const delTreeClick = () => {
    const left = leftTreeRef.value,
        right = rightTreeRef.value;
    let delNodes = right.getCheckedNodes();
    //只把选中的节点移除
    delNodes.forEach((node) => {
        right.remove(node);
        left.setChecked(node.id, false);
    });
    checkLeftTreeChange();
    checkRightTreeChange();
};

const setRightTree = () => {
    let ids = [];
    const data = rightTreeData.value;
    for (let i = 0; i < data.length; i++) {
        getLeafIds(ids, data[i]);
    }
    //在左边把右边的节点勾选上
    const e = leftTreeRef.value;
    nextTick(() => {
        e.setCheckedKeys(ids, true);
    });
};

const getLeafIds = (ids, data) => {
    if (data.children && data.children.length) {
        for (let i = 0; i < data.children.length; i++) {
            getLeafIds(ids, data.children[i]);
        }
    } else {
        ids.push(data.id);
    }
};

const getTreeAllId = async (name) => {
    let tree;
    if (name === "left") {
        tree = leftTreeRef.value;
    } else if (name === "right") {
        tree = rightTreeRef.value;
    }
    if (allChecked.value) {
        tree = leftTreeRef.value;
    }
    let ids = [];
    for (let i = 0; i < tree.data.length; i++) {
        await getIds(ids, tree.data[i]);
    }
    return ids.join(",");
};

const getIds = async (ids, data) => {
    ids.push(data.id);
    if (data.children && data.children.length) {
        for (let i = 0; i < data.children.length; i++) {
            await getIds(ids, data.children[i]);
        }
    }
};

const setCheckTreeChange = () => {
    console.log("默认全部启用");
};

const getTreeObj = async () => {
    const form = getObjValue(formModel.value);
    const ids = await getTreeAllId("right");
    return {
        wbsId: wbsId.value,
        projectId: form.id,
        wbsType: "4",
        wbsTreeIds: ids,
    };
};

defineExpose({
    getTreeObj,
});
</script>

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