package com.hz.pm.api.scheduler.listener;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.util.StrPool;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.common.enumeration.CommonEnum;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.entity.ProjectInst;
import com.hz.pm.api.projectlib.service.IProjectInstService;
import com.hz.pm.api.projectlib.service.IProjectService;
import com.hz.pm.api.sys.manage.EarlyWarningManage;
import com.hz.pm.api.sys.service.IProjectEarlyWarningService;
import com.wflow.enums.WarningRuleTypeEnum;
import com.wflow.workflow.notify.event.EarlyWarningEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.time.ZoneId;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 预警规则触发
 *
 * @author ZPF
 * @return
 * @since 2023/08/03 14:19
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class EarlyWarningListener {
    private final HistoryService historyService;
    private final IProjectInstService projectInstService;

    private final IProjectService projectService;

    private final EarlyWarningManage earlyWarningManage;

    private final IProjectEarlyWarningService projectEarlyWarningService;

    @Async
    @EventListener
    public void onApplicationEvent(EarlyWarningEvent event) {
        log.info("进入预警规则触发的 事件监听!");
        log.info("event:{}", JSON.toJSONString(event));
        String nodeId = event.getNodeId();
        Integer timeout = event.getTimeout();
        String noticeMethod = event.getNoticeMethod();
        String noticeContent = event.getNoticeContent();
        Integer noticeType = event.getNoticeType();
        Integer overTimeout = event.getOverTimeout();

        //1.根据nodeId 查询到 node 去查找 未完成 项目实例关系表 找到实例
        List<HistoricActivityInstance> hais = historyService.createHistoricActivityInstanceQuery()
                .activityId(nodeId)
                .unfinished()
                .orderByHistoricActivityInstanceStartTime()
                .asc()
                .list();

        if (CollUtil.isEmpty(hais)) {
            log.info("没有查到 历史实例");
            return;
        }

        String instanceId = hais.get(0).getProcessInstanceId();

        //查询当前未完成的此实例
        HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(instanceId)
                .unfinished()
                .singleResult();

        if (Objects.isNull(instance)) {
            log.info("没有查到实例 或者 实例已经结束");
            return;
        }

        //2.查到 此流程实例的 项目
        ProjectInst pi = projectInstService.getOne(Wrappers.lambdaQuery(ProjectInst.class)
                .eq(ProjectInst::getInstCode, instanceId)
                .last(BizConst.LIMIT_1));

        if (Objects.isNull(pi)) {
            log.info("没有查到实例项目关联信息");
            return;
        }

        Long projectId = pi.getProjectId();
        Project project = projectService.getById(projectId);

        if (Objects.isNull(project)) {
            log.info("没有查到该项目信息");
            return;
        }

        //项目 预警信息
        projectEarlyWarningService.earlyWarning(project,
                WarningRuleTypeEnum.PROCESS_WARNING.getCode(), noticeType);

        if (StringUtils.isBlank(noticeMethod) ||
                (!noticeMethod.contains(String.valueOf(CommonEnum.ZWDD.getCode())) &&
                        !noticeMethod.contains(String.valueOf(CommonEnum.MOBILE.getCode())))) {
            log.info("通知方式为空或者错误!");
            return;
        }

        //这一批员工要通知的员工号
        String batchEmployees = hais.stream().map(HistoricActivityInstance::getAssignee)
                .collect(Collectors.joining(StrPool.COMMA));
        for (HistoricActivityInstance hai : hais) {
            String employeeCode = hai.getAssignee();
            String taskId = hai.getTaskId();
            String path = "toDoCenter/handleDuringExamine?instanceId=" +
                    instanceId + "&projectId=" + projectId + "&nodeId=" + nodeId + "&taskId=" + taskId;
            earlyWarningManage.doEarlyWarning(noticeMethod, noticeContent, timeout, overTimeout, pi.getInstType(),
                    hai.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()
                    , Long.valueOf(employeeCode), project, WarningRuleTypeEnum.PROCESS_WARNING.getCode(), noticeType,
                    path, batchEmployees, nodeId);
        }
    }
}