package com.yunzhupaas.flowable.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.util.SentMessageUtil;
import com.yunzhupaas.flowable.entity.OperatorEntity;
import com.yunzhupaas.flowable.entity.TaskEntity;
import com.yunzhupaas.flowable.enums.OperatorStateEnum;
import com.yunzhupaas.flowable.model.message.DelegateModel;
import com.yunzhupaas.flowable.model.task.FlowModel;
import com.yunzhupaas.flowable.model.trigger.ExecuteAsyncModel;
import com.yunzhupaas.flowable.model.trigger.ExecuteModel;
import com.yunzhupaas.flowable.model.util.FlowConstant;
import com.yunzhupaas.flowable.model.util.FlowNature;
import com.yunzhupaas.flowable.model.util.SystemAuditModel;
import com.yunzhupaas.flowable.service.OperatorService;
import com.yunzhupaas.flowable.service.TaskService;
import com.yunzhupaas.message.model.SentMessageForm;
import com.yunzhupaas.permission.entity.UserEntity;
import com.yunzhupaas.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 类的描述
 *
 * @author YUNZHUPAASYUNZHUPAAS开发组
 * @version 5.0.x
 * @since 2024/8/26 16:56
 */
@Component
public class FlowAsyncUtil {

    @Lazy
    @Autowired
    private ServiceUtil serviceUtil;
    @Autowired
    private SentMessageUtil sentMessageUtil;
    @Autowired
    private TriggerUtil triggerUtil;
    @Autowired
    private OperatorService operatorService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private OperatorUtil operatorUtil;

    // --------------------------------------委托消息------------------------------------------------------
    @Async
    public void delegateMsg(DelegateModel flowDelegate) {
        List<String> toUserIds = flowDelegate.getToUserIds();
        if (!toUserIds.isEmpty()) {
            UserInfo userInfo = flowDelegate.getUserInfo();
            TaskEntity flowTask = flowDelegate.getFlowTask();
            Map<String, String> contentMsg = new HashMap<>();
            Boolean delegate = flowDelegate.getDelegate();
            boolean approve = flowDelegate.getApprove();
            if (approve) {
                SentMessageForm flowMsgModel = new SentMessageForm();
                flowMsgModel.setToUserIds(toUserIds);
                flowMsgModel.setUserInfo(flowDelegate.getUserInfo());
                Map<String, Object> parameterMap = new HashMap<>();
                parameterMap.put(FlowConstant.MANDATOR, userInfo.getUserName());
                UserEntity mandatary = StringUtil.isNotEmpty(flowTask.getDelegateUserId())
                        ? serviceUtil.getUserInfo(flowTask.getDelegateUserId())
                        : null;
                parameterMap.put(FlowConstant.MANDATARY, mandatary != null ? mandatary.getRealName() : "");
                parameterMap.put(FlowConstant.TITLE, delegate ? "委托" : "代理");
                flowMsgModel.setParameterMap(parameterMap);
                // 委托/代理确认通知
                Integer ack = flowDelegate.getAck();
                // 1.委托设置 2.委托给我
                Integer type = flowDelegate.getType();
                String templateId = FlowNature.EndMsg.equals(type) ? "PZXTLG021"
                        : ObjectUtil.equals(ack, 1) ? "PZXTLG020" : "PZXTLG019";
                flowMsgModel.setTemplateId(templateId);

                Integer delegateType = FlowNature.EndMsg.equals(type) ? 0 : delegate ? 2 : 4;
                contentMsg.put("type", delegateType + "");

                flowMsgModel.setContentMsg(contentMsg);
                flowMsgModel.setFlowType(2);
                flowMsgModel.setType(2);
                List<SentMessageForm> messageListAll = new ArrayList<>();
                messageListAll.add(flowMsgModel);
                serviceUtil.sendDelegateMsg(messageListAll);
            }
        }
    }

    // --------------------------------发送消息------------------------------
    @Async
    public void sendMessage(List<SentMessageForm> messageListAll) {
        for (SentMessageForm messageForm : messageListAll) {
            if (messageForm.isSysMessage()) {
                sentMessageUtil.sendMessage(messageForm);
            }
        }
    }

    @Async
    public void execute(List<ExecuteAsyncModel> list) throws Exception {
        for (ExecuteAsyncModel asyncModel : list) {
            FlowModel flowModel = asyncModel.getFlowModel();
            ExecuteModel model = asyncModel.getModel();
            Boolean sync = asyncModel.getSync();
            List<OperatorEntity> operatorList = asyncModel.getOperatorList();
            List<SystemAuditModel> systemList = asyncModel.getSystemList();
            List<TaskEntity> subTaskList = asyncModel.getSubTaskList();
            this.execute(model, sync, operatorList, subTaskList, systemList, flowModel);
        }
    }

    public void execute(ExecuteModel model, Boolean isAsync, List<OperatorEntity> operatorList,
            List<TaskEntity> subTaskList, List<SystemAuditModel> systemList, FlowModel flowModel) throws Exception {
        try {
            triggerUtil.execute(model);
        } catch (Exception e) {
            e.printStackTrace();
            // 终止流程
            if (isAsync) {
                TaskEntity taskEntity = flowModel.getTaskEntity();
                taskService.cancel(taskEntity.getId(), flowModel, true);
            }
            return;
        }
        // try {
        // System.out.println("==================================================1");
        // Thread.sleep(20000);
        // System.out.println("==================================================2");
        // } catch (InterruptedException e) {
        // e.printStackTrace();
        // }
        if (isAsync) {
            if (CollectionUtil.isNotEmpty(operatorList)) {
                for (OperatorEntity operator : operatorList) {
                    operator.setStatus(OperatorStateEnum.Runing.getCode());
                }
                operatorService.updateBatchById(operatorList);
            }
            if (CollectionUtil.isNotEmpty(subTaskList)) {
                for (TaskEntity taskEntity : subTaskList) {
                    Integer hisStatus = taskEntity.getHisStatus();
                    taskEntity.setStatus(hisStatus);
                }
                taskService.updateBatchById(subTaskList);
            }
            if (CollectionUtil.isNotEmpty(systemList)) {
                for (SystemAuditModel systemAuditModel : systemList) {
                    try {
                        operatorUtil.autoAudit(systemAuditModel.getOperator(), systemAuditModel.getFlowModel());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            try {
                operatorUtil.autoAudit(flowModel, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
