package com.ruoyi.interfaces.workflow.executor;

import com.alibaba.fastjson2.JSONObject;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
import com.ruoyi.common.utils.HttpRequestUtil;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.interfaces.domain.MdModelStep;
import com.ruoyi.interfaces.domain.MdModelStepExecution;
import com.ruoyi.interfaces.service.MdModelStepExecutionService;
import com.ruoyi.interfaces.workflow.ExecutionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * API调用步骤执行器
 */
@Slf4j
@Component
public class ApiStepExecutor implements StepExecutor {

    @Autowired
    private MdModelStepExecutionService stepExecutionService;

    @Override
    public MdModelStep.StepType getSupportedStepType() {
        return MdModelStep.StepType.API;
    }

    @Override
    public MdModelStepExecution execute(MdModelStep step, ExecutionContext context) {
        MdModelStepExecution stepExecution = new MdModelStepExecution();
        stepExecution.setExecutionId(context.getWorkflowId());
        stepExecution.setStepId(step.getId());
        stepExecution.setStepName(step.getName());
        stepExecution.setStepType(MdModelStep.StepType.API);
        stepExecution.markStart();
        stepExecutionService.saveOrUpdate(stepExecution);

        try {
            // 准备请求
            Map<String, Object> config = (Map<String, Object>) JsonUtils.jsonToPojo(step.getConfig(), Map.class);
            HttpMethod method = HttpMethod.valueOf(config.get("method").toString());
            String url = context.renderTemplate(config.get("url").toString());
            Map<String, String> headers = (Map<String, String>) config.get("headers");
            String requestBody = JsonUtils.objectToJson(context.parseTemplate((Map<String, Object>) config.get("body")));
            stepExecution.setInput(requestBody);
            // 执行API调用
            JSONObject response = HttpRequestUtil.getJSONObjectByRequest(url, method.toString(), headers, requestBody);

            // 处理响应
            if (response == null) {
                stepExecution.markFailed("API请求失败");
            } else {
                Map<String, Object> responseMap = new HashMap<>(response);
                stepExecution.markSuccess(responseMap);
                stepExecutionService.saveOrUpdate(stepExecution);
                context.setStepOutput(String.valueOf(step.getId()), responseMap);

                // 保存到全局上下文
                saveToGlobalContext(step, context, response);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            stepExecution.markFailed(e.getMessage());
            stepExecutionService.saveOrUpdate(stepExecution);
        }

        return stepExecution;
    }

    private void saveToGlobalContext(MdModelStep step, ExecutionContext context, Map<String, Object> response) {
        // 根据配置保存特定字段到全局上下文
        if (step.getOutputMapping() == null) {
            return;
        }

        Map<String, Object> outputMapping = JsonUtils.jsonToPojo(step.getOutputMapping(), JSONObject.class);
        if (outputMapping != null) {
            outputMapping.forEach((responsePath, contextKey) -> {
                Object value = extractFromResponse(response, responsePath);
                if (value != null) {
                    context.setContextValue(contextKey.toString(), value);
                }
            });
        }
    }

    private Object extractFromResponse(Map<String, Object> response, String path) {
        if (response == null || path == null || path.isEmpty()) {
            return null;
        }

        try {
            // 将 Map 转换为 JSON 字符串
            String json = JsonUtils.objectToJson(response);

            // 使用 JsonPath 解析
            ReadContext ctx = JsonPath.parse(json);
            return ctx.read(path);
        } catch (Exception e) {
            log.warn("JSONPath提取失败，path: {}, error: {}", path, e.getMessage());
            return null;
        }
    }
}
