package com.flowable.devops.integration;

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.WorkflowDefinition;
import com.flowable.devops.service.WorkflowService;
import com.flowable.devops.service.WorkflowService.WorkflowExecutionResult;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;

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

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

/**
 * 工作流端到端集成测试
 * 
 * 测试完整流程：
 * 1. 创建工作流定义（包含HTTP请求节点和审批节点）
 * 2. 激活工作流
 * 3. 执行工作流
 * 4. 处理审批任务
 * 5. 验证执行结果
 */
@SpringBootTest
@ActiveProfiles("test")
@Transactional
public class WorkflowIntegrationTest {
    
    @Autowired
    private WorkflowService workflowService;
    
    @Autowired
    private RuntimeService runtimeService;
    
    @Autowired
    private TaskService taskService;
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    /**
     * 端到端工作流测试：HTTP请求 → 审批
     */
    @Test
    public void testHttpRequestToApprovalWorkflow() throws Exception {
        // 1. 创建工作流定义
        WorkflowDefinition workflow = createHttpToApprovalWorkflow();
        WorkflowDefinition created = workflowService.create(workflow);
        
        assertNotNull(created);
        assertNotNull(created.getId());
        assertEquals(WorkflowDefinition.WorkflowStatus.DRAFT, created.getStatus());
        
        // 2. 激活工作流
        WorkflowDefinition activated = workflowService.activate(created.getId());
        
        assertEquals(WorkflowDefinition.WorkflowStatus.ACTIVE, activated.getStatus());
        assertNotNull(activated.getFlowableProcessDefinitionId());
        assertNotNull(activated.getFlowableDeploymentId());
        
        // 3. 执行工作流
        Map<String, Object> input = new HashMap<>();
        input.put("userId", "test_user_001");
        input.put("requestData", Map.of("type", "approval_request"));
        
        WorkflowExecutionResult result = workflowService.execute(created.getId(), input);
        
        assertNotNull(result);
        assertNotNull(result.getProcessInstanceId());
        assertNotNull(result.getExecutionId());
        assertEquals("running", result.getStatus()); // 应该在审批节点暂停
        assertNotNull(result.getStartedAt());
        assertNull(result.getEndedAt()); // 尚未结束
        
        // 4. 验证审批任务存在
        List<Task> tasks = taskService.createTaskQuery()
                .processInstanceId(result.getProcessInstanceId())
                .list();
        
        assertFalse(tasks.isEmpty(), "应该存在待办审批任务");
        Task approvalTask = tasks.get(0);
        assertEquals("审批", approvalTask.getName());
        
        // 5. 完成审批任务
        Map<String, Object> approvalResult = new HashMap<>();
        approvalResult.put("approved", true);
        approvalResult.put("comment", "测试通过");
        
        taskService.complete(approvalTask.getId(), approvalResult);
        
        // 6. 验证工作流完成
        // 等待工作流结束
        Thread.sleep(1000);
        
        // 检查流程实例是否已结束
        boolean isEnded = runtimeService.createProcessInstanceQuery()
                .processInstanceId(result.getProcessInstanceId())
                .count() == 0;
        
        assertTrue(isEnded, "工作流应该已完成");
        
        // 7. 验证执行历史
        WorkflowService.WorkflowExecutionDetail detail = workflowService
                .getExecutionDetail(result.getExecutionId());
        
        assertNotNull(detail);
        assertEquals("completed", detail.getStatus());
        assertNotNull(detail.getEndedAt());
    }
    
    /**
     * 测试条件分支工作流
     */
    @Test
    public void testConditionalWorkflow() throws Exception {
        // 1. 创建带条件分支的工作流
        WorkflowDefinition workflow = createConditionalWorkflow();
        WorkflowDefinition created = workflowService.create(workflow);
        WorkflowDefinition activated = workflowService.activate(created.getId());
        
        // 2. 测试分支1：金额 > 1000
        Map<String, Object> highAmountInput = new HashMap<>();
        highAmountInput.put("amount", 1500);
        highAmountInput.put("applicant", "张三");
        
        WorkflowExecutionResult result1 = workflowService.execute(created.getId(), highAmountInput);
        assertEquals("running", result1.getStatus());
        
        // 验证高金额审批任务存在
        List<Task> highAmountTasks = taskService.createTaskQuery()
                .processInstanceId(result1.getProcessInstanceId())
                .list();
        
        assertFalse(highAmountTasks.isEmpty());
        assertEquals("高级审批", highAmountTasks.get(0).getName());
        
        // 3. 测试分支2：金额 <= 1000  
        Map<String, Object> lowAmountInput = new HashMap<>();
        lowAmountInput.put("amount", 800);
        lowAmountInput.put("applicant", "李四");
        
        WorkflowExecutionResult result2 = workflowService.execute(created.getId(), lowAmountInput);
        assertEquals("running", result2.getStatus());
        
        // 验证低金额审批任务存在
        List<Task> lowAmountTasks = taskService.createTaskQuery()
                .processInstanceId(result2.getProcessInstanceId())
                .list();
        
        assertFalse(lowAmountTasks.isEmpty());
        assertEquals("普通审批", lowAmountTasks.get(0).getName());
    }
    
    /**
     * 创建HTTP请求 → 审批的工作流定义
     */
    private WorkflowDefinition createHttpToApprovalWorkflow() {
        WorkflowDefinition workflow = new WorkflowDefinition();
        workflow.setId("test_http_approval_workflow");
        workflow.setName("HTTP请求审批工作流");
        workflow.setDescription("测试用工作流：HTTP请求后进行审批");
        
        ObjectNode definition = objectMapper.createObjectNode();
        definition.put("id", workflow.getId());
        definition.put("name", workflow.getName());
        definition.put("schemaVersion", "1.0");
        
        // 节点定义
        ArrayNode nodes = objectMapper.createArrayNode();
        
        // HTTP请求节点
        ObjectNode httpNode = objectMapper.createObjectNode();
        httpNode.put("id", "http_request_1");
        httpNode.put("name", "API调用");
        httpNode.put("type", "http_request");
        
        ObjectNode httpPos = objectMapper.createObjectNode();
        httpPos.put("x", 100);
        httpPos.put("y", 100);
        httpNode.set("position", httpPos);
        
        ObjectNode httpConfig = objectMapper.createObjectNode();
        httpConfig.put("url", "https://jsonplaceholder.typicode.com/posts/1");
        httpConfig.put("method", "GET");
        httpConfig.put("timeout", 30000);
        httpNode.set("config", httpConfig);
        
        nodes.add(httpNode);
        
        // 审批节点
        ObjectNode approvalNode = objectMapper.createObjectNode();
        approvalNode.put("id", "approval_1");
        approvalNode.put("name", "审批");
        approvalNode.put("type", "approval");
        
        ObjectNode approvalPos = objectMapper.createObjectNode();
        approvalPos.put("x", 300);
        approvalPos.put("y", 100);
        approvalNode.set("position", approvalPos);
        
        ObjectNode approvalConfig = objectMapper.createObjectNode();
        approvalConfig.put("assignee", "admin");
        approvalNode.set("config", approvalConfig);
        
        nodes.add(approvalNode);
        
        definition.set("nodes", nodes);
        
        // 连线定义
        ArrayNode edges = objectMapper.createArrayNode();
        
        ObjectNode edge = objectMapper.createObjectNode();
        edge.put("source", "http_request_1");
        edge.put("target", "approval_1");
        
        edges.add(edge);
        
        definition.set("edges", edges);
        
        workflow.setDefinition(definition);
        return workflow;
    }
    
    /**
     * 创建带条件分支的工作流定义
     */
    private WorkflowDefinition createConditionalWorkflow() {
        WorkflowDefinition workflow = new WorkflowDefinition();
        workflow.setId("test_conditional_workflow");
        workflow.setName("条件分支工作流");
        workflow.setDescription("根据金额自动选择审批路径");
        
        ObjectNode definition = objectMapper.createObjectNode();
        definition.put("id", workflow.getId());
        definition.put("name", workflow.getName());
        definition.put("schemaVersion", "1.0");
        
        // 节点定义
        ArrayNode nodes = objectMapper.createArrayNode();
        
        // 条件网关
        ObjectNode gatewayNode = objectMapper.createObjectNode();
        gatewayNode.put("id", "amount_check");
        gatewayNode.put("name", "金额检查");
        gatewayNode.put("type", "exclusive_gateway");
        
        ObjectNode gatewayPos = objectMapper.createObjectNode();
        gatewayPos.put("x", 100);
        gatewayPos.put("y", 100);
        gatewayNode.set("position", gatewayPos);
        
        nodes.add(gatewayNode);
        
        // 高金额审批节点
        ObjectNode highApprovalNode = objectMapper.createObjectNode();
        highApprovalNode.put("id", "high_approval");
        highApprovalNode.put("name", "高级审批");
        highApprovalNode.put("type", "approval");
        
        ObjectNode highPos = objectMapper.createObjectNode();
        highPos.put("x", 300);
        highPos.put("y", 50);
        highApprovalNode.set("position", highPos);
        
        ObjectNode highConfig = objectMapper.createObjectNode();
        highConfig.put("assignee", "manager");
        highApprovalNode.set("config", highConfig);
        
        nodes.add(highApprovalNode);
        
        // 低金额审批节点
        ObjectNode lowApprovalNode = objectMapper.createObjectNode();
        lowApprovalNode.put("id", "low_approval");
        lowApprovalNode.put("name", "普通审批");
        lowApprovalNode.put("type", "approval");
        
        ObjectNode lowPos = objectMapper.createObjectNode();
        lowPos.put("x", 300);
        lowPos.put("y", 150);
        lowApprovalNode.set("position", lowPos);
        
        ObjectNode lowConfig = objectMapper.createObjectNode();
        lowConfig.put("assignee", "supervisor");
        lowApprovalNode.set("config", lowConfig);
        
        nodes.add(lowApprovalNode);
        
        definition.set("nodes", nodes);
        
        // 连线定义（包含条件）
        ArrayNode edges = objectMapper.createArrayNode();
        
        // 高金额分支
        ObjectNode highEdge = objectMapper.createObjectNode();
        highEdge.put("source", "amount_check");
        highEdge.put("target", "high_approval");
        highEdge.put("condition", "${workflow.input.amount > 1000}");
        
        edges.add(highEdge);
        
        // 低金额分支
        ObjectNode lowEdge = objectMapper.createObjectNode();
        lowEdge.put("source", "amount_check");
        lowEdge.put("target", "low_approval");
        lowEdge.put("condition", "${workflow.input.amount <= 1000}");
        
        edges.add(lowEdge);
        
        definition.set("edges", edges);
        
        workflow.setDefinition(definition);
        return workflow;
    }
    
    /**
     * 测试表达式解析和数据映射
     */
    @Test
    public void testExpressionAndDataMapping() throws Exception {
        // 创建包含数据映射的工作流
        WorkflowDefinition workflow = createExpressionMappingWorkflow();
        WorkflowDefinition created = workflowService.create(workflow);
        WorkflowDefinition activated = workflowService.activate(created.getId());
        
        // 执行工作流
        Map<String, Object> input = new HashMap<>();
        input.put("user", Map.of(
            "id", "U001",
            "name", "测试用户",
            "email", "test@example.com",
            "department", "IT部门"
        ));
        input.put("amount", 2500);
        
        WorkflowExecutionResult result = workflowService.execute(created.getId(), input);
        
        assertNotNull(result);
        assertEquals("running", result.getStatus());
        
        // 验证节点输出数据（表达式解析结果）
        Map<String, Object> nodes = result.getNodes();
        assertNotNull(nodes);
        
        // 这里需要等待一段时间让节点执行完成
        Thread.sleep(2000);
        
        // 重新获取执行详情
        WorkflowService.WorkflowExecutionDetail detail = workflowService
                .getExecutionDetail(result.getExecutionId());
        
        assertNotNull(detail);
        // 验证节点执行的输入输出数据映射是否正确
    }
    
    /**
     * 创建包含表达式和数据映射的工作流
     */
    private WorkflowDefinition createExpressionMappingWorkflow() {
        WorkflowDefinition workflow = new WorkflowDefinition();
        workflow.setId("test_expression_mapping");
        workflow.setName("表达式映射测试工作流");
        
        ObjectNode definition = objectMapper.createObjectNode();
        definition.put("id", workflow.getId());
        definition.put("name", workflow.getName());
        definition.put("schemaVersion", "1.0");
        
        // 数据转换节点
        ArrayNode nodes = objectMapper.createArrayNode();
        
        ObjectNode transformNode = objectMapper.createObjectNode();
        transformNode.put("id", "data_transform_1");
        transformNode.put("name", "数据转换");
        transformNode.put("type", "data_transform");
        
        ObjectNode transformPos = objectMapper.createObjectNode();
        transformPos.put("x", 100);
        transformPos.put("y", 100);
        transformNode.set("position", transformPos);
        
        ObjectNode transformConfig = objectMapper.createObjectNode();
        transformConfig.put("userEmail", "${workflow.input.user.email}");
        transformConfig.put("userName", "${workflow.input.user.name}");
        transformConfig.put("isHighAmount", "${workflow.input.amount > 2000}");
        transformConfig.put("processInfo", "${workflow.input.user.name} 申请 ${workflow.input.amount} 元");
        transformNode.set("config", transformConfig);
        
        nodes.add(transformNode);
        
        // 条件审批节点
        ObjectNode conditionalApproval = objectMapper.createObjectNode();
        conditionalApproval.put("id", "conditional_approval");
        conditionalApproval.put("name", "条件审批");
        conditionalApproval.put("type", "approval");
        
        ObjectNode condPos = objectMapper.createObjectNode();
        condPos.put("x", 300);
        condPos.put("y", 100);
        conditionalApproval.set("position", condPos);
        
        ObjectNode condConfig = objectMapper.createObjectNode();
        condConfig.put("assignee", "${nodes.data_transform_1.output.isHighAmount ? 'manager' : 'supervisor'}");
        condConfig.put("description", "${nodes.data_transform_1.output.processInfo}");
        conditionalApproval.set("config", condConfig);
        
        nodes.add(conditionalApproval);
        
        definition.set("nodes", nodes);
        
        // 连线
        ArrayNode edges = objectMapper.createArrayNode();
        
        ObjectNode edge = objectMapper.createObjectNode();
        edge.put("source", "data_transform_1");
        edge.put("target", "conditional_approval");
        
        edges.add(edge);
        
        definition.set("edges", edges);
        
        workflow.setDefinition(definition);
        return workflow;
    }
}