package cn.fateverse.workflow.process.listener;

import cn.fateverse.workflow.constant.ProcessConstant;
import cn.hutool.core.date.DateUtil;
import cn.fateverse.common.core.constant.DateConstants;
import cn.fateverse.common.core.exception.CustomException;
import cn.fateverse.workflow.entity.HistoricalOperation;
import cn.fateverse.workflow.entity.bpmn.ProcessNode;
import cn.fateverse.workflow.entity.bpmn.Properties;
import cn.fateverse.workflow.enums.OperationStateEnums;
import cn.fateverse.workflow.mapper.HistoricalOperationMapper;
import cn.fateverse.workflow.process.ProcessServiceUtils;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.IntermediateCatchEvent;
import org.flowable.bpmn.model.TimerEventDefinition;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Optional;

/**
 * 延时等待时间监听器
 *
 * @author Clay
 * @date 2023-03-21
 */
@Slf4j
@Component
public class IntermediateCatchEventListener implements ExecutionListener {


    private final RepositoryService repositoryService;

    private final HistoricalOperationMapper operationMapper;

    public IntermediateCatchEventListener(RepositoryService repositoryService, HistoricalOperationMapper operationMapper) {
        this.repositoryService = repositoryService;
        this.operationMapper = operationMapper;
    }


    @Override
    public void notify(DelegateExecution execution) {
        String value = ProcessServiceUtils.getBpmnValue(repositoryService, execution.getProcessDefinitionId(), ProcessConstant.BPMN_FORM_PROCESS);
        //获取到节点的数据信息
        String currentActivityId = execution.getCurrentActivityId();
        //获取到流程节点的数据信息
        Optional<ProcessNode> nodeOptional = JSON.parseArray(value, ProcessNode.class).stream().filter(node -> currentActivityId.equals(node.getId())).findAny();
        if (nodeOptional.isEmpty()) {
            throw new CustomException("数据异常!");
        }
        ProcessNode processNode = nodeOptional.get();
        switch (execution.getEventName()) {
            case ExecutionListener.EVENTNAME_START:
                FlowElement currentFlowElement = execution.getCurrentFlowElement();
                if (currentFlowElement instanceof IntermediateCatchEvent){
                    IntermediateCatchEvent intermediateCatchEvent = (IntermediateCatchEvent) currentFlowElement;
                    TimerEventDefinition timerEventDefinition = (TimerEventDefinition)intermediateCatchEvent.getEventDefinitions().get(0);
                    Properties props = processNode.getProps();
                    if (props.getType().equals("AUTO")) {
                        Date date = new Date();
                        String dateToStr = DateUtil.format(date,DateConstants.YYYY_MM_DD);
                        dateToStr = dateToStr + " " + props.getDateTime();
                        Date targetDate = DateUtil.parseDateTime(dateToStr);
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTime(targetDate);
                        if (targetDate.getTime() < date.getTime()){
                            log.info("超过当前时间,需要移交到明天");
                            calendar.add(Calendar.DATE,1);
                        }
                        String timeDate = DateUtil.format(calendar.getTime(),"yyyy-MM-dd'T'HH:mm:ss");
                        log.info("时间为:"+timeDate);
                        timerEventDefinition.setTimeDate(timeDate);

                    }
                    //设置好时间事件
                    intermediateCatchEvent.setEventDefinitions(Collections.singletonList(timerEventDefinition));
                    execution.setCurrentFlowElement(currentFlowElement);
                }
                HistoricalOperation operation = HistoricalOperation.toHistoricalOperation(execution, null, processNode.getName(), processNode.getType().getType());
                int count = operationMapper.selectCountByProcessInstanceIdAndNodeId(execution.getProcessInstanceId(), processNode.getId());
                if (count <= 0) {
                    operationMapper.insert(operation);
                }
                break;
            case ExecutionListener.EVENTNAME_END:
                operationMapper.updateStatusByProcessInstanceIdAndNodeId(execution.getProcessInstanceId(),processNode.getId(), OperationStateEnums.AGREE);
                log.info("延时器结束!");
                break;
            default:
                break;
        }
    }
}
