package com.flowable.devops.workflow.node;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.flowable.devops.entity.NodeType;
import com.flowable.devops.workflow.model.NodeExecutionContext;
import com.flowable.devops.workflow.model.NodeExecutionResult;
import com.flowable.devops.workflow.model.NodeInput;
import com.flowable.devops.workflow.plugin.NodePlugin;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * HTTP请求节点实现
 * 
 * 支持发送HTTP请求到指定URL，支持各种HTTP方法
 * 
 * @author Flowable Team
 * @since 1.0.0
 */
@Slf4j
@NodePlugin(
    id = "http_request",
    name = "httpRequest",
    displayName = "HTTP Request",
    category = NodeType.NodeCategory.API,
    version = "1.0.0",
    author = "Flowable Team",
    description = "发送HTTP请求到指定URL，支持GET/POST/PUT/DELETE等方法",
    icon = "api",
    enabled = true
)
@Component
public class HttpRequestNode implements WorkflowNode {
    
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;
    
    public HttpRequestNode() {
        this.restTemplate = new RestTemplate();
        this.objectMapper = new ObjectMapper();
    }
    
    @Override
    public NodeType getMetadata() {
        NodeType nodeType = new NodeType();
        nodeType.setId("http_request");
        nodeType.setName("httpRequest");
        nodeType.setDisplayName("HTTP Request");
        nodeType.setCategory(NodeType.NodeCategory.API);
        nodeType.setIcon("api");
        nodeType.setDescription("发送HTTP请求到指定URL");
        nodeType.setImplementationClass(this.getClass().getName());
        nodeType.setEnabled(true);
        
        // 构建字段定义JSON
        nodeType.setFields(createFieldsJson());
        
        // 构建输出结构JSON
        nodeType.setOutputSchema(createOutputSchemaJson());
        
        return nodeType;
    }
    
    /**
     * 创建字段定义JSON
     */
    private JsonNode createFieldsJson() {
        ArrayNode fields = objectMapper.createArrayNode();
        
        // URL字段
        ObjectNode urlField = objectMapper.createObjectNode();
        urlField.put("name", "url");
        urlField.put("label", "URL");
        urlField.put("type", "text");
        urlField.put("required", true);
        urlField.put("supportsExpression", true);
        urlField.put("placeholder", "https://api.example.com/users");
        fields.add(urlField);
        
        // 请求方法字段
        ObjectNode methodField = objectMapper.createObjectNode();
        methodField.put("name", "method");
        methodField.put("label", "Method");
        methodField.put("type", "select");
        methodField.put("required", true);
        methodField.put("defaultValue", "GET");
        ArrayNode methodOptions = objectMapper.createArrayNode();
        methodOptions.add("GET").add("POST").add("PUT").add("DELETE").add("PATCH");
        methodField.set("options", methodOptions);
        fields.add(methodField);
        
        // 请求头字段
        ObjectNode headersField = objectMapper.createObjectNode();
        headersField.put("name", "headers");
        headersField.put("label", "Headers");
        headersField.put("type", "key_value");
        headersField.put("supportsFieldMapping", true);
        fields.add(headersField);
        
        // 请求体字段
        ObjectNode bodyField = objectMapper.createObjectNode();
        bodyField.put("name", "body");
        bodyField.put("label", "Request Body");
        bodyField.put("type", "code");
        bodyField.put("language", "json");
        bodyField.put("supportsExpression", true);
        fields.add(bodyField);
        
        // 超时字段
        ObjectNode timeoutField = objectMapper.createObjectNode();
        timeoutField.put("name", "timeout");
        timeoutField.put("label", "Timeout (ms)");
        timeoutField.put("type", "number");
        timeoutField.put("defaultValue", 30000);
        fields.add(timeoutField);
        
        return fields;
    }
    
    /**
     * 创建输出结构JSON Schema
     */
    private JsonNode createOutputSchemaJson() {
        ObjectNode schema = objectMapper.createObjectNode();
        schema.put("type", "object");
        
        ObjectNode properties = objectMapper.createObjectNode();
        
        // statusCode字段
        ObjectNode statusCode = objectMapper.createObjectNode();
        statusCode.put("type", "number");
        statusCode.put("description", "HTTP状态码");
        properties.set("statusCode", statusCode);
        
        // body字段
        ObjectNode body = objectMapper.createObjectNode();
        body.put("type", "object");
        body.put("description", "响应体");
        properties.set("body", body);
        
        // headers字段
        ObjectNode headers = objectMapper.createObjectNode();
        headers.put("type", "object");
        headers.put("description", "响应头");
        properties.set("headers", headers);
        
        // elapsed字段
        ObjectNode elapsed = objectMapper.createObjectNode();
        elapsed.put("type", "number");
        elapsed.put("description", "耗时(ms)");
        properties.set("elapsed", elapsed);
        
        schema.set("properties", properties);
        return schema;
    }
    
    @Override
    public void validate(NodeInput input) {
        // 验证必需参数
        input.getStringRequired("url");
        
        String method = input.getString("method", "GET");
        if (!isValidHttpMethod(method)) {
            throw new IllegalArgumentException("Invalid HTTP method: " + method);
        }
        
        Integer timeout = input.getInteger("timeout");
        if (timeout != null && timeout < 0) {
            throw new IllegalArgumentException("Timeout must be non-negative");
        }
    }
    
    @Override
    public NodeExecutionResult execute(NodeInput input, NodeExecutionContext context) {
        LocalDateTime startTime = LocalDateTime.now();
        
        try {
            // 验证输入参数
            validate(input);
            
            // 获取参数（表达式已被解析）
            String url = input.getStringRequired("url");
            String method = input.getString("method", "GET");
            Map<String, Object> headers = input.getMap("headers", new HashMap<>());
            String body = input.getString("body");
            Integer timeout = input.getInteger("timeout", 30000);
            
            log.info("执行HTTP请求: {} {}", method, url);
            
            // 构建HTTP请求
            HttpHeaders httpHeaders = new HttpHeaders();
            
            // 设置默认Content-Type
            if (body != null && !body.trim().isEmpty() && !headers.containsKey("Content-Type")) {
                httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            }
            
            // 添加自定义头
            for (Map.Entry<String, Object> entry : headers.entrySet()) {
                httpHeaders.set(entry.getKey(), entry.getValue().toString());
            }
            
            HttpEntity<String> entity = new HttpEntity<>(body, httpHeaders);
            
            // 发送请求
            long requestStart = System.currentTimeMillis();
            ResponseEntity<String> response = restTemplate.exchange(
                url,
                HttpMethod.valueOf(method.toUpperCase()),
                entity,
                String.class
            );
            long requestEnd = System.currentTimeMillis();
            long elapsed = requestEnd - requestStart;
            
            // 解析响应体
            Object responseBody = parseResponseBody(response.getBody());
            
            // 构建输出
            Map<String, Object> output = new HashMap<>();
            output.put("statusCode", response.getStatusCode().value());
            output.put("body", responseBody);
            output.put("headers", response.getHeaders().toSingleValueMap());
            output.put("elapsed", elapsed);
            
            LocalDateTime endTime = LocalDateTime.now();
            log.info("HTTP请求成功: {} {}, 状态码: {}, 耗时: {}ms", 
                    method, url, response.getStatusCode().value(), elapsed);
            
            return NodeExecutionResult.success(output, startTime, endTime);
            
        } catch (Exception e) {
            LocalDateTime endTime = LocalDateTime.now();
            log.error("HTTP请求执行失败: {}", e.getMessage(), e);
            
            // 构建错误输出
            Map<String, Object> output = new HashMap<>();
            output.put("statusCode", -1);
            output.put("body", null);
            output.put("headers", new HashMap<>());
            output.put("elapsed", 0);
            output.put("error", e.getMessage());
            
            return NodeExecutionResult.failed(e.getMessage(), e.getClass().getSimpleName(), startTime, endTime);
        }
    }
    
    /**
     * 解析响应体
     */
    private Object parseResponseBody(String responseBody) {
        if (responseBody == null || responseBody.trim().isEmpty()) {
            return null;
        }
        
        try {
            // 尝试解析为JSON
            return objectMapper.readValue(responseBody, Object.class);
        } catch (Exception e) {
            // 解析失败，返回原始文本
            log.debug("响应体不是有效的JSON，返回原始文本: {}", e.getMessage());
            return responseBody;
        }
    }
    
    /**
     * 验证HTTP方法是否有效
     */
    private boolean isValidHttpMethod(String method) {
        try {
            HttpMethod.valueOf(method.toUpperCase());
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}