package cn.axzo.workflow.core.engine.cmd;

import cn.axzo.workflow.common.enums.ApproverEmptyHandleTypeEnum;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
import cn.axzo.workflow.core.engine.listener.EngineExecutionStartListener;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.runtime.Execution;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper.getApproverSpecify;

/**
 * 自定义的推测用户任务的审批人的命令实现
 *
 * @author wangli
 * @since 2023/12/11 17:56
 */
@Slf4j
public class CustomForecastUserTaskAssigneeCmd implements Command<List<BpmnTaskDelegateAssigner>>, Serializable {
    private final String processInstanceId;
    private final UserTask userTask;
    private final EngineExecutionStartListener engineExecutionStartListener;

    public CustomForecastUserTaskAssigneeCmd(String processInstanceId, UserTask userTask,
                                             EngineExecutionStartListener engineExecutionStartListener) {
        this.processInstanceId = processInstanceId;
        this.userTask = userTask;
        this.engineExecutionStartListener = engineExecutionStartListener;
    }

    @Override
    public List<BpmnTaskDelegateAssigner> execute(CommandContext commandContext) {
        ProcessEngineConfigurationImpl processEngineConfiguration =
                CommandContextUtil.getProcessEngineConfiguration(commandContext);
        List<Execution> list =
                processEngineConfiguration.getRuntimeService().createExecutionQuery().processInstanceId(processInstanceId).list();
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<BpmnTaskDelegateAssigner> forecastAssigners = new ArrayList<>();
        getApproverSpecify(userTask).ifPresent(specify -> {
            forecastAssigners.addAll(engineExecutionStartListener.approverSelect(specify.getType(), userTask,
                    (DelegateExecution) list.get(0), false));
        });

        // 如果没找到审批人,加载管理员
        if (CollectionUtils.isEmpty(forecastAssigners)) {
            log.info("流程实例: {} 推测审批人时, UserTask{}: 未找到审批人, 开始根据'审批人为空'时的兜底配置进行计算!", processInstanceId,
                    userTask.getId());
            BpmnMetaParserHelper.getApproverEmptyHandleType(userTask).ifPresent(type -> {
                switch (type) {
                    case transferToAdmin:
                        forecastAssigners.addAll(engineExecutionStartListener.approverSelect(ApproverEmptyHandleTypeEnum.transferToAdmin.getType(), userTask,
                                (DelegateExecution) list.get(0), false));
                        break;
                    case specifyAssignee:
                        BpmnMetaParserHelper.getApproverSpecifyValue(userTask)
                                .ifPresent(s -> forecastAssigners.addAll(JSON.parseArray(s,
                                        BpmnTaskDelegateAssigner.class)));
                        break;
                    default:
                        break;
                }
            });
        }
        log.info("流程实例: {} , UserTask: {}推测的最终审批人为: {}", processInstanceId, userTask.getId(),
                JSONUtil.toJsonStr(forecastAssigners));
        return forecastAssigners;
    }
}
