<!-- 流程详情页面 tab切换 -->
<template>
    <div class="default-main" style="overflow: hidden">
        <!--返回按钮-->
        <back-component style="margin: 8px; position: absolute; z-index: 10; top: -3px; right: 2px" />
        <el-tabs type="border-card" v-model="tab" @tab-click="handleClickTab">
            <el-tab-pane label="流程审核" name="流程审核" v-if="runningTasks.length > 0">
                <el-card v-loading="processInstanceLoading" class="box-card">
                    <template #header>
                        <span class="el-icon-document">申请信息【{{ processInstance.name }}】</span>
                    </template>
                    <!-- 情况一：流程表单 -->
                    <el-col v-if="processInstance?.processDefinition?.formType === 10" :offset="6" :span="16">
                        <form-create v-model="detailForm.value" v-model:api="fApi" :option="detailForm.option"
                            :rule="detailForm.rule" />
                    </el-col>
                    <!-- 情况二：业务表单 -->
                    <div v-if="processInstance?.processDefinition?.formType === 20">
                        <BusinessFormComponent :id="processInstance.businessKey" :applyTitle="processInstance.name" />
                    </div>
                </el-card>
                <el-card v-for="(item, index) in runningTasks" :key="index" v-loading="processInstanceLoading"
                    class="box-card">
                    <template #header>
                        <span class="el-icon-picture-outline">当前任务【{{ item.name }}】</span>
                    </template>
                    <el-col :offset="6" :span="16">
                        <el-form :ref="'form' + index" :model="auditForms[index]" :rules="auditRule"
                            label-width="100px">
                            <el-form-item v-if="processInstance && processInstance.name" label="流程名">
                                {{ processInstance.name }}
                            </el-form-item>
                            <el-form-item v-if="processInstance && processInstance.startUser" label="发起人">
                                {{ processInstance?.startUser.name }}
                            </el-form-item>
                            <el-form-item v-if="processInstance && processInstance.startUser" label="发起部门">
                                {{ processInstance?.startUser.deptName }}
                            </el-form-item>

                            <el-card  v-if="runningTasks[index].formId != null" style="width: 100%; margin-right: 40%">
                                <template #header>
                                    <span class="el-icon-picture-outline">
                                        {{ runningTasks[index]?.formName }}
                                    </span>
                                </template>
                                <form-create v-model="approveForms[index].value" v-model:api="approveFormFApis[index]"
                                    :option="approveForms[index].option" :rule="approveForms[index].rule" />
                            </el-card>

                            <el-form-item label="审批建议" prop="reason" style="margin-top: 15px">
                                <el-input v-model="auditForms[index].reason" placeholder="请输入审批建议" type="textarea" />
                            </el-form-item>
                            <!--                <el-form-item label='抄送人' prop='copyUserIds'>-->
                            <!--                  <el-select v-model='auditForms[index].copyUserIds' multiple placeholder='请选择抄送人'>-->
                            <!--                    <el-option-->
                            <!--                        v-for='item in userOptions'-->
                            <!--                        :key='item.id'-->
                            <!--                        :label='item.nickname'-->
                            <!--                        :value='item.id'-->
                            <!--                    />-->
                            <!--                  </el-select>-->
                            <!--                </el-form-item>-->
                        </el-form>
                        <div style="margin-bottom: 20px; margin-left: 10%; font-size: 14px">
                            <el-button type="success" :icon="Select" @click="handleAudit(item, true)"
                                :loading="loading">通过</el-button>
                            <el-button type="danger" :icon="Close" @click="handleAudit(item, false)"
                                :loading="loading">不通过</el-button>
                            <!--                <el-button type='primary' @click='openTaskUpdateAssigneeForm(item.id)'>-->
                            <!--                  <Icon icon='ep:edit' />-->
                            <!--                  转办-->
                            <!--                </el-button>-->
                            <!--                <el-button type='primary' @click='handleDelegate(item)'>-->
                            <!--                  <Icon icon='ep:position' />-->
                            <!--                  委派-->
                            <!--                </el-button>-->
                            <!--                <el-button type='primary' @click='handleSign(item)'>-->
                            <!--                  <Icon icon='ep:plus' />-->
                            <!--                  加签-->
                            <!--                </el-button>-->
                            <!--                            <el-button type="warning" :icon="Back" @click="handleBack(item)">回退</el-button>-->
                        </div>
                    </el-col>
                </el-card>

            </el-tab-pane>
            <el-tab-pane label="申请信息" name="申请信息" v-if="runningTasks.length == 0">
                <!-- 申请信息 -->
                <el-card v-loading="processInstanceLoading" class="box-card">
                    <template #header>
                        <span class="el-icon-document">申请信息【{{ processInstance.name }}】</span>
                    </template>
                    <!-- 情况一：流程表单 -->
                    <el-col v-if="processInstance?.processDefinition?.formType === 10" :offset="6" :span="16">
                        <form-create v-model="detailForm.value" v-model:api="fApi" :option="detailForm.option"
                            :rule="detailForm.rule" />
                    </el-col>
                    <!-- 情况二：业务表单 -->
                    <div v-if="processInstance?.processDefinition?.formType === 20">
                        <BusinessFormComponent  :id="processInstance.businessKey" :applyTitle="processInstance.name" />
                    </div>
                </el-card>
            </el-tab-pane>
            <el-tab-pane label="审批记录" name="审批记录">
                <!-- 审批记录 -->
                <ProcessInstanceTaskList :loading="tasksLoad" :process-instance="processInstance" :tasks="tasks"
                    @refresh="getTaskList" />
            </el-tab-pane>
            <el-tab-pane label="流程图" name="流程图">
                <ProcessInstanceBpmnViewer ref="mapRef" :id="`${id}`" :bpmn-xml="bpmnXml"
                    :loading="processInstanceLoading" :process-instance="processInstance" :tasks="tasks" />
            </el-tab-pane>
        </el-tabs>
        <ContentWrap>
            <!-- 弹窗：转派审批人 -->
            <TaskTransferForm ref="taskTransferFormRef" @success="getDetail" />
            <!-- 弹窗：回退节点 -->
            <TaskReturnForm ref="taskReturnFormRef" @success="getDetail" />
            <!-- 弹窗：委派，将任务委派给别人处理，处理完成后，会重新回到原审批人手中-->
            <TaskDelegateForm ref="taskDelegateForm" @success="getDetail" />
            <!-- 弹窗：加签，当前任务审批人为A，向前加签选了一个C，则需要C先审批，然后再是A审批，向后加签B，A审批完，需要B再审批完，才算完成这个任务节点 -->
            <TaskSignCreateForm ref="taskSignCreateFormRef" @success="getDetail" />
        </ContentWrap>
    </div>
</template>
<script lang="ts" setup>
import { onMounted, ref, getCurrentInstance, reactive, watch, unref, nextTick, markRaw } from 'vue'
import { ElMessage } from 'element-plus'
import ContentWrap from '@/components/ContentWrap/src/ContentWrap.vue'
import { setConfAndFields2 } from '@/utils/formCreate'
import type { ApiAttrs } from '@form-create/element-ui/types/config'
import ProcessInstanceBpmnViewer from './ProcessInstanceBpmnViewer.vue'
import ProcessInstanceTaskList from './ProcessInstanceTaskList.vue'
import TaskReturnForm from './dialog/TaskReturnForm.vue'
import TaskDelegateForm from './dialog/TaskDelegateForm.vue'
import TaskTransferForm from './dialog/TaskTransferForm.vue'
import TaskSignCreateForm from './dialog/TaskSignCreateForm.vue'
import { registerComponent } from '@/utils/routerHelper'
import { isEmpty } from '@/utils/is'
import { useRouter, useRoute } from 'vue-router'
import { approveTask, getTaskListByProcessInstanceId, listByProcessInstanceId, rejectTask } from '@/api/bpm-boot/task'
import { getProcessInstanceById } from '@/api/bpm-boot/instance'
import { getProcessDefinitionById } from '@/api/bpm-boot/definition'
import { getUserSimpleList } from '@/api/user-boot/user'
import { Close, Back, Select } from '@element-plus/icons-vue'
import BackComponent from '@/components/icon/back/index.vue'

defineOptions({ name: 'BpmProcessInstanceDetail' })

const { query } = useRoute() // 查询参数
const { proxy } = getCurrentInstance() as any
const states = history.state

const userId = JSON.parse(window.localStorage.getItem('adminInfo')).id // 当前登录的编号
const id = (states.id as unknown as string) || query.id // 流程实例的编号
const historyInstanceId = states.historyInstanceId as unknown as string // 历史流程实例的编号

const todo = states.todo // 是否存在待办事项
const processInstanceLoading = ref(false) // 流程实例的加载中
const processInstance = ref({}) // 流程实例
const bpmnXml = ref('') // BPMN XML
const tasksLoad = ref(true) // 任务的加载中
const loading = ref(false) // 任务的加载中
const tasks = ref<any[]>([]) // 任务列表
// ========== 审批信息 ==========
const runningTasks = ref<any[]>([]) // 运行中的任务
const auditForms = ref<any[]>([]) // 审批任务的表单
const auditRule = reactive({
    reason: [{ required: true, message: '审批建议不能为空', trigger: 'blur' }]
})
const approveForms = ref<any[]>([]) // 审批通过时，额外的补充信息
const approveFormFApis = ref<ApiAttrs[]>([]) // approveForms 的 fAPi

// ========== 申请信息 ==========
const fApi = ref<ApiAttrs>() //
const detailForm = ref({
    rule: [],
    option: {},
    value: {}
}) // 流程实例的表单详情

/** 监听 approveFormFApis，实现它对应的 form-create 初始化后，隐藏掉对应的表单提交按钮 */
watch(
    () => approveFormFApis.value,
    value => {
        value?.forEach(api => {
            api.btn.show(false)
            api.resetBtn.show(false)
        })
    },
    {
        deep: true
    }
)

/** 处理审批通过和不通过的操作 */
const handleAudit = async (task, pass) => {

    loading.value = true
    // 1.1 获得对应表单
    const index = runningTasks.value.indexOf(task)
    const auditFormRef = proxy.$refs['form' + index][0]
    // 1.2 校验表单
    const elForm = unref(auditFormRef)
    
     if (!elForm){
         loading.value = false
         return
    } 
    
    // const valid = await elForm.validate() 
    // if (!valid)
    //     return
      try {
        const valid = await new Promise((resolve) => {
            elForm.validate((isValid) => {
                resolve(isValid)
            })
        })
        if (!valid){
            loading.value = false
            return
        }
    } catch (error) {
        loading.value = false
        return
    }

       // 1.3 验证 approveForms 中的 radio 字段是否都有值
    const currentApproveForm = approveForms.value[index];
    if (currentApproveForm && currentApproveForm.rule && Array.isArray(currentApproveForm.rule)) {
        const emptyRadioFields = currentApproveForm.rule.filter(rule => 
            rule.type === 'radio' && 
            (rule.value === undefined || 
             rule.value === null || 
             rule.value === '')

        );

        if (emptyRadioFields.length > 0) {
            ElMessage.error('请确认'+ stepList.value[index].formName +'都已勾选！');
            loading.value = false;
            return;
        }
    }

    // 2.1 提交审批
    const data = {
        id: task.id,
        reason: auditForms.value[index].reason,
        copyUserIds: auditForms.value[index].copyUserIds
    }
    if (pass) {
        // 审批通过，并且有额外的 approveForm 表单，需要校验 + 拼接到 data 表单里提交
        const formCreateApi = approveFormFApis.value[index]
        if (formCreateApi) {
            await formCreateApi.validate()
            data.variables = approveForms.value[index].value
        }
        await approveTask(data)
        tab.value = '审批记录'
        ElMessage.success('审批通过成功')
    } else {
        const formCreateApi = approveFormFApis.value[index]
        if (formCreateApi) {
            await formCreateApi.validate()
            data.variables = approveForms.value[index].value
        }
        await rejectTask(data)
        tab.value = '审批记录'
        ElMessage.success('审批不通过成功')
    }
    // 2.2 加载最新数据
    await getDetail()
    await setTimeout(() => {
        loading.value = false 
    }, 0);
}

/** 转派审批人 */
const taskTransferFormRef = ref()
const openTaskUpdateAssigneeForm = (id: string) => {
    taskTransferFormRef.value.open(id)
}

/** 处理审批委托的操作 */
const taskDelegateForm = ref()
const handleDelegate = async task => {
    taskDelegateForm.value.open(task.id)
}

/** 处理审批退回的操作 */
const taskReturnFormRef = ref()
const handleBack = async (task: any) => {
    taskReturnFormRef.value.open(task.id)
}

/** 处理审批加签的操作 */
const taskSignCreateFormRef = ref()
const handleSign = async (task: any) => {
    taskSignCreateFormRef.value.open(task.id)
}

/** 获得详情 */
const getDetail = () => {
    // 1. 获得流程实例相关
    getProcessInstance()
    //获取历史流程
    // 2. 获得流程任务列表（审批记录）
    getTaskList()
}
//tab切换
const mapRef = ref(null)
const handleClickTab = (tab: any, event: any) => {
    if (tab.props.name == '流程图') {
        mapRef.value.getMapList()
    }
}

/** 加载流程实例 */
const BusinessFormComponent = ref(null) // 异步组件
const historyInstanceIdList: any = ref([])

//查询流程数据
const getProcessInstance = async () => {
    try {
        processInstanceLoading.value = true
        let data
        await getProcessInstanceById(id).then(res => {
            data = res.data
        })

        if (!data) {
            ElMessage.error('查询不到流程信息！')
            return
        }
        processInstance.value = data
       
        // 设置表单信息
        const processDefinition = data.processDefinition
        if (processDefinition.formType === 10) {
            setConfAndFields2(detailForm, processDefinition.formConf, processDefinition.formFields, data.formVariables)
            nextTick().then(() => {
                fApi.value?.btn.show(false)
                fApi.value?.resetBtn.show(false)
                fApi.value?.disabled(true)
            })
        } else {
            // 注意：data.processDefinition.formCustomViewPath 是组件的全路径，例如说：/crm/contract/detail/index.vue
            //用markRaw解决因使用ref定义组件，导致组件被标记成响应式对象，造成性能开销警告的问题
            BusinessFormComponent.value = markRaw(registerComponent(data.processDefinition.formCustomViewPath))
        }

        // 加载流程图
        await getProcessDefinitionById(processDefinition.id).then(res => {
            bpmnXml.value = res.data?.bpmnXml
        })
        // console.log(bpmnXml.value, '流程图数据')
    } finally {
        processInstanceLoading.value = false
    }
}
const sortYMDHMS = val => {
    return val.replace('-', '').replace('-', '').replace(' ', '').replace(':', '').replace(':', '') - 0
}

/** 加载任务列表 */
let stepList = ref([])
const getTaskList = async () => {
    historyInstanceIdList.value = historyInstanceId ? historyInstanceId?.split(',') : []
    runningTasks.value = []
    auditForms.value = []
    approveForms.value = []
    approveFormFApis.value = []
    tasks.value = []
    stepList.value = []
    try {
        // 获得未取消的任务
        tasksLoad.value = true
        //根据历史实例id查询历史任务日志数据把最新的id加进去
        historyInstanceIdList.value.push(id)
        //轮询
        await historyInstanceIdList.value?.map((item: any) => {
            getTaskListByProcessInstanceId(item).then(res => {
                res.data?.map(vv => {
                    stepList.value.push(vv)
                })
            })
            tasks.value = []
        })
    } finally {
        tasksLoad.value = false
    }
}

/**
 * 设置 runningTasks 中的任务
 */
const loadRunningTask = tasks => {
    //清空数据
    runningTasks.value = []
    // tasks.length = 1
    tasks?.forEach(task => {
        if (!isEmpty(task.children)) {
            loadRunningTask(task.children)
        }
        // 2.1 只有待处理才需要
        if (task.status !== 1 && task.status !== 6) {
            return
        }
        // 2.2 自己不是处理人
        if (!task.assigneeUser || task.assigneeUser.id !== userId) {
            return
        }
        // 2.3 添加到处理任务
        runningTasks.value.push({ ...task })
        auditForms.value.push({
            reason: '',
            copyUserIds: []
        })
        // 2.4 处理 approve 表单
        if (task.formId && task.formConf) {
            const approveForm = {}
             // 创建包含默认值的表单变量
            const formVariablesWithDefaults = { ...task.formVariable }
            
            // 解析 formFields 并设置默认值
            let processedFormFields = task.formFields;
            if (task.formFields && Array.isArray(task.formFields)) {
                processedFormFields = task.formFields.map(field => {
                    // 如果是字符串，需要先解析为对象
                    let fieldObj = typeof field === 'string' ? JSON.parse(field) : field;
                    
                    // 为 radio 类型设置默认值
                    if (fieldObj.type === 'radio' && fieldObj.options && fieldObj.options.length > 0) {
                        // 如果表单变量中还没有该字段的值，则设置默认值
                        if (!(fieldObj.field in formVariablesWithDefaults)) {
                            formVariablesWithDefaults[fieldObj.field] = fieldObj.defaultValue !== undefined ? 
                                fieldObj.defaultValue : fieldObj.options[0].value;
                        }
                        // 设置字段的默认值
                        fieldObj.value = formVariablesWithDefaults[fieldObj.field];
                    }
                    
                    // 将处理后的对象重新转换为JSON字符串（如果是原始字符串）
                    return typeof field === 'string' ? JSON.stringify(fieldObj) : fieldObj;
                });
            }
            setConfAndFields2(approveForm, task.formConf, processedFormFields, task.formVariable)
            approveForms.value.push(approveForm)
        } else {
            approveForms.value.push({}) // 占位，避免为空
        }
    })
}

const tab = ref('')

/** 初始化 */
const userOptions = ref([]) // 用户列表
//监听历史流程实例数据
watch(
    () => stepList.value,
    (val, oldVal) => {
        if (val && val.length != 0) {
            tasks.value = []
            val.map(task => {
                if (task.status !== 4) {
                    tasks.value.push(task)
                }
            })
            // 1.2 排序，将未完成的排在前面，已完成的排在后面；
            let list = Array.from(tasks.value)?.sort((a, b) => {
                // 有已完成的情况，按照完成时间倒序
                if (a.endTime && b.endTime) {
                    return sortYMDHMS(b.endTime) - sortYMDHMS(a.endTime)
                } else if (a.endTime) {
                    return 1
                } else if (b.endTime) {
                    return -1
                    // 都是未完成，按照创建时间倒序
                } else {
                    return sortYMDHMS(b.createTime) - sortYMDHMS(a.createTime)
                }
            })
            // 获得需要自己审批的任务
            loadRunningTask(list)
            //有自己审批的任务显示流程审核
            if (runningTasks.value.length > 0) {
                tab.value = '流程审核'
            } else {
                tab.value = '申请信息'
            }
        }
    },
    {
        immediate: true,
        deep: true
    }
)

onMounted(async () => {
    getDetail()
    // 获得用户列表
    await getUserSimpleList().then(res => {
        userOptions.value = res.data
    })
    // if (todo) {
    //     tab.value = '流程审核'
    // } else {
    //     tab.value = '申请信息'
    // }
})
</script>
<style lang="scss" scoped>
::v-deep .el-tab-pane {
    height: calc(100vh - 200px) !important;
    overflow: auto !important;
}

::v-deep .el-col-offset-6 {
    margin-left: 15% !important;
}
</style>
