package com.qqchen.deploy.backend.workflow.service.impl;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.workflow.dto.WorkflowNodeDefinitionDTO;
import com.qqchen.deploy.backend.workflow.dto.WorkflowNodeTypeDefinedDTO;
import com.qqchen.deploy.backend.workflow.dto.query.WorkflowDefinitionQuery;
import com.qqchen.deploy.backend.workflow.entity.WorkflowNodeDefinition;
import com.qqchen.deploy.backend.workflow.enums.NodeCategoryEnums;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums;
import com.qqchen.deploy.backend.workflow.repository.IWorkflowNodeDefinitionRepository;
import com.qqchen.deploy.backend.workflow.service.IWorkflowNodeDefinitionService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.lang.reflect.Field;
import java.util.Map;

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 static com.qqchen.deploy.backend.workflow.util.GenerateSchemaUtils.generateSchema;

/**
 * 工作流节点定义服务实现
 */
@Slf4j
@Service
public class WorkflowNodeDefinitionServiceImpl extends BaseServiceImpl<WorkflowNodeDefinition, WorkflowNodeDefinitionDTO, WorkflowDefinitionQuery, Long> implements IWorkflowNodeDefinitionService {

    @Resource
    private IWorkflowNodeDefinitionRepository workflowNodeDefinitionRepository;

    @Override
    public WorkflowNodeDefinitionDTO getByType(String type) {
        return workflowNodeDefinitionRepository.findByNodeTypeAndEnabledTrue(type)
            .map(super.converter::toDto)
            .orElse(null);
    }

    @Override
    public List<WorkflowNodeDefinitionDTO> listByCategory(NodeCategoryEnums category) {
        return workflowNodeDefinitionRepository.findByEnabledTrueAndCategory(category.name())
            .stream()
            .map(super.converter::toDto)
            .collect(Collectors.toList());
    }

    @Override
    public List<WorkflowNodeDefinitionDTO> listAllEnabled() {
        return workflowNodeDefinitionRepository.findByEnabledTrue()
            .stream()
            .map(super.converter::toDto)
            .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void enable(Long id) {
        WorkflowNodeDefinition definition = workflowNodeDefinitionRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Node definition not found: " + id));

        definition.setEnabled(true);
        workflowNodeDefinitionRepository.save(definition);
        log.info("Enabled node definition: {}", id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void disable(Long id) {
        WorkflowNodeDefinition definition = workflowNodeDefinitionRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Node definition not found: " + id));

        definition.setEnabled(false);
        workflowNodeDefinitionRepository.save(definition);
        log.info("Disabled node definition: {}", id);
    }

    @Override
    public List<WorkflowNodeTypeDefinedDTO> defined() {
        List<WorkflowNodeTypeDefinedDTO> result = new ArrayList<>();

        // 遍历所有节点类型
        for (NodeTypeEnums nodeType : NodeTypeEnums.values()) {
            try {
                WorkflowNodeTypeDefinedDTO definedDTO = new WorkflowNodeTypeDefinedDTO();
                definedDTO.setNodeCode(nodeType.getCode());
                definedDTO.setNodeName(nodeType.getName());
                definedDTO.setCategory(nodeType.getCategory());
                definedDTO.setNodeType(nodeType);
                result.add(definedDTO);
            } catch (Exception e) {
                log.error("Error processing node type: " + nodeType, e);
            }
        }

        return result;
    }

}