<template>
    <a-modal :mask-closable="false" :title="dialogTitle" :visible="isOpen" :width="500" centered class="geg" @cancel="onClickCancel">
        <template #footer>
            <a-button :disabled="loading" @click="onClickCancel">取消</a-button>
            <a-button :loading="loading" type="primary" @click="onClickOK">确定</a-button>
        </template>
        <div class="dialog-wrap">
            <a-form :label-col="{ span: 6 }" :model="formState" autocomplete="off">
                <a-form-item v-if="_action === 'agree'" label="下一节点" name="nextNodeName">
                    <span>{{ getNextNodesName() }}</span>
                </a-form-item>
                <template v-for="node in flowNextNodes" :key="node.activityId">
                    <div v-if="flowNextNodes.length > 1" class="node-info">
                        <span class="node-label">{{ node.nodeTypeLabel }}</span>
                        <span class="node-name">{{node.activityName}}</span>
                        <a-switch :checked="node.chooseNode" v-if="!node.hiddenNode" style="margin-left: 10px;" @change="agreeNodeChange(node)"></a-switch>
                    </div>
                    <a-form-item :required="(flowNextNodes.length === 1 || node.chooseNode)" v-if="_action === 'agree' && !isEnd" :label="'审批人'">
                        <a-select v-show="node.chooseAssign" v-model:value="node.assignees" :options="node.nextAssignees" :disabled="loading"
                                :placeholder="'审批人'" max-tag-count="responsive"
                                :mode="node.isChooseMulti? 'multiple' : ''"
                                :filterOption="search"
                        ></a-select>
                        <span v-show="!node.chooseAssign">{{ getAssigneeText(node) }}</span>
                    </a-form-item>
                </template>

                <a-form-item v-if="_action === 'reject'" label="退回至" name="rejectNode">
                    <a-select v-model:value="rejectNodeId" :disabled="loading">
                        <a-select-option v-for="(item, index) in rejectNodeList" :key="index" :value="item.activityId">{{ item.activityName }}</a-select-option>
                    </a-select>
                </a-form-item>
                <template v-for="node in rejectNodeList">
                    <a-form-item v-if="_action === 'reject'&&rejectNodeId===node.activityId" label="审批人">
                        <a-select v-show="node.chooseAssign" v-model:value="node.assignees" :options="node.nextAssignees" :disabled="loading"
                                  :placeholder="'请选择' + node.activityName + '的审批人'" max-tag-count="responsive" mode="multiple"
                                  :filterOption="search"
                        ></a-select>
                        <span v-show="!node.chooseAssign">{{ getAssigneeText(node) }}</span>
                    </a-form-item>
                </template>

                <a-form-item label="审批意见" name="opinion">
                    <a-textarea v-model:value="formState.opinion" :disabled="loading" :maxlength="200" :rows="3" placeholder="请输入审批意见，不超过200字" />
                </a-form-item>
            </a-form>
        </div>
    </a-modal>
</template>

<script setup>
    import { reactive, ref } from 'vue';
    import { getRejectNodeList } from '/@/api/workflow/task';
    import { message } from 'ant-design-vue';

    const dialogTitle = ref('审批');
    const isOpen = ref(false);
    const rejectNodeList = ref([]);
    const rejectNodeId = ref('');
    const loading = ref(false);
    const isEnd = ref(false);

    let _action = ref('agree');
    let _processId = '';
    let _taskId = '';
    let flowNextNodes = ref([]);
    let _callback = null;
    let _onCancel = null;

    const formState = reactive({
        opinion: '',
        opinionList: ['同意。', '请领导审批。']
    });

    function getAssigneeText(node) {
        // 注意这里用的是下拉框的数据结构 所以字段是value和label
        return (node.nextAssignees || [])
            .filter((item) => node.assignees.includes(item.value))
            .map((item) => item.label)
            .join('、');
    }

    function getNextNodesName() {
        return flowNextNodes.value.length > 1 ? '多个节点，请选择流向节点' : flowNextNodes?.value[0]?.activityName;
    }

    function toggleDialog({ isClose, action, callback, rejectCancel, processId, taskId, nextNodes } = {}) {
        if (isClose) {
            isOpen.value = false;
            loading.value = false;
            return;
        }
        isOpen.value = true;
        _action.value = action;
        _callback = callback;
        _onCancel = rejectCancel;
        _processId = processId;
        _taskId = taskId;
        flowNextNodes.value = nextNodes;
        formState.opinion = '';
        dialogTitle.value = `审批`;
        if (nextNodes && nextNodes.length) {
            // 下一个节点唯一时（可能有并行节点）
            const nNode = nextNodes[0];
            //formState.nextNodeName = nNode.activityName;
            isEnd.value = nNode.isEnd;
            const typeCount = nextNodes.length <= 1 ? nextNodes.length : (new Set(nextNodes.map(nNode => nNode.nodeType))).size;
            nextNodes.forEach((nNode) => {
                if (!nNode.userList?.length) {
                    return;
                }
                const selected = [];
                nNode.nextAssignees = nNode.userList.map((item) => {
                    if (item.checked || nNode.userList.length === 1) {
                        // 只有一个人的时候必须选他
                        selected.push(item['F_UserId']);
                    }
                    return {
                        value: item['F_UserId'],
                        label: item['F_RealName'],
                        item:item
                    };
                });
                nNode.assignees = selected;
                if (!nNode.chooseAssign) {
                    // 不需要选审批人的时候 所有备选人都要放到下个节点
                    nNode.assignees = nNode.userList.map((item) => item['F_UserId']);
                }
                nNode.chooseAssign = nNode.chooseAssign;

                if (nNode.nodeType === 'commitToNode') {
                    nNode.nodeTypeLabel = '提交到退回节点:';
                }
                if (nextNodes.length>1 && nNode.nodeType === 'common') {
                    nNode.nodeTypeLabel = '并行节点:';
                }
                // 如果是必选并行节点 或者 只有一个节点，默认选中
                if (nNode.isChooseParallel || nextNodes.length == 1) {
                    nNode.chooseNode = true;
                    if (typeCount == 1) {
                        // 如果只有一个节点类型的，默认隐藏
                        nNode.hiddenNode = true;
                    } else {
                        nNode.hiddenNode = false;
                    }
                }
            });
            flowNextNodes.value = nextNodes;
        }
        if (action === 'reject') {
            loadRejectNodeList();
        }
    }

    function agreeNodeChange(node) {
        if (node.chooseNode) {
            // 如果是必选并行节点，取消选择时，警告并返回
            if (node.isChooseParallel) {
                return message.warning('并行节点必选，不能取消选择');
            }
            node.chooseNode = false;
            // 遍历节点，如果不是common类型都是false了，需要遍历common类型中必填节点是否都是true
            const sumNotCommonNode = flowNextNodes.value.filter((nNode) => nNode.nodeType != 'common' && nNode.chooseNode).length;
            if (sumNotCommonNode === 0) {
                // 如果没有非common类型的节点被选中，则将遍历common类型的节点,必填节点设置为true
                flowNextNodes.value.forEach((nNode) => {
                    if (nNode.nodeType === 'common' && nNode.isChooseParallel) {
                        nNode.chooseNode = true;
                    }
                });
            }
        } else if (!node.chooseNode) {
            node.chooseNode = true;
            // 遍历节点，取消与自己不同类型的节点的选择
            flowNextNodes.value.forEach((nNode) => {
                if (nNode.nodeType != node.nodeType) {
                    nNode.chooseNode = false;
                }
            });
            if (node.nodeType === 'common') {
                // 如果是common类型的节点，遍历所有common类型的节点，必填节点设置为true
                flowNextNodes.value.forEach((nNode) => {
                    if (nNode.nodeType === 'common' && nNode.isChooseParallel) {
                        nNode.chooseNode = true;
                    }
                });
            }
        }

    }

    function search(inputValue, option){
        return inputValue?(option.item.F_Account.indexOf(inputValue)>-1||option.item.F_RealName.indexOf(inputValue)>-1):true;
    }

    async function loadRejectNodeList() {
        rejectNodeId.value='';
        let res = await getRejectNodeList(_processId, _taskId);
        if (res && Array.isArray(res) && res.length > 0) {
            rejectNodeList.value = res;
            dialogTitle.value = `退回`;
            if (res?.length) {
                res.forEach((nNode) => {
                    if (!nNode.userList?.length) {
                        return;
                    }
                    const selected = [];
                    nNode.nextAssignees = nNode.userList.map((item) => {
                        if (item.checked || nNode.userList.length === 1) {
                            // 只有一个人的时候必须选他
                            selected.push(item['F_UserId']);
                        }
                        return {
                            value: item['F_UserId'],
                            label: item['F_RealName']+(item.remarks?"("+item.remarks+")":""),
                            item:item
                        };
                    });
                    nNode.assignees = selected;
                    if (!nNode.chooseAssign) {
                        // 不需要选审批人的时候 所有备选人都要放到下个节点
                        nNode.assignees = nNode.userList.map((item) => item['F_UserId']);
                    }
                    nNode.chooseAssign = nNode.chooseAssign;
                });
            }
        }
    }

    function onClickOK() {
        const nextTaskUser = {};
        if (_action.value === 'agree' && !isEnd.value) {
            // 如果是同意，并且没有选择节点 报错
            const choose = flowNextNodes.value.find((node) => (node.chooseNode));
            if (!choose) {
                return message.error('请选择下一节点');
            }
            // 调整成选中的节点的被审人员
            const isEmpty = flowNextNodes.value.find((node) => (!node.assignees?.length && node.chooseNode));
            if (isEmpty) {
                return message.error('请选择审批人');
            }
            flowNextNodes.value.filter((node)=>node.chooseNode).forEach((nNode) => {
                nextTaskUser[nNode.activityId] = isEnd.value ? '' : (typeof(nNode.assignees) == 'string' ? nNode.assignees : nNode.assignees.join(','));
            });
        }
        if (_action.value === 'reject') {
            const isChoose = rejectNodeList.value.find((node) => node.activityId==rejectNodeId.value&&node.assignees?.length);
            if (!isChoose) {
                return message.error('请选择审批人');
            }
            rejectNodeList.value.forEach((nNode) => {
                if(nNode.activityId==rejectNodeId.value){
                    nextTaskUser[nNode.activityId] = isEnd.value ? '' : nNode.assignees.join(',');
                }
            });
        }
        if (_callback && typeof _callback === 'function') {
            loading.value = true;
            _callback({
                opinion: formState.opinion,
                rejectNodeId: rejectNodeId.value,
                nextTaskUser,
                isEnd
            });
        } else {
            isOpen.value = false;
        }
    }

    function onClickCancel() {
        if (_onCancel && typeof _onCancel === 'function') {
            _onCancel();
        }
        isOpen.value = false;
    }

    function stopLoading() {
        loading.value = false;
    }

    defineExpose({
        toggleDialog,
        stopLoading
    });
</script>

<style lang="less" scoped>
.dialog-wrap {
    padding: 10px 15px 0 0;
}
.node-info {
    display: block;
    margin: 6px 0;
    line-height: 2;
    padding-left: 0;
}
.node-label {
    display: inline-block;
    min-width: 25%;
    text-align: right;
    padding-right: 8px;
    color: #000;
    vertical-align: top;
}
.node-name {
    display: inline-block;
    flex: none;
    text-align: left;
    color: #333;
    font-weight: 600;
    vertical-align: top;
}
</style>
