package com.qqchen.deploy.backend.workflow.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.qqchen.deploy.backend.workflow.annotation.SchemaProperty;
import com.qqchen.deploy.backend.workflow.annotation.SchemaPropertyDataSource;
import com.qqchen.deploy.backend.workflow.annotation.SchemaPropertyDataSourceParam;
import com.qqchen.deploy.backend.workflow.annotation.CodeEditorConfig;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class GenerateSchemaUtils {

    public static ObjectNode generateSchema(Class<?> cls) {
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode schema = mapper.createObjectNode();
        schema.put("type", "object");

        // 处理属性
        ObjectNode properties = schema.putObject("properties");
        List<String> required = new ArrayList<>();

        // 获取所有字段，包括父类的字段
        List<Field> allFields = getAllFields(cls);
        
        // 按SchemaProperty的order排序
        allFields.sort((a, b) -> {
            SchemaProperty annotationA = a.getAnnotation(SchemaProperty.class);
            SchemaProperty annotationB = b.getAnnotation(SchemaProperty.class);
            if (annotationA == null && annotationB == null) {
                return 0;
            }
            if (annotationA == null) {
                return 1;
            }
            if (annotationB == null) {
                return -1;
            }
            return Integer.compare(annotationA.order(), annotationB.order());
        });

        // 遍历所有字段
        for (Field field : allFields) {
            SchemaProperty annotation = field.getAnnotation(SchemaProperty.class);
            if (annotation != null) {
                ObjectNode property = properties.putObject(field.getName());

                // 设置基本属性
                String jsonType = getJsonSchemaType(field.getType());
                property.put("type", jsonType);

                // 从注解中获取属性
                if (!annotation.title().isEmpty()) {
                    property.put("title", annotation.title());
                }
                if (!annotation.description().isEmpty()) {
                    property.put("description", annotation.description());
                }
                if (annotation.readOnly()) {
                    property.put("readOnly", true);
                }
                if (!annotation.format().isEmpty()) {
                    property.put("format", annotation.format());
                    
                    // 处理代码编辑器配置
                    if (annotation.format().endsWith("-editor")) {
                        CodeEditorConfig editorConfig = annotation.codeEditor();
                        if (editorConfig != null && !editorConfig.language().isEmpty()) {
                            ObjectNode configNode = property.putObject("editorConfig");
                            configNode.put("language", editorConfig.language());
                            configNode.put("theme", editorConfig.theme());
                            configNode.put("minimap", editorConfig.minimap());
                            configNode.put("lineNumbers", editorConfig.lineNumbers());
                            configNode.put("wordWrap", editorConfig.wordWrap());
                            configNode.put("fontSize", editorConfig.fontSize());
                            configNode.put("tabSize", editorConfig.tabSize());
                            configNode.put("autoComplete", editorConfig.autoComplete());
                            configNode.put("folding", editorConfig.folding());
                        }
                    }
                }
                if (annotation.required()) {
                    required.add(field.getName());
                }
                if (annotation.defaultValue().length() > 0) {
                    if (jsonType.equals("integer")) {
                        property.put("default", Integer.parseInt(annotation.defaultValue()));
                    } else if (jsonType.equals("number")) {
                        property.put("default", Double.parseDouble(annotation.defaultValue()));
                    } else {
                        property.put("default", annotation.defaultValue());
                    }
                }

                // 处理枚举
                if (annotation.enumValues().length > 0) {
                    ArrayNode enumNode = property.putArray("enum");
                    for (String value : annotation.enumValues()) {
                        enumNode.add(value);
                    }

                    if (annotation.enumNames().length > 0) {
                        ArrayNode enumNamesNode = property.putArray("enumNames");
                        for (String name : annotation.enumNames()) {
                            enumNamesNode.add(name);
                        }
                    }
                }

                // 处理数组类型
                if (List.class.isAssignableFrom(field.getType())) {
                    ObjectNode items = property.putObject("items");
                    items.put("type", "string");
                    
                    // 如果有枚举值定义，则在items中设置枚举相关属性
                    if (annotation.enumValues().length > 0) {
                        // 在items中设置enum
                        ArrayNode enumNode = items.putArray("enum");
                        for (String value : annotation.enumValues()) {
                            enumNode.add(value);
                        }

                        // 在items中设置enumNames
                        if (annotation.enumNames().length > 0) {
                            ArrayNode enumNamesNode = items.putArray("enumNames");
                            for (String name : annotation.enumNames()) {
                                enumNamesNode.add(name);
                            }
                        }
                    }
                    
                    // 只在数组类型时移除顶层的enum和enumNames
                    property.remove("enum");
                    property.remove("enumNames");
                }

                // 处理Map类型
                if (Map.class.isAssignableFrom(field.getType())) {
                    ObjectNode additionalProperties = property.putObject("additionalProperties");
                    additionalProperties.put("type", "string");
                }

                // 处理嵌套对象
                if (property.get("type").asText().equals("object") && !Map.class.isAssignableFrom(field.getType()) && !field.getType().getName().startsWith("java.")) {
                    ObjectNode nestedSchema = generateSchema(field.getType());
                    if (nestedSchema.has("properties")) {
                        property.set("properties", nestedSchema.get("properties"));
                    }
                    if (nestedSchema.has("required")) {
                        property.set("required", nestedSchema.get("required"));
                    }
                }

                // 处理数据源
                SchemaPropertyDataSource dataSource = annotation.dataSource();
                if (dataSource != null && !dataSource.type().isEmpty()) {
                    processDataSource(property, dataSource);
                }
            }
        }

        // 添加required字段
        if (!required.isEmpty()) {
            ArrayNode requiredNode = schema.putArray("required");
            required.forEach(requiredNode::add);
        }
        return schema;
    }

    /**
     * 处理SchemaPropertyDataSource注解，生成数据源配置
     *
     * @param property   当前属性节点
     * @param dataSource 数据源注解
     */
    private static void processDataSource(ObjectNode property, SchemaPropertyDataSource dataSource) {
        ObjectNode dataSourceNode = property.putObject("dataSource");

        // 处理基本属性
        dataSourceNode.put("type", dataSource.type());
        dataSourceNode.put("url", dataSource.url());
        dataSourceNode.put("valueField", dataSource.valueField());
        dataSourceNode.put("labelField", dataSource.labelField());

        // 处理依赖字段
        String[] dependsOn = dataSource.dependsOn();
        if (dependsOn != null && dependsOn.length > 0) {
            ArrayNode dependsOnNode = dataSourceNode.putArray("dependsOn");
            for (String depend : dependsOn) {
                dependsOnNode.add(depend);
            }
        }

        // 处理请求参数
        SchemaPropertyDataSourceParam[] params = dataSource.params();
        if (params != null && params.length > 0) {
            ObjectNode paramsNode = dataSourceNode.putObject("params");
            for (SchemaPropertyDataSourceParam param : params) {
                paramsNode.put(param.name(), param.value());
            }
        }

//        // 处理其他可选属性
//        if (!dataSource.method().isEmpty()) {
//            dataSourceNode.put("method", dataSource.method());
//        }
//        if (!dataSource.searchField().isEmpty()) {
//            dataSourceNode.put("searchField", dataSource.searchField());
//        }
    }

    /**
     * 获取类的所有字段，包括父类的字段
     */
    private static List<Field> getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        Class<?> currentClass = clazz;

        // 遍历类的继承层次
        while (currentClass != null && !currentClass.equals(Object.class)) {
            // 添加当前类的字段
            fields.addAll(Arrays.asList(currentClass.getDeclaredFields()));
            // 获取父类
            currentClass = currentClass.getSuperclass();
        }

        return fields;
    }

    private static String getJsonSchemaType(Class<?> type) {
        if (String.class.equals(type)) {
            return "string";
        } else if (Integer.class.equals(type) || int.class.equals(type) || Long.class.equals(type) || long.class.equals(type)) {
            return "integer";
        } else if (Double.class.equals(type) || double.class.equals(type) || Float.class.equals(type) || float.class.equals(type)) {
            return "number";
        } else if (Boolean.class.equals(type) || boolean.class.equals(type)) {
            return "boolean";
        } else if (List.class.isAssignableFrom(type)) {
            return "array";
        } else if (Map.class.isAssignableFrom(type)) {
            return "object";
        } else {
            return "object";
        }
    }
}
