package com.qqchen.deploy.backend.workflow.event.handler;

import com.qqchen.deploy.backend.workflow.enums.WorkflowNodeInstanceStatusEnums;
import com.qqchen.deploy.backend.workflow.dto.event.WorkflowNodeInstanceStatusChangeEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.engine.delegate.event.FlowableActivityEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.BOUNDARY_EVENT_ERROR_PREFIX;
import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.END_EVENT_ERROR_PREFIX;

@Slf4j
@Component
public class ActivityEventHandler implements IFlowableEventHandler {

    @Resource
    private ApplicationEventPublisher publisher;


    @Override
    public boolean canHandle(String eventType) {
        return eventType.startsWith("ACTIVITY_");
    }

    @Override
    public void handle(FlowableEvent event) {
        String eventType = event.getType().name();
        if (!(event instanceof FlowableActivityEvent activityEvent)) {
            return;
        }
        List<String> ignoredList = Arrays.asList(BOUNDARY_EVENT_ERROR_PREFIX, END_EVENT_ERROR_PREFIX);

        boolean ignored = ignoredList.stream().anyMatch(v -> activityEvent.getActivityId().contains(v));
        if (ignored) {
            return;
        }
        WorkflowNodeInstanceStatusEnums status = convertToNodeStatus(eventType);

        if (status != null) {
            publisher.publishEvent(WorkflowNodeInstanceStatusChangeEvent.builder()
                .processInstanceId(activityEvent.getProcessInstanceId())
                .executionId(activityEvent.getExecutionId())
                .nodeId(activityEvent.getActivityId())
                .nodeName(StringUtils.isEmpty(activityEvent.getActivityName()) ? activityEvent.getActivityId() : activityEvent.getActivityName())
                .nodeType(activityEvent.getActivityType())
                .status(status)
                .endTime(LocalDateTime.now())
                .build()
            );
        }
    }

    private WorkflowNodeInstanceStatusEnums convertToNodeStatus(String eventType) {
        return switch (eventType) {
            case "ACTIVITY_CANCELLED" -> WorkflowNodeInstanceStatusEnums.TERMINATED;
            case "ACTIVITY_ERROR_RECEIVED" -> WorkflowNodeInstanceStatusEnums.FAILED;
            default -> null;
        };
    }
} 