<template>
    <a-spin :spinning="spinning" tip="请稍后...">
        <div class="page-bg-wrap">
            <div class="geg-flow-page">
                <div class="top-toolbar">
                    <a-space :size="10" wrap>
                        <a-button style="margin-right: 10px" @click="close">
                            <slot name="icon">
                                <close-outlined />
                            </slot>
                            关闭
                        </a-button>
                        <template v-for="(btn, index) in buttonMap.normal">
                            <a-button @click="onClickBtn(btn)" :type="btn.buttonCode === ApproveCode.AGREE ? 'primary' : ''">
                                <slot name="icon" v-if="btn.buttonCode === ApproveCode.AGREE">
                                    <check-circle-outlined />
                                </slot>
                                <slot name="icon" v-if="btn.buttonCode === ApproveCode.REJECT">
                                    <stop-outlined />
                                </slot>
                                {{ btn.buttonName }}
                            </a-button>
                        </template>
                        <template v-for="(btnGroup, btnGroupKey) in buttonMap">
                            <a-dropdown v-if="btnGroupKey !== 'normal' && btnGroup.length">
                                <template #overlay>
                                    <a-menu>
                                        <a-menu-item v-for="(btn, index) in btnGroup" :key="btn.buttonCode" @click="onClickBtn(btn)">
                                            {{ btn.buttonName }}
                                        </a-menu-item>
                                    </a-menu>
                                </template>
                                <a-button>
                                    {{ btnGroupKey }}
                                    <down-outlined />
                                </a-button>
                            </a-dropdown>
                        </template>
                    </a-space>
                </div>
                <FormInformation
                    :key="renderKey"
                    ref="formInformation"
                    :disabled="readonly"
                    :formAssignmentData="data.formAssignmentData"
                    :formInfos="data.formInfos"
                    :opinions="data.opinions"
                    :opinionsComponents="data.opinionsComponents"
                    @get-form-configs="(config) => (formConfigs = config)"
                />
                <Title :font-size="18" default-value="流转信息"></Title>
                <flow-history :items="getTaskRecords()"></flow-history>
                <opinion-dialog ref="opinionDlg" />
                <transfer-dialog ref="transferDlg" />
                <a-modal :closable="false" v-if="showFlowChart" visible="true" centered class="geg" title="流程图" width="1200px" @cancel="closeFlowChart">
                    <process-information :process-id="processId" :xml="data.xml" :currentTaskInfo="data.currentTaskInfo" :currentTaskAssigneeNames="data.currentTaskAssigneeNames" :currentTaskAssignees="data.currentTaskAssignees" />
                    <template #footer>
                        <a-button type="primary" @click="closeFlowChart">关闭</a-button>
                    </template>
                </a-modal>
                <a-modal :closable="false" v-if="showRecord" visible="true" centered class="geg" title="流程记录" width="1200px" @cancel="closeFlowRecord">
                    <div class="flow-record-box">
                        <FlowRecord :list="data.taskRecords" :processId="processId" />
                    </div>
                    <template #footer>
                        <a-button type="primary" @click="closeFlowRecord">关闭</a-button>
                    </template>
                </a-modal>
                <SelectUserV2 ref="selectUser" v-model:value="addStepUser" @change="changeAddStepUser" just-dialog title="加签减签" />
            </div>
        </div>
    </a-spin>
</template>

<script setup>
    import { useRouter } from 'vue-router';
    import { onMounted, reactive, ref, unref, createVNode, provide } from 'vue';
    import FormInformation from '/@/views/secondDev/FormInformation.vue';
    import userTaskItem from '/@/views/workflow/task/hooks/userTaskItem';
    import { getApprovalProcess, postApproval, postGetNextTaskMaybeArrival, postTransfer, getDrawNode, withdraw } from '/@/api/workflow/task';
    import { ApproveCode, ApproveType, ButtonType } from '/@/enums/workflowEnum';
    import { CheckCircleOutlined, StopOutlined, CloseOutlined, DownOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
    import OpinionDialog from '/@/components/SecondDev/OpinionDialog.vue';
    import TransferDialog from '/@/components/SecondDev/TransferDialog.vue';
    import SelectUserV2 from '/@/components/Form/src/components/SelectUserV2.vue';
    import { separator } from '/@bpmn/config/info';
    import { useMultipleTabStore } from '/@/store/modules/multipleTab';
    import Title from '/@/components/Title/src/Title.vue';
    import FlowHistory from '/@/components/SecondDev/FlowHistory.vue';
    import { message, Modal } from 'ant-design-vue';
    import useEventBus from '/@/hooks/event/useEventBus';
    import ProcessInformation from '/@/views/workflow/task/components/flow/ProcessInformation.vue';
    import { useI18n } from '/@/hooks/web/useI18n';
    import { useMessage } from '/@/hooks/web/useMessage';
    import { useUserStore } from '/@/store/modules/user';
    import { deleteDraft, postDraft, putDraft, getDraftInfo } from '/@/api/workflow/process';
    import { TaskTypeUrl } from '/@/enums/workflowEnum';
    import { postSetSign, postSetSignV2 } from '/@/api/workflow/task';
    import FlowRecord from '/@/views/workflow/task/components/flow/FlowRecord.vue';

    const spinning = ref(false);
    const userStore = useUserStore();
    const { t } = useI18n();
    const { notification } = useMessage();

    const { data, approveUserData, initProcessData, notificationError, notificationSuccess } = userTaskItem();
    const { bus, FLOW_PROCESSED } = useEventBus();

    const tabStore = useMultipleTabStore();
    const router = useRouter();
    const currentRoute = router.currentRoute.value;
    const fullPath = currentRoute.fullPath;
    const rQuery = currentRoute.query;
    const rParams = currentRoute.params;
    const schemaId = ref(rParams.arg1);
    const taskId = ref(rQuery.taskId);
    const processId = ref(rParams.arg2);
    const readonly = ref(!!rQuery.readonly); // 查看流程会触发只读模式
    const rDraftsId = ref(rQuery.draftId || '');
    const renderKey = ref('');
    const formConfigs = ref();
    const opinionDlg = ref();
    const transferDlg = ref();
    const validateSuccess = ref(false);
    const formInformation = ref();
    const selectUser = ref();
    const addStepUser = ref('');
    const lastAddStepUser = ref('');
    const hasBtnAddStep = ref(false);
    const hasBtnTransfer = ref(false);
    const showFlowChart = ref(false);
    const showRecord = ref(false);
    const hasBtnApprove = ref(false);
    const hasBtnDisagree = ref(false);
    const hasBtnReject = ref(false);
    const hasBtnFinish = ref(false);
    const hasBtnDraft = ref(false);
    const approveBtnName = ref('同意');
    const transferBtnName = ref('转办');
    const addStepBtnName = ref('会签');
    const finishBtnName = ref('终止');
    const rejectBtnName = ref('拒绝');
    const drawBackBtnName = ref('撤回');
    const draftBtnName = ref('暂存');
    const disagreeBtnName = ref('不同意');
    const buttonMap = ref({
        normal: []
    });
    let draftData = {};
    const drawNode = ref('');
    const props = defineProps({
        rowKeyData: {
            type: String
        }
    });
    const processInfo = ref();
    provide('processInfo', processInfo);

    let approvalData = reactive({
        isCountersign: false,
        isAddOrSubSign: false,
        isEnd: false,
        stampInfo: {
            stampId: '',
            password: ''
        },
        buttonConfigs: [],
        approvedType: ApproveType.AGREE,
        approvedResult: ApproveCode.AGREE,
        approvedContent: '',
        rejectNodeActivityId: '',
        rejectNodeActivityIds: [],
        circulateConfigs: [],
        nextTaskUser: {} // 格式为taskKey: 用户id（逗号分隔）
    });
    let approvedType = ref(ApproveType.AGREE);

    function showButton(btn) {
        // 撤回有drawNode才显示，流程图任何情况下都显示
        let show =
            (btn.checked && ((!readonly.value && btn.buttonCode !== ApproveCode.DRAWBACK) || (readonly.value && btn.buttonCode === ApproveCode.DRAWBACK && drawNode.value))) ||
            btn.buttonCode === ApproveCode.FLOWBPMN ||
            btn.buttonCode === ApproveCode.FLOWRECORD;
        return show;
    }

    function onClickBtn(btn) {
        const key = btn.buttonCode;
        if (btn.buttonType === ButtonType.DEFAULT) {
            let funName = `handle${key}`;
            methods[funName](btn);
        } else if (btn.buttonType === ButtonType.SCRIPT) {
            handleFunction(btn);
        }
    }
    function onMoreClick(e) {
        const key = e.key;
        if (btn.buttonType === ButtonType.DEFAULT) {
            let funName = `handle${key}`;
            methods[funName](btn);
        } else if (btn.buttonType === ButtonType.SCRIPT) {
            handleFunction(btn);
        }
    }

    function handleFunction(btn) {
        // eval(script)
        if (btn.handleFuncName) {
            formInformation.value?.handleInnerFun(btn.handleFuncName);
        }
    }

    const methods = {
        handlesetDraft() {
            setDraft();
        },
        handledraft() {
            saveDraft();
        },
        handleaddStep() {
            selectUser.value.show();
        },
        handledrawBack() {
            Modal.confirm({
                title: t('提示'),
                icon: createVNode(ExclamationCircleOutlined),
                content: t('请确认是否撤回该流程？'),
                okText: t('确定'),
                okType: 'danger',
                cancelText: t('取消'),
                onOk() {
                    openSpinning();
                    withdraw(processId.value, drawNode.value)
                        .then((res) => {
                            if (res) {
                                notification.open({
                                    type: 'success',
                                    message: t('撤回'),
                                    description: t('撤回成功')
                                });
                            } else {
                                notification.open({
                                    type: 'error',
                                    message: t('撤回'),
                                    description: t('撤回失败')
                                });
                            }
                        })
                        .finally(() => {
                            closeSpinning();
                        });
                },
                onCancel() {}
            });
        },
        handlefinish(btn) {
            Modal.confirm({
                title: () => '提示',
                content: () => `确定${btn.buttonName}吗？`,
                onOk: () => {
                    onFinishClick();
                }
            });
        },
        handleflowBpmn() {
            showFlowChart.value = true;
        },
        handletransfer() {
            onTransferClick();
        },
        handleagree() {
            onApproveClick();
        },
        handledisagree() {
            onDisagreeClick();
        },
        handlereject() {
            onDenyClick();
        },
        handleflowRecord() {
            showRecord.value = true;
        }
    };

    function closeFlowChart() {
        showFlowChart.value = false;
    }

    function closeFlowRecord() {
        showRecord.value = false;
    }

    function close() {
        tabStore.closeTab(currentRoute, router);
        if (window?.isOnlyShowContent == 'Y') {
            window.close();
        }
    }
    async function setDraft(needModal = true) {
        let formData = [];
        let params = {
            taskId: taskId.value,
            userId: userStore.getUserInfo.id
        };
        let res = await getDraftInfo('', taskId.value, userStore.getUserInfo.id);
        if (res) {
            draftData = JSON.parse(res.formData);
            rDraftsId.value = res.id;
            if (!needModal) return;
            Modal.confirm({
                title: () => '提示',
                content: () => '确认使用草稿覆盖当前数据？',
                onOk: async () => {
                    data.formInfos.forEach((item) => {
                        if (draftData && item.formConfig && item.formConfig.key && draftData[item.formConfig.key]) {
                            formData.push(item.formConfig.key ? draftData[item.formConfig.key] : {});
                        }
                    });
                    await formInformation.value.setFormData(formData);
                }
            });
        }
    }
    async function saveDraft() {
        try {
            spinning.value = true;
            let formModels = await formInformation.value.saveDraftData();
            if (rDraftsId.value) {
                let res = await putDraft(schemaId.value, formModels, rDraftsId.value, props.rowKeyData, processId.value, taskId.value);
                showResult(res, '保存草稿');
            } else {
                let res = await postDraft(schemaId.value, formModels, props.rowKeyData, processId.value, taskId.value);
                showResult(res, '保存草稿');
            }
            setDraft(false);
            spinning.value = false;
        } catch (error) {
            spinning.value = false;
            notificationError('保存草稿');
        }
    }
    function showResult(res, title) {
        if (res) {
            notificationSuccess(title);
        } else {
            notificationError(title);
        }
    }
    async function changeAddStepUser(ids, memberList) {
        try {
            spinning.value = true;
            let idList = memberList.map((item) => {
                return item.id;
            });
            let lastIdList = lastAddStepUser.value.split(',');
            let addUserIds = idList.filter((item) => {
                return lastIdList.indexOf(item) == -1;
            });
            let subUserIds = lastIdList.filter((item) => {
                return idList.indexOf(item) == -1;
            });
            let data = {
                addUserIds,
                subUserIds,
                schemaId: schemaId.value,
                taskId: taskId.value
            };
            await postSetSignV2(data);
            let res = await getApprovalProcess(unref(taskId), unref(processId));
            initProcessData(res);
            spinning.value = false;
            message.success('操作成功');
        } catch (e) {
            message.error(e);
            spinning.value = false;
            message.error('操作失败，请稍后再试');
        }
    }

    async function onApproveClick(isAutoAgreeBreak = false) {
        try {
            openSpinning();
            if (!isAutoAgreeBreak) {
                await submit();
            }
            if (!validateSuccess.value) {
                closeSpinning();
                return;
            }
            const params = await getApproveParams();
            const nextNodes = await postGetNextTaskMaybeArrival(params);
            approvalData.approvedType = ApproveType.AGREE;
            approvalData.approvedResult = ApproveCode.AGREE;
            //如果是自动同意触发的，关闭弹层的loading
            if (isAutoAgreeBreak) {
                opinionDlg.value.stopLoading();
            }
            closeSpinning();
            opinionDlg.value.toggleDialog({
                action: 'agree',
                nextNodes,
                callback: (args) => {
                    approvalData.approvedContent = args.opinion;
                    approvalData.nextTaskUser = args.nextTaskUser;
                    approvalData.isEnd = args.isEnd;
                    onFinish('approve');
                }
            });
        } catch (e) {
            console.error(e);
            closeSpinning();
            throw new Error(e);
        }
    }

    async function onDisagreeClick() {
        try {
            openSpinning();
            await submit();
            if (!validateSuccess.value) {
                closeSpinning();
                return;
            }
            const params = await getApproveParams();
            const nextNodes = await postGetNextTaskMaybeArrival(params);
            approvalData.approvedType = ApproveType.DISAGREE;
            approvalData.approvedResult = ApproveCode.DISAGREE;
            closeSpinning();
            opinionDlg.value.toggleDialog({
                action: 'disagree',
                nextNodes,
                callback: (args) => {
                    approvalData.approvedContent = args.opinion;
                    onFinish('disagree');
                }
            });
        } catch (e) {
            console.error(e);
            closeSpinning();
            throw new Error(e);
        }
    }

    async function onDenyClick() {
        approvalData.approvedType = ApproveType.REJECT;
        approvalData.approvedResult = ApproveCode.REJECT;
        opinionDlg.value.toggleDialog({
            action: 'reject',
            processId: processId.value,
            taskId: taskId.value,
            callback: (args) => {
                approvalData.approvedContent = args.opinion;
                approvalData.rejectNodeActivityId = args.rejectNodeId;
                approvalData.nextTaskUser = args.nextTaskUser;
                onFinish('reject');
            }
        });
    }

    function onTransferClick() {
        transferDlg.value.toggleDialog({
            taskId: taskId.value,
            callback: (args) => {
                onTransfer(args);
            }
        });
    }

    function onTransfer({ taskId, userId }) {
        transferDlg.value.validate().then(() => {
            transferDlg.value.startLoading();
            postTransfer(taskId, userId)
                .then((res) => {
                    transferDlg.value.toggleDialog({
                        isClose: true
                    });
                    message.success('转办成功');
                    setTimeout(() => {
                        bus.emit(FLOW_PROCESSED);
                        close();
                    }, 500);
                })
                .catch((err) => {
                    message.error('转办失败');
                    transferDlg.value.toggleDialog({
                        isClose: true
                    });
                });
        });
    }

    function onTransferFlowFail() {
        transferDlg.value.stopLoading();
    }

    async function onFinishClick() {
        approvalData.approvedType = ApproveType.FINISH;
        approvalData.approvedResult = ApproveCode.FINISH;
        onFinish('finish');
    }

    function flowSuccess() {
        opinionDlg.value.toggleDialog({
            isClose: true
        });
        message.success('操作成功');
        setTimeout(() => {
            bus.emit(FLOW_PROCESSED);
            close();
        }, 500);
    }

    function flowFail() {
        opinionDlg.value.stopLoading();
    }

    function reset() {
        approvalData.isAddOrSubSign = false;
        approvalData.stampInfo = {
            stampId: '',
            password: ''
        };
        approvalData.buttonConfigs = [];
        approvalData.approvedType = ApproveType.AGREE;
        approvalData.approvedContent = '';
        approvalData.rejectNodeActivityId = '';
        approvalData.rejectNodeActivityIds = [];
        approvalData.circulateConfigs = [];
    }

    function setBtnStatus() {
        const btnConfigs = approvalData.buttonConfigs;
        let draftBtn = btnConfigs.find((item) => item.buttonCode === ApproveCode.DRAFT);
        if (draftBtn && rDraftsId.value) {
            btnConfigs.push({
                ...draftBtn,
                buttonName: t('从草稿导入'),
                buttonCode: 'setDraft',
                approveType: ApproveType.DRAFT,
                index: 1
            });
        }
        btnConfigs.forEach((btn) => {
            const index = btn.index;
            const buttonGroup = btn?.buttonGroup;
            if (buttonGroup) {
                if (!buttonMap.value[buttonGroup]) {
                    buttonMap.value[buttonGroup] = [];
                }
                if (showButton(btn)) {
                    buttonMap.value[buttonGroup].push(btn);
                }
            } else {
                if (showButton(btn)) {
                    buttonMap.value['normal'].push(btn);
                }
            }
            for (let key in buttonMap.value) {
                buttonMap.value[key].sort((a, b) => {
                    let aIndex = a?.index || 0;
                    let bIndex = b?.index || 0;
                    return aIndex - bIndex;
                });
            }
        });
    }

    function getTaskRecords() {
        if (data?.taskApproveOpinions?.length) {
            return data.taskApproveOpinions || [];
        }
    }

    onMounted(async () => {
        try {
            let res = await getApprovalProcess(unref(taskId), unref(processId));
            initProcessData(res);
            await getBackNode();
            processInfo.value = res;
            const title = res?.schemaInfo?.name;
            if (title) {
                const tabPrefix = readonly.value ? '查看' : '审批';
                tabStore.changeTitle(fullPath, `${tabPrefix}：${title}`);
            }
            if (taskId.value) {
                let ids = '';
                res.currentTaskAssignees[res.taskInfo.taskDefinitionKey].forEach((item, index) => {
                    ids = `${ids}${index == 0 ? '' : ','}${item.assigneeIdStr}`;
                });
                addStepUser.value = ids;
                lastAddStepUser.value = ids;
            }
            if (res.buttonConfigs) {
                approvalData.buttonConfigs = res.buttonConfigs;
                setBtnStatus();
            }
            if (!readonly.value) {
                if (res.relationTasks) {
                    data.predecessorTasks = res.relationTasks;
                }
                if (res.isAddOrSubSign) {
                    approvalData.isAddOrSubSign = res.isAddOrSubSign;
                }

                approvalData.approvedType = ApproveType.AGREE;
                approvedType.value = ApproveType.AGREE;
                approvalData.approvedContent = '';
                approvalData.rejectNodeActivityId = '';
                approvalData.rejectNodeActivityIds = [];
                approvalData.circulateConfigs = [];
            }
            renderKey.value = Math.random() + '';
            setDraft();
        } catch (error) {}
    });

    async function getBackNode() {
        await getDrawNode(processId.value).then((res) => {
            if (res.length) {
                drawNode.value = res[0].activityId;
            } else {
                drawNode.value = '';
            }
        });
    }

    async function submit() {
        data.submitLoading = true;
        validateSuccess.value = false;
        try {
            let validateForms = await formInformation.value.validateForm();
            if (validateForms.length > 0) {
                let successValidate = validateForms.filter((ele) => {
                    return ele.validate;
                });
                if (successValidate.length == validateForms.length) {
                    validateSuccess.value = true;
                    data.submitLoading = false;
                } else {
                    data.submitLoading = false;
                    notificationError(t('审批流程'), t('表单校验未通过'));
                }
            }
        } catch (error) {
            data.submitLoading = false;
            notificationError(t('审批流程'), t('审批流程失败'));
        }
    }

    function getUploadFileFolderIds(formModels) {
        let fileFolderIds = [];
        let uploadComponentIds = formInformation.value.getUploadComponentIds();
        uploadComponentIds.forEach((ids) => {
            if (ids.includes(separator)) {
                let arr = ids.split(separator);
                if (arr.length == 2 && formModels[arr[0]][arr[1]]) {
                    fileFolderIds.push(formModels[arr[0]][arr[1]]);
                } else if (arr.length == 3 && formModels[arr[0]][arr[1]] && Array.isArray(formModels[arr[0]][arr[1]])) {
                    formModels[arr[0]][arr[1]].forEach((o) => {
                        fileFolderIds.push(o[arr[2]]);
                    });
                }
            }
        });
        return fileFolderIds;
    }

    async function getApproveParams() {
        try {
            let formModels = await formInformation.value.getFormModels();
            let system = formInformation.value.getSystemType();
            let fileFolderIds = getUploadFileFolderIds(formModels);
            return {
                approvedType: approvalData.approvedType,
                approvedResult: approvalData.approvedResult, // approvalData.approvedType 审批结果 如果为 4 就需要传buttonCode
                approvedContent: approvalData.approvedContent,
                formData: formModels,
                rejectNodeActivityId: approvalData.rejectNodeActivityId,
                taskId: taskId.value,
                fileFolderIds,
                circulateConfigs: approvalData.circulateConfigs,
                /*stampId: values.stampId,
                stampPassword: values.password,*/
                isOldSystem: system,
                isEnd: approvalData.isEnd,
                nextTaskUser: approvalData.nextTaskUser
            };
        } catch (e) {
            console.error(e);
        }
    }

    async function onFinish(values) {
        try {
            if (validateSuccess.value || values === 'reject' || values === 'finish' || values === 'disagree') {
                let params = await getApproveParams();
                let response = await postApproval(params);
                // 判断返回值是否带有isAutoAgree 来判断中间是否有自动审批的业务，如有再执行判断待审人员是否包含自己，不包含就直接flowSuccess
                if (checkIsAutoAgree(response)) return;
                flowSuccess();
                data.submitLoading = false;
            }
        } catch (error) {
            flowFail();
            throw new Error(error);
        }
    }

    /**
     * 判断该次审核是否触发自动同意事务，并且检验返回得task 是否是自身作为被审需要弹框再次审核
     * @param response
     */
    function checkIsAutoAgree(response) {
        if (
            response != null &&
            response.length != 0 &&
            response[0].isAutoAgree == true && //
            response[0].approveUserIds.includes(userStore.getUserInfo.id)
        ) {
            // 注入新得taskId
            taskId.value = response[0].taskId;
            data.submitLoading = false;
            onApproveClick(true);
            return true;
        } else {
            return false;
        }
    }

    function openSpinning() {
        spinning.value = true;
    }
    function closeSpinning() {
        spinning.value = false;
    }
</script>

<style lang="less" scoped>
    .flow-record-box {
        height: 500px;
        overflow: auto;
    }
</style>
