package com.qqchen.deploy.backend.workflow.listener.flowable.execution;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants;
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.bpmn.model.FlowElement;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;

import java.time.LocalDateTime;
import java.util.*;

import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.WORKFLOW_PREVIOUS_NODE_EXECUTION_STATE_VARIABLE_NAME;

@Slf4j
@Component("globalNodeExecutionListener")
public class GlobalNodeExecutionListener implements ExecutionListener {

    @Resource
    @Lazy
    private ApplicationEventPublisher eventPublisher;

    @Resource
    private ObjectMapper objectMapper;

    @Override
    public void notify(DelegateExecution execution) {
        // 获取当前节点信息
        FlowElement flowElement = execution.getCurrentFlowElement();
        String eventName = execution.getEventName();
        String processInstanceId = execution.getProcessInstanceId();
        String executionId = execution.getId();
        String nodeId = execution.getCurrentActivityId();
        String nodeName = flowElement.getName();
        String nodeType = flowElement.getClass().getSimpleName();
        log.debug("Node execution event: {}, processInstanceId: {}, nodeId: {}, nodeType: {}, nodeName:{}", eventName, processInstanceId, nodeId, nodeType, nodeName);
        LocalDateTime now = LocalDateTime.now();
        WorkflowNodeInstanceStatusEnums status = null;
        LocalDateTime startTime = null;
        LocalDateTime endTime = null;
        String variablesJson = null;
        String errorMessage = null;
        
        String nodeExecutionStatus = Optional.ofNullable(execution.getVariables())
            .map(vars -> vars.get(WORKFLOW_PREVIOUS_NODE_EXECUTION_STATE_VARIABLE_NAME))
            .map(Object::toString)
            .orElse(null);
        switch (eventName) {
            case ExecutionListener.EVENTNAME_START:
                status = WorkflowNodeInstanceStatusEnums.RUNNING;
                startTime = now;
                break;
            case ExecutionListener.EVENTNAME_END:
                if (StringUtils.isEmpty(nodeExecutionStatus)) {
                    status = WorkflowNodeInstanceStatusEnums.COMPLETED;
                } else {
                    if (WorkFlowConstants.WORKFLOW_NODE_EXECUTION_STATE_SUCCESS.equals(nodeExecutionStatus)) {
                        status = WorkflowNodeInstanceStatusEnums.COMPLETED;
                    } else {
                        status = WorkflowNodeInstanceStatusEnums.FAILED;
                    }
                }
                
                // ✅ 收集节点执行变量
                variablesJson = collectNodeVariables(execution, nodeId, status);
                
                // ✅ 如果失败，提取错误信息
                if (status == WorkflowNodeInstanceStatusEnums.FAILED) {
                    errorMessage = extractErrorMessage(execution, nodeId);
                }
                
                endTime = now;
                break;
            default:
                log.warn("Unexpected event type: {}", eventName);
                return;
        }
        eventPublisher.publishEvent(WorkflowNodeInstanceStatusChangeEvent.builder()
            .processInstanceId(processInstanceId)
            .executionId(executionId)
            .nodeId(nodeId)
            .nodeName(nodeName)
            .nodeType(nodeType)
            .status(status)
            .startTime(startTime)
            .endTime(endTime)
            .variables(variablesJson)
            .errorMessage(errorMessage)
            .build());
    }

    /**
     * 收集节点执行变量
     * 
     * @param execution Flowable执行上下文
     * @param nodeId 节点ID
     * @param status 节点执行状态
     * @return JSON格式的变量字符串
     */
    private String collectNodeVariables(DelegateExecution execution, String nodeId, 
                                       WorkflowNodeInstanceStatusEnums status) {
        try {
            // ✅ 直接获取所有流程变量
            Map<String, Object> allVariables = execution.getVariables();
            
            if (allVariables == null || allVariables.isEmpty()) {
                return null;
            }
            
            return objectMapper.writeValueAsString(allVariables);
            
        } catch (Exception e) {
            log.error("Failed to collect node variables for nodeId: {}", nodeId, e);
            return null;
        }
    }

    /**
     * 提取错误信息
     * 
     * @param execution Flowable执行上下文
     * @param nodeId 节点ID
     * @return 错误信息字符串
     */
    private String extractErrorMessage(DelegateExecution execution, String nodeId) {
        try {
            Object nodeOutput = execution.getVariable(nodeId);
            if (nodeOutput instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> outputMap = (Map<String, Object>) nodeOutput;
                Object errorMsg = outputMap.get("errorMessage");
                if (errorMsg != null) {
                    return errorMsg.toString();
                }
            }
        } catch (Exception e) {
            log.warn("Failed to extract error message for nodeId: {}", nodeId, e);
        }
        return null;
    }
}