package com.ruoyi.interfaces.workflow;

import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.interfaces.domain.MdModelStep;
import com.ruoyi.interfaces.domain.MdModelStepExecution;
import com.ruoyi.interfaces.domain.MdModelWorkflowExecution;
import com.ruoyi.interfaces.exception.StepExecutionException;
import com.ruoyi.interfaces.service.MdModelStepService;
import com.ruoyi.interfaces.service.MdModelWorkflowExecutionService;
import com.ruoyi.interfaces.workflow.executor.StepExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author LinQiLong
 * @date 2025/7/15 16:23
 */

@Service
public class WorkflowEngine {

    @Autowired
    private MdModelStepService stepService;

    @Autowired
    private MdModelWorkflowExecutionService executionService;

    @Autowired
    private ExecutorFactory executorFactory;

    public ExecutionResult execute(Long workflowId, Map<String, Object> input) {
        // 获取工作流步骤
        List<MdModelStep> steps = stepService.listByWorkflowIdOrderBySequence(workflowId);

        // 创建执行上下文
        ExecutionContext context = new ExecutionContext(input);

        // 创建执行记录
        MdModelWorkflowExecution workflowExecution = new MdModelWorkflowExecution();
        workflowExecution.setWorkflowId(workflowId);
        workflowExecution.setStatus(MdModelWorkflowExecution.ExecutionStatus.RUNNING);
        workflowExecution.setInput(JsonUtils.objectToJson(input));
        workflowExecution.setStartTime(new Date());
        executionService.save(workflowExecution);
        context.setWorkflowId(workflowExecution.getWorkflowId());

        // 创建执行结果
        ExecutionResult result = new ExecutionResult(String.valueOf(workflowId), input);
        result.setStatus(ExecutionResult.ExecutionStatus.RUNNING);

        try {
            for (int i = 0; i < steps.size(); i++) {
                MdModelStep currentStep = steps.get(i);

                // 执行当前步骤
                StepExecutor executor = executorFactory.getExecutor(currentStep.getType());
                MdModelStepExecution stepExecution = executor.execute(currentStep, context);

                // 保存步骤执行结果
                result.addStepExecution(stepExecution);

                // 处理步骤执行结果
                if (stepExecution.isFailed()) {
                    // 根据错误策略处理
                    switch (currentStep.getErrorPolicy()) {
                        case ABORT:
                            throw new StepExecutionException(stepExecution.getErrorMsg());
                        case IGNORE:
                            // 继续执行下一步
                            break;
                        case RETRY:
                            // 实现重试逻辑
                            handleRetry(currentStep, context, stepExecution);
                            break;
                    }
                }

                // 处理条件分支
                if (currentStep.getType() == MdModelStep.StepType.CONDITION) {
                    // 实现条件分支逻辑
                    handleConditionBranch(steps, i, context, result);
                }
            }

            // 所有步骤成功完成
            result.markSuccess(context.getAllContextData());
            workflowExecution.setOutput(context.getAllContextData());
            workflowExecution.setStatus(MdModelWorkflowExecution.ExecutionStatus.SUCCESS);
        } catch (StepExecutionException e) {
            result.markFailed(e.getMessage());
            workflowExecution.setStatus(MdModelWorkflowExecution.ExecutionStatus.FAILED);
        }

        // 持久化执行结果
        workflowExecution.setEndTime(new Date());
        executionService.updateById(workflowExecution);
        return result;
    }

    private void handleRetry(MdModelStep step, ExecutionContext context, MdModelStepExecution stepExecution) {
        StepExecutor executor = executorFactory.getExecutor(step.getType());
        int maxRetries = step.getRetryCount();

        for (int retry = 1; retry <= maxRetries; retry++) {
            stepExecution.increaseRetryCount();

            try {
                MdModelStepExecution newExecution = executor.execute(step, context);
                stepExecution.setStatus(newExecution.getStatus());
                stepExecution.setOutput(newExecution.getOutput());

                if (newExecution.isSuccess()) {
                    stepExecution.setErrorMsg(null);
                    return; // 重试成功
                } else {
                    stepExecution.setErrorMsg(newExecution.getErrorMsg());
                }
            } catch (Exception e) {
                stepExecution.setErrorMsg(e.getMessage());
            }
        }
    }

    private void handleConditionBranch(List<MdModelStep> steps, int currentIndex,
                                       ExecutionContext context,
                                       ExecutionResult result) {
        // 获取条件判断结果
        Boolean conditionResult = (Boolean) context.getAllContextData().get("CONDITION_RESULT");

        if (conditionResult != null && !conditionResult) {
            // 跳过后续步骤直到下一个分支节点或结束
            while (currentIndex + 1 < steps.size()) {
                MdModelStep nextStep = steps.get(currentIndex + 1);

                // 如果遇到结束条件或新分支，停止跳过
                if (nextStep.getType() == MdModelStep.StepType.CONDITION) {
                    break;
                }

                // 创建被跳过的步骤执行记录
                MdModelStepExecution skippedExecution = new MdModelStepExecution();
                skippedExecution.setStepId(nextStep.getId());
                skippedExecution.setStepName(nextStep.getName());
                skippedExecution.setStepType(nextStep.getType());
                skippedExecution.markSkipped();

                // 添加到执行结果
                result.addStepExecution(skippedExecution);

                currentIndex++;
            }
        }
    }

}
