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.dto.inputmapping.ApprovalInputMapping;
import com.qqchen.deploy.backend.workflow.dto.outputs.ApprovalOutputs;
import com.qqchen.deploy.backend.workflow.enums.ApprovalResultEnum;
import com.qqchen.deploy.backend.workflow.enums.NodeExecutionStatusEnum;
import com.qqchen.deploy.backend.workflow.model.NodeContext;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

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

/**
 * 审批任务结束监听器
 * 在 UserTask 结束时自动装配上下文信息并构建 ApprovalOutputs
 *
 * @author qqchen
 * @since 2025-10-23
 */
@Slf4j
@Component("approvalExecutionListener")
public class ApprovalExecutionListener implements ExecutionListener {

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private HistoryService historyService;

    @Override
    public void notify(DelegateExecution execution) {
        String nodeId = execution.getCurrentActivityId();
        try {
            log.info("ApprovalExecutionListener: Building outputs for node: {}", nodeId);

            // 1. 读取现有的 NodeContext
            Object nodeDataObj = execution.getVariable(nodeId);
            if (!(nodeDataObj instanceof Map)) {
                log.warn("NodeContext not found for node: {}, skipping ApprovalExecutionListener", nodeId);
                return;
            }

            @SuppressWarnings("unchecked")
            Map<String, Object> nodeDataMap = (Map<String, Object>) nodeDataObj;
            NodeContext<ApprovalInputMapping, ApprovalOutputs> nodeContext = 
                NodeContext.fromMap(nodeDataMap, ApprovalInputMapping.class, ApprovalOutputs.class, objectMapper);

            // 2. 检查是否已经有临时的 outputs（由 ApprovalTaskServiceImpl 设置）
            ApprovalOutputs outputs = nodeContext.getOutputs();
            if (outputs == null) {
                log.warn("Outputs not found in NodeContext for node: {}, skipping", nodeId);
                return;
            }

            // 3. 自动装配上下文信息（计算审批用时、历史任务ID等）
            enrichApprovalOutputs(execution, nodeId, outputs);

            // 4. 更新 NodeContext 的 outputs
            nodeContext.setOutputs(outputs);

            // 5. 保存回流程变量
            execution.setVariable(nodeId, nodeContext.toMap(objectMapper));
            
            log.info("Stored approval outputs for node: {}, result: {}", nodeId, outputs.getApprovalResult());

            // 6. 设置节点执行状态为成功（供 GlobalNodeExecutionListener 使用）
            execution.setVariable(WORKFLOW_PREVIOUS_NODE_EXECUTION_STATE_VARIABLE_NAME, WORKFLOW_NODE_EXECUTION_STATE_SUCCESS);

        } catch (Exception e) {
            log.error("Failed to build approval outputs for node: {}", nodeId, e);
            execution.setVariable(WORKFLOW_PREVIOUS_NODE_EXECUTION_STATE_VARIABLE_NAME,
                WORKFLOW_NODE_EXECUTION_STATE_FAILURE);
            throw new RuntimeException("Failed to build approval outputs: " + nodeId, e);
        }
    }

    /**
     * 丰富 ApprovalOutputs
     * 自动装配上下文信息（审批用时等）
     */
    private void enrichApprovalOutputs(DelegateExecution execution, String nodeId, ApprovalOutputs outputs) {
        // 1. ⚙️ 自动装配：审批用时（从任务历史计算）
        Long duration = calculateApprovalDuration(execution, nodeId);
        outputs.setApprovalDuration(duration);
        
        // TODO: 未来可以添加更多自动装配逻辑（如历史任务ID、审批状态等）
    }

    /**
     * 构建 ApprovalOutputs（弃用，保留以防万一）
     * 自动装配所有上下文信息
     * @deprecated 使用 enrichApprovalOutputs 代替
     */
    @Deprecated
    private ApprovalOutputs buildApprovalOutputs(DelegateExecution execution, String nodeId, Map<String, Object> approvalData) {
        ApprovalOutputs outputs = new ApprovalOutputs();

        // 1. 设置审批结果（从 approvalData 读取）
        String approvalResultStr = (String) approvalData.get("approvalResult");
        try {
            outputs.setApprovalResult(ApprovalResultEnum.valueOf(approvalResultStr));
        } catch (IllegalArgumentException e) {
            log.warn("Invalid approval result: {}, defaulting to REJECTED", approvalResultStr);
            outputs.setApprovalResult(ApprovalResultEnum.REJECTED);
        }

        // 2. 设置审批意见（从 approvalData 读取）
        String comment = (String) approvalData.get("approvalComment");
        outputs.setApprovalComment(comment);

        // 3. 设置审批人（从 approvalData 读取）
        String approver = (String) approvalData.get("approver");
        outputs.setApprover(approver);

        // 4. ⚙️ 自动装配：审批人ID（如果有）
        Object approverUserIdObj = approvalData.get("approverUserId");
        if (approverUserIdObj != null) {
            outputs.setApproverUserId(Long.valueOf(approverUserIdObj.toString()));
        }

        // 5. 设置审批时间（从 approvalData 读取）
        Object approvalTimeObj = approvalData.get("approvalTime");
        if (approvalTimeObj instanceof LocalDateTime) {
            outputs.setApprovalTime((LocalDateTime) approvalTimeObj);
        } else if (approvalTimeObj != null) {
            // 尝试从其他格式转换
            outputs.setApprovalTime(LocalDateTime.now());
        }

        // 6. ⚙️ 自动装配：审批用时（从任务历史计算）
        Long duration = calculateApprovalDuration(execution, nodeId);
        outputs.setApprovalDuration(duration);

        // 7. ⚙️ 自动装配：所有审批人列表（会签/或签场景）
        List<ApprovalOutputs.ApproverInfo> allApprovers = getAllApprovers(execution, nodeId);
        if (allApprovers != null && !allApprovers.isEmpty()) {
            outputs.setAllApprovers(allApprovers);
        }

        // 8. ⚙️ 自动装配：节点执行状态
        outputs.setStatus(NodeExecutionStatusEnum.SUCCESS);

        return outputs;
    }

    /**
     * 计算审批用时（秒）
     */
    private Long calculateApprovalDuration(DelegateExecution execution, String nodeId) {
        try {
            // 查询任务历史
            List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(execution.getProcessInstanceId())
                .taskDefinitionKey(nodeId)
                .orderByHistoricTaskInstanceEndTime()
                .desc()
                .list();

            if (!tasks.isEmpty()) {
                HistoricTaskInstance task = tasks.get(0);
                if (task.getCreateTime() != null && task.getEndTime() != null) {
                    long durationMillis = task.getEndTime().getTime() - task.getCreateTime().getTime();
                    return durationMillis / 1000; // 转换为秒
                }
            }
        } catch (Exception e) {
            log.warn("Failed to calculate approval duration", e);
        }

        return null;
    }

    /**
     * 获取所有审批人列表（会签/或签场景）
     */
    private List<ApprovalOutputs.ApproverInfo> getAllApprovers(DelegateExecution execution, String nodeId) {
        try {
            // 查询该节点的所有历史任务
            List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(execution.getProcessInstanceId())
                .taskDefinitionKey(nodeId)
                .finished()
                .list();

            if (tasks.size() > 1) {
                // 多个任务说明是会签/或签场景
                List<ApprovalOutputs.ApproverInfo> approvers = new ArrayList<>();
                for (HistoricTaskInstance task : tasks) {
                    ApprovalOutputs.ApproverInfo info = new ApprovalOutputs.ApproverInfo();
                    info.setUserName(task.getAssignee());

                    // 从任务变量中获取审批结果和意见
                    Map<String, Object> taskVariables = task.getTaskLocalVariables();
                    if (taskVariables != null) {
                        info.setResult((String) taskVariables.get("taskApprovalResult"));
                        info.setComment((String) taskVariables.get("taskApprovalComment"));
                    }

                    if (task.getEndTime() != null) {
                        info.setTime(convertToLocalDateTime(task.getEndTime()));
                    }

                    approvers.add(info);
                }
                return approvers;
            }
        } catch (Exception e) {
            log.warn("Failed to get all approvers", e);
        }

        return null;
    }

    /**
     * Date 转 LocalDateTime
     */
    private LocalDateTime convertToLocalDateTime(Date date) {
        if (date == null) return null;
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }
}

