package com.mortals.flowable.listener.global;


import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.mortals.xhx.common.code.PlatformTypeEnum;
import com.mortals.xhx.common.code.flowable.runtime.CommentTypeEnum;
import com.mortals.xhx.common.code.flowable.runtime.ProcessStatusEnum;
import com.mortals.xhx.flowable.message.FlowMessageReq;
import com.mortals.xhx.module.comment.model.CommentInfoEntity;
import com.mortals.xhx.module.comment.service.CommentInfoService;
import com.mortals.xhx.module.extend.model.ExtendHisprocinstEntity;
import com.mortals.xhx.module.extend.model.ExtendHisprocinstQuery;
import com.mortals.xhx.module.extend.model.ExtendProcinstEntity;
import com.mortals.xhx.module.extend.model.ExtendProcinstQuery;
import com.mortals.xhx.module.extend.service.ExtendHisprocinstService;
import com.mortals.xhx.module.extend.service.ExtendProcinstService;
import com.mortals.xhx.module.platform.model.PlatformEntity;
import com.mortals.xhx.module.platform.model.PlatformListenerQuery;
import com.mortals.xhx.module.platform.model.PlatformQuery;
import com.mortals.xhx.module.platform.service.PlatformListenerService;
import com.mortals.xhx.module.platform.service.PlatformModelinfoService;
import com.mortals.xhx.module.platform.service.PlatformService;
import lombok.extern.apachecommons.CommonsLog;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.engine.HistoryService;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 流程结束全局监听器
 *
 * @author: zxfei
 * @date: 2021/9/9 10:56
 */
@Component
@Slf4j
public class GlobalProcistEndListener extends AbstractFlowableEngineEventListener {

    public static String ProcessEnd = "1";

    @Autowired
    private ExtendProcinstService extendProcinstService;
    @Autowired
    private ExtendHisprocinstService extendHisprocinstService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private CommentInfoService commentInfoService;
    @Autowired
    private PlatformService platformService;
    @Autowired
    private PlatformListenerService platformListenerService;


    @Override
    protected void processCompleted(FlowableEngineEntityEvent event) {
        log.info("进入流程结束全局监听器");
        FlowableEntityEventImpl flowableEntityEvent = (FlowableEntityEventImpl) event;

        String processInstanceId = flowableEntityEvent.getProcessInstanceId();


        Map<String, Object> variables = ((ProcessInstance) flowableEntityEvent.getEntity()).getProcessVariables();

        //拷贝数据
        this.updateExtendInfoToHis(processInstanceId, variables);
    }

    /**
     * 更新历史的扩展信息
     *
     * @param processInstanceId 流程实例id
     */
    private void updateExtendInfoToHis(String processInstanceId, Map<String, Object> variables) {
        //1.更新历史的流程实例的扩展信息 批量更新
        ExtendHisprocinstEntity extendHisProcinst = extendHisprocinstService.selectOne(new ExtendHisprocinstQuery().processInstanceId(processInstanceId), null);
        if (extendHisProcinst != null && !ProcessStatusEnum.ZZ.toString().equals(extendHisProcinst.getProcessStatus())) {
            extendHisProcinst.setProcessStatus(ProcessStatusEnum.BJ.toString());
            extendHisprocinstService.update(extendHisProcinst);
        }
        //流程结束信息如果是知会不用评论
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        //流程一发起就结束信息添加
        if (historicProcessInstance == null) {
            extendHisProcinst.setProcessStatus(ProcessStatusEnum.BJ.toString());
            extendHisprocinstService.update(extendHisProcinst);
        }
        CommentInfoEntity commentInfo = new CommentInfoEntity();
        commentInfo.setProcessInstanceId(processInstanceId);
        commentInfo.setType(CommentTypeEnum.SPJS.name());
        commentInfo.setMessage(CommentTypeEnum.getEnumMsgByType(CommentTypeEnum.SPJS.toString()));
        commentInfo.setPersonalCode("system");
        commentInfoService.save(commentInfo);
        //删除运行时的流程实例扩展信息
        ExtendProcinstEntity extendProcinstEntity = extendProcinstService.selectOne(new ExtendProcinstQuery().processInstanceId(processInstanceId), null);
        if (!ObjectUtils.isEmpty(extendProcinstEntity)) {
            extendProcinstService.remove(new Long[]{extendProcinstEntity.getId()}, null);
        }

        //发送消息或者http回调
        PlatformEntity modelinfoEntity = platformService.selectOne(new PlatformQuery().platformSn(extendHisProcinst.getTenantId()), null);
        if (ObjectUtils.isEmpty(modelinfoEntity)) {
            log.info("平台用户为空，sn:" + extendHisProcinst.getTenantId());
            return;
        }
        //校验当前平台用户是否订阅了流程终结消息
        Set<String> collect = platformListenerService.find(new PlatformListenerQuery().platformId(modelinfoEntity.getId())).stream().map(item -> item.getTypeCode()).collect(Collectors.toSet());

        if (!collect.contains(ProcessEnd)) {
            log.info("当前平台用户未订阅流程结束通知，sn:" + modelinfoEntity.getPlatformSn());
            return;
        }

        log.info("发送消息或者http回调,type:{}", modelinfoEntity.getType());
        //手动终止撤销的不触发通知消息
        if (!ObjectUtils.isEmpty(modelinfoEntity)
                && !ProcessStatusEnum.ZZ.toString().equals(extendHisProcinst.getProcessStatus())) {

            if (PlatformTypeEnum.HTTP.getValue() == modelinfoEntity.getType()) {
                //http
                FlowMessageReq flowMessageReq = new FlowMessageReq();
                BeanUtils.copyProperties(extendHisProcinst, flowMessageReq);
                flowMessageReq.setPlatformSn(extendHisProcinst.getTenantId());
                flowMessageReq.setType(Integer.parseInt(ProcessEnd));
                flowMessageReq.setBusinessKey(extendHisProcinst.getBusinessKey());


                if (historicProcessInstance != null && historicProcessInstance.getProcessVariables() != null) {
                    flowMessageReq.setContent(JSON.toJSONString(variables));
                }

                doPostMessage(modelinfoEntity.getCallbackUrl(), flowMessageReq);

            } else if (PlatformTypeEnum.JMS.getValue() == modelinfoEntity.getType()) {
                //todo
            }

            //modelinfoEntity.get
        }

    }


    private void doPostMessage(String url, FlowMessageReq flowMessageReq) {
        String ret = "";
        try {
            log.info(String.format("发送请求,url:%s,body:%s", url, JSON.toJSONString(flowMessageReq)));
            HashMap<String, String> header = new HashMap<>();
            header.put("Content-Type", "application/json");
            ret = com.mortals.framework.util.HttpUtil.doPost(url, header, JSON.toJSONString(flowMessageReq));
            log.info("收到响应:" + ret);
        } catch (Exception e) {
            log.error("回调异常", e);
            try {
                Thread.sleep(10000);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
            doPostMessage(url, flowMessageReq);
        }
    }

}
