package com.qqchen.deploy.backend.framework.annotation.formily;

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 java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FormilySchemaFactory {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 生成Formily JSON Schema
     * @param clazz 带有FormilyForm和FormilyField注解的类
     * @return Formily JSON Schema
     */
    public static JsonNode generateSchema(Class<?> clazz) {
        if (clazz == null) {
            throw new IllegalArgumentException("Class cannot be null");
        }

        // 获取所有字段，包括父类的字段
        List<Field> allFields = getAllFields(clazz);
        if (allFields.isEmpty()) {
            throw new IllegalArgumentException("No fields found in class: " + clazz.getName());
        }

        // 获取最近的带有FormilyForm注解的类（可能是父类）
        Class<?> formClass = findNearestFormClass(clazz);
        if (formClass == null) {
            throw new IllegalArgumentException("No @FormilyForm annotation found in class hierarchy: " + clazz.getName());
        }

        FormilyForm formDef = formClass.getAnnotation(FormilyForm.class);
        ObjectNode schema = objectMapper.createObjectNode();
        
        // 基础属性
        schema.put("type", "object");
        schema.put("version", formDef.version());
        schema.put("name", formDef.name());
        schema.put("validateFirst", formDef.validateFirst());
        
        if (!formDef.description().isEmpty()) {
            schema.put("description", formDef.description());
        }

        // 表单布局配置
        ObjectNode formProps = schema.putObject("x-props");
        formProps.put("labelCol", formDef.labelCol());
        formProps.put("wrapperCol", formDef.wrapperCol());

        ObjectNode properties = schema.putObject("properties");
        boolean hasFields = false;

        // 将字段按order排序
        List<Field> sortedFields = allFields.stream()
            .filter(field -> field.isAnnotationPresent(FormilyField.class))
            .sorted((f1, f2) -> {
                FormilyField a1 = f1.getAnnotation(FormilyField.class);
                FormilyField a2 = f2.getAnnotation(FormilyField.class);
                return Integer.compare(a1.order(), a2.order());
            })
            .collect(Collectors.toList());

        for (Field field : sortedFields) {
            FormilyField fieldDef = field.getAnnotation(FormilyField.class);
            properties.set(field.getName(), generateFieldSchema(fieldDef));
            hasFields = true;
        }

        if (!hasFields) {
            throw new IllegalArgumentException("No @FormilyField annotations found in class hierarchy: " + clazz.getName());
        }

        return schema;
    }

    private static JsonNode generateFieldSchema(FormilyField field) {
        ObjectNode fieldSchema = objectMapper.createObjectNode();

        // 基础属性
        fieldSchema.put("type", field.type());
        fieldSchema.put("title", field.title());
        if (!field.description().isEmpty()) {
            fieldSchema.put("description", field.description());
        }
        if (!field.defaultValue().isEmpty()) {
            fieldSchema.put("default", field.defaultValue());
        }
        if (!field.tooltip().isEmpty()) {
            fieldSchema.put("tooltip", field.tooltip());
        }

        // 组件属性
        fieldSchema.put("x-decorator", field.decorator());
        fieldSchema.put("x-component", field.component());

        // 装饰器属性
        ObjectNode decoratorProps = generateDecoratorProps(field);
        if (decoratorProps.size() > 0) {
            fieldSchema.set("x-decorator-props", decoratorProps);
        }

        // 组件属性
        if ("map".equals(field.type())) {
            generateMapSchema(fieldSchema, field.mapConfig());
        } else {
            ObjectNode componentProps = generateComponentProps(field.props(), field.component());
            if (componentProps.size() > 0) {
                fieldSchema.set("x-component-props", componentProps);
            }
        }

        // 验证规则
        if (field.validators().length > 0 || field.required()) {
            ArrayNode validators = fieldSchema.putArray("x-validator");
            if (field.required()) {
                ObjectNode requiredValidator = objectMapper.createObjectNode();
                requiredValidator.put("required", true);
                requiredValidator.put("message", "此项为必填项");
                validators.add(requiredValidator);
            }
            for (FormilyValidator validator : field.validators()) {
                validators.add(generateValidator(validator));
            }
        }

        // 联动配置
        if (field.reactions().length > 0) {
            ArrayNode reactions = fieldSchema.putArray("x-reactions");
            for (FormilyReaction reaction : field.reactions()) {
                reactions.add(generateReaction(reaction));
            }
        }

        // 展示控制
        fieldSchema.put("x-pattern", field.pattern());
        fieldSchema.put("x-display", field.display());
        fieldSchema.put("x-hidden", field.hidden());

        return fieldSchema;
    }

    private static ObjectNode generateDecoratorProps(FormilyField field) {
        ObjectNode props = objectMapper.createObjectNode();
        
        if (field.gridSpan() > 1) {
            props.put("gridSpan", field.gridSpan());
        }
        if (!field.tooltip().isEmpty()) {
            props.put("tooltip", field.tooltip());
        }
        if (field.required()) {
            props.put("asterisk", true);
        }
        
        return props;
    }

    private static ObjectNode generateComponentProps(FormilyComponentProps props, String componentType) {
        ObjectNode node = objectMapper.createObjectNode();
        
        // 通用属性
        if (!props.placeholder().isEmpty()) {
            node.put("placeholder", props.placeholder());
        }
        if (props.disabled()) {
            node.put("disabled", true);
        }
        if (props.loading()) {
            node.put("loading", true);
        }
        
        // Select组件属性
        if ("Select".equals(componentType)) {
            if (!props.labelField().equals("label")) {
                node.put("labelField", props.labelField());
            }
            if (!props.valueField().equals("value")) {
                node.put("valueField", props.valueField());
            }
            if (props.allowClear()) {
                node.put("allowClear", true);
            }
            if (props.showSearch()) {
                node.put("showSearch", true);
            }
            if (!props.mode().isEmpty()) {
                node.put("mode", props.mode());
            }
            node.put("filterOption", props.filterOption());
            
            if (props.enum_().length > 0) {
                ArrayNode enumValues = node.putArray("enum");
                Arrays.stream(props.enum_()).forEach(enumValues::add);
            }
            if (props.enumNames().length > 0) {
                ArrayNode enumNames = node.putArray("enumNames");
                Arrays.stream(props.enumNames()).forEach(enumNames::add);
            }
        }
        
        // MonacoEditor组件属性
        if ("MonacoEditor".equals(componentType)) {
            FormilyEditorProps editorProps = props.editor();
            ObjectNode options = node.putObject("options");
            
            options.put("language", editorProps.language());
            options.put("theme", editorProps.theme());
            options.put("minimap", editorProps.minimap());
            options.put("lineNumbers", editorProps.lineNumbers());
            options.put("wordWrap", editorProps.wordWrap());
            options.put("fontSize", editorProps.fontSize());
            options.put("tabSize", editorProps.tabSize());
            options.put("automaticLayout", editorProps.automaticLayout());
            options.put("folding", editorProps.folding());
            options.put("scrollBeyondLastLine", editorProps.scrollBeyondLastLine());
            options.put("suggestOnTriggerCharacters", editorProps.suggestOnTriggerCharacters());
            options.put("snippetsPreventQuickSuggestions", editorProps.snippetsPreventQuickSuggestions());
            
            ObjectNode scrollbar = options.putObject("scrollbar");
            scrollbar.put("vertical", editorProps.scrollbarVertical());
            scrollbar.put("horizontal", editorProps.scrollbarHorizontal());
            
            node.put("debounceTime", editorProps.debounceTime());
            node.put("readOnly", editorProps.readOnly());
        }

        return node;
    }

    private static void generateMapSchema(ObjectNode fieldSchema, FormilyMapConfig config) {
        fieldSchema.put("x-component", "ArrayItems");
        
        // Map组件属性
        ObjectNode componentProps = fieldSchema.putObject("x-component-props");
        componentProps.put("allowAdd", config.allowAdd());
        componentProps.put("allowRemove", config.allowRemove());
        componentProps.put("allowCustomKey", config.allowCustomKey());

        // 生成Map项的Schema
        ObjectNode items = fieldSchema.putObject("items");
        items.put("type", "object");
        items.put("x-component", "ArrayItems.Item");

        // 生成Map项的属性Schema
        ObjectNode properties = items.putObject("properties");

        // 键的Schema
        ObjectNode keySchema = properties.putObject("key");
        keySchema.put("type", "string");
        keySchema.put("title", config.keyTitle());
        keySchema.put("x-decorator", "FormItem");
        keySchema.put("x-component", config.keyComponent());
        
        ObjectNode keyProps = generateComponentProps(config.keyProps(), config.keyComponent());
        if (keyProps.size() > 0) {
            keySchema.set("x-component-props", keyProps);
        }

        // 值的Schema
        ObjectNode valueSchema = properties.putObject("value");
        valueSchema.put("type", "string");
        valueSchema.put("title", config.valueTitle());
        valueSchema.put("x-decorator", "FormItem");
        valueSchema.put("x-component", config.valueComponent());
        
        ObjectNode valueProps = generateComponentProps(config.valueProps(), config.valueComponent());
        if (valueProps.size() > 0) {
            valueSchema.set("x-component-props", valueProps);
        }

        // 操作按钮
        ObjectNode operationSchema = properties.putObject("operations");
        operationSchema.put("type", "void");
        operationSchema.put("x-component", "ArrayItems.Remove");

        // 添加按钮
        ObjectNode addition = fieldSchema.putObject("properties").putObject("addition");
        addition.put("type", "void");
        addition.put("title", config.addText());
        addition.put("x-component", "ArrayItems.Addition");
    }

    private static JsonNode generateValidator(FormilyValidator validator) {
        ObjectNode node = objectMapper.createObjectNode();
        
        if (validator.required()) {
            node.put("required", true);
        }
        if (!validator.message().isEmpty()) {
            node.put("message", validator.message());
        }
        if (!validator.format().isEmpty()) {
            node.put("format", validator.format());
        }
        if (!validator.pattern().isEmpty()) {
            node.put("pattern", validator.pattern());
        }
        if (validator.whitespace()) {
            node.put("whitespace", true);
        }
        if (validator.min() != Double.MIN_VALUE) {
            node.put("min", validator.min());
        }
        if (validator.max() != Double.MAX_VALUE) {
            node.put("max", validator.max());
        }
        if (validator.minLength() != -1) {
            node.put("minLength", validator.minLength());
        }
        if (validator.maxLength() != -1) {
            node.put("maxLength", validator.maxLength());
        }
        if (!validator.triggerType().isEmpty()) {
            node.put("triggerType", validator.triggerType());
        }
        if (!validator.validator().isEmpty()) {
            node.put("validator", validator.validator());
        }
        if (!validator.asyncValidator().isEmpty()) {
            node.put("asyncValidator", validator.asyncValidator());
        }

        return node;
    }

    private static JsonNode generateReaction(FormilyReaction reaction) {
        ObjectNode node = objectMapper.createObjectNode();
        
        if (reaction.dependencies().length > 0) {
            ArrayNode dependencies = node.putArray("dependencies");
            Arrays.stream(reaction.dependencies()).forEach(dependencies::add);
        }
        
        if (!reaction.when().isEmpty()) {
            node.put("when", reaction.when());
        }

        ObjectNode fulfill = node.putObject("fulfill");
        
        // 处理run配置
        if (!reaction.run().isEmpty()) {
            fulfill.put("run", reaction.run());
        }
        
        ObjectNode state = fulfill.putObject("state");
        
        // 处理loading状态
        if (reaction.showLoading()) {
            state.put("loading", false);
        }
        
        // 处理数据源
        if (!reaction.state().isEmpty()) {
            state.put(reaction.state(), reaction.value());
        }
        
        if (!reaction.onSuccess().isEmpty()) {
            fulfill.put("onSuccess", reaction.onSuccess());
        }
        
        if (!reaction.onError().isEmpty()) {
            fulfill.put("onError", reaction.onError());
        }
        
        if (reaction.immediate()) {
            node.put("immediate", true);
        }
        
        if (reaction.runOnMounted()) {
            node.put("runOnMounted", true);
        }
        
        if (reaction.debounceTime() != 100) {
            node.put("debounceTime", reaction.debounceTime());
        }

        return node;
    }

    private static List<Field> getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        Class<?> currentClass = clazz;
        
        while (currentClass != null && currentClass != Object.class) {
            fields.addAll(Arrays.asList(currentClass.getDeclaredFields()));
            currentClass = currentClass.getSuperclass();
        }
        
        return fields;
    }

    private static Class<?> findNearestFormClass(Class<?> clazz) {
        Class<?> currentClass = clazz;
        
        while (currentClass != null && currentClass != Object.class) {
            if (currentClass.isAnnotationPresent(FormilyForm.class)) {
                return currentClass;
            }
            currentClass = currentClass.getSuperclass();
        }
        
        return null;
    }
} 