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

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

public class FormilySchemaFactoryTest {

    @Test
    public void testGenerateSchema() throws Exception {
        JsonNode schema = FormilySchemaFactory.generateSchema(CascadeForm.class);

        // 打印生成的Schema
        ObjectMapper mapper = new ObjectMapper();
        System.out.println("Generated Schema:");
        System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));

        // 验证基本结构
        assertEquals("object", schema.get("type").asText());
        assertEquals("2.0", schema.get("version").asText());
        assertEquals("级联选择表单", schema.get("name").asText());
        assertTrue(schema.get("validateFirst").asBoolean());
        
        // 验证表单布局
        JsonNode xProps = schema.get("x-props");
        assertEquals(6, xProps.get("labelCol").asInt());
        assertEquals(18, xProps.get("wrapperCol").asInt());

        // 验证字段A（系统选择）
        JsonNode fieldA = schema.get("properties").get("systemId");
        assertEquals("string", fieldA.get("type").asText());
        assertEquals("选择系统", fieldA.get("title").asText());
        assertEquals("Select", fieldA.get("x-component").asText());
        assertEquals("FormItem", fieldA.get("x-decorator").asText());
        
        // 验证装饰器属性
        JsonNode decoratorPropsA = fieldA.get("x-decorator-props");
        assertTrue(decoratorPropsA.get("asterisk").asBoolean());
        
        // 验证组件属性
        JsonNode propsA = fieldA.get("x-component-props");
        assertEquals("请选择系统", propsA.get("placeholder").asText());
        assertEquals("name", propsA.get("labelField").asText());
        assertEquals("id", propsA.get("valueField").asText());
        assertTrue(propsA.get("showSearch").asBoolean());
        assertEquals("single", propsA.get("mode").asText());
        assertTrue(propsA.get("filterOption").asBoolean());
        
        // 验证验证规则
        JsonNode validatorA = fieldA.get("x-validator").get(0);
        assertTrue(validatorA.get("required").asBoolean());
        assertEquals("此项为必填项", validatorA.get("message").asText());
        
        // 验证展示控制
        assertEquals("editable", fieldA.get("x-pattern").asText());
        assertEquals("visible", fieldA.get("x-display").asText());
        assertFalse(fieldA.get("x-hidden").asBoolean());

        // 验证字段B（视图选择）
        JsonNode fieldB = schema.get("properties").get("viewId");
        JsonNode reactionsB = fieldB.get("x-reactions");
        JsonNode reactionB = reactionsB.get(0);
        
        // 验证B依赖于A
        assertTrue(reactionB.has("dependencies"));
        JsonNode depsB = reactionB.get("dependencies");
        assertTrue(depsB.isArray());
        assertEquals("systemId", depsB.get(0).asText());
        
        // 验证B的条件
        assertEquals("{{$deps.systemId}}", reactionB.get("when").asText());
        
        // 验证B的数据源
        JsonNode fulfillB = reactionB.get("fulfill");
        JsonNode stateB = fulfillB.get("state");
        assertFalse(stateB.get("loading").asBoolean());
        assertEquals("{{$fetch('/api/v1/views?systemId=' + $deps.systemId).then(data => data.data)}}", 
            stateB.get("dataSource").asText());

        // 验证字段C（任务选择）
        JsonNode fieldC = schema.get("properties").get("jobId");
        JsonNode reactionsC = fieldC.get("x-reactions");
        JsonNode reactionC = reactionsC.get(0);
        
        // 验证C依赖于A和B
        JsonNode depsC = reactionC.get("dependencies");
        assertEquals(2, depsC.size());
        assertEquals("systemId", depsC.get(0).asText());
        assertEquals("viewId", depsC.get(1).asText());
        
        // 验证C的条件
        assertEquals("{{$deps.systemId && $deps.viewId}}", reactionC.get("when").asText());
        
        // 验证C的数据源
        JsonNode fulfillC = reactionC.get("fulfill");
        JsonNode stateC = fulfillC.get("state");
        assertFalse(stateC.get("loading").asBoolean());
        assertEquals(
            "{{$fetch('/api/v1/jobs?systemId=' + $deps.systemId + '&viewId=' + $deps.viewId).then(data => data.data)}}", 
            stateC.get("dataSource").asText());
    }
}

@FormilyForm(
    name = "级联选择表单",
    version = "2.0",
    validateFirst = true,
    labelCol = 6,
    wrapperCol = 18
)
class CascadeForm {
    @FormilyField(
        title = "选择系统",
        component = "Select",
        order = 1,
        required = true,
        props = @FormilyComponentProps(
            labelField = "name",
            valueField = "id",
            showSearch = true,
            mode = "single",
            filterOption = true,
            placeholder = "请选择系统"
        ),
        reactions = {
            @FormilyReaction(
                state = "dataSource",
                value = "{{$fetch('/api/v1/systems').then(data => data.data)}}",
                showLoading = true
            )
        }
    )
    private String systemId;

    @FormilyField(
        title = "选择视图",
        component = "Select",
        order = 2,
        required = true,
        props = @FormilyComponentProps(
            labelField = "name",
            valueField = "id",
            showSearch = true,
            mode = "single",
            filterOption = true,
            placeholder = "请选择视图"
        ),
        reactions = {
            @FormilyReaction(
                dependencies = {"systemId"},
                when = "{{$deps.systemId}}",
                state = "dataSource",
                value = "{{$fetch('/api/v1/views?systemId=' + $deps.systemId).then(data => data.data)}}",
                showLoading = true
            )
        }
    )
    private String viewId;

    @FormilyField(
        title = "选择任务",
        component = "Select",
        order = 3,
        required = true,
        props = @FormilyComponentProps(
            labelField = "name",
            valueField = "id",
            showSearch = true,
            mode = "single",
            filterOption = true,
            placeholder = "请选择任务"
        ),
        reactions = {
            @FormilyReaction(
                dependencies = {"systemId", "viewId"},
                when = "{{$deps.systemId && $deps.viewId}}",
                state = "dataSource",
                value = "{{$fetch('/api/v1/jobs?systemId=' + $deps.systemId + '&viewId=' + $deps.viewId).then(data => data.data)}}",
                showLoading = true
            )
        }
    )
    private String jobId;
} 