package tech.easyflow.publicapi.dto;

import java.io.Serializable;
import java.util.List;

/**
 * Public Workflow API 对外公开的安全拓扑视图。
 *
 * @param workflowId 工作流 ID
 * @param alias 工作流别名
 * @param title 工作流标题
 * @param description 工作流描述
 * @param revision 发布内容修订号
 * @param publishedAt 发布时间，ISO-8601 格式
 * @param nodes 按稳定拓扑顺序排列的节点
 * @param edges 按发布定义顺序排列的边
 * @param topologicalOrder 节点 ID 的稳定拓扑顺序
 * @param topologyLevels 考虑循环体完成屏障后的可并行拓扑层级
 * @param hasCycle 发布图中是否存在环
 * @param unresolvedNodeIds 受环路影响而无法进入标准拓扑序的节点 ID
 */
public record PublicWorkflowTopology(
        String workflowId,
        String alias,
        String title,
        String description,
        Integer revision,
        String publishedAt,
        List<Node> nodes,
        List<Edge> edges,
        List<String> topologicalOrder,
        List<List<String>> topologyLevels,
        boolean hasCycle,
        List<String> unresolvedNodeIds) implements Serializable {

    /**
     * 创建不可变工作流拓扑。
     */
    public PublicWorkflowTopology {
        nodes = immutable(nodes);
        edges = immutable(edges);
        topologicalOrder = immutable(topologicalOrder);
        topologyLevels = topologyLevels == null
                ? List.of()
                : topologyLevels.stream()
                .map(PublicWorkflowTopology::immutable)
                .toList();
        unresolvedNodeIds = immutable(unresolvedNodeIds);
    }

    /**
     * 工作流公开节点。
     *
     * @param nodeId 节点 ID
     * @param nodeType 节点类型
     * @param nodeName 节点名称
     * @param description 节点描述
     * @param parentNodeId 父级容器节点 ID
     * @param definitionIndex 节点在发布定义中的位置
     * @param topologyIndex 节点在稳定拓扑序中的位置
     * @param topologyLevel 节点所在拓扑层级
     * @param inDegree 发布定义中的原始入度
     * @param outDegree 发布定义中的原始出度
     * @param startNode 是否开始节点
     * @param endNode 是否结束节点
     * @param predecessorNodeIds 直接前驱节点 ID
     * @param successorNodeIds 直接后继节点 ID
     * @param incomingEdgeIds 入边 ID
     * @param outgoingEdgeIds 出边 ID
     * @param inputParameters 节点输入参数元数据
     * @param outputParameters 节点输出参数元数据
     */
    public record Node(
            String nodeId,
            String nodeType,
            String nodeName,
            String description,
            String parentNodeId,
            int definitionIndex,
            int topologyIndex,
            int topologyLevel,
            int inDegree,
            int outDegree,
            boolean startNode,
            boolean endNode,
            List<String> predecessorNodeIds,
            List<String> successorNodeIds,
            List<String> incomingEdgeIds,
            List<String> outgoingEdgeIds,
            List<Parameter> inputParameters,
            List<Parameter> outputParameters) implements Serializable {

        /**
         * 创建不可变公开节点。
         */
        public Node {
            predecessorNodeIds = immutable(predecessorNodeIds);
            successorNodeIds = immutable(successorNodeIds);
            incomingEdgeIds = immutable(incomingEdgeIds);
            outgoingEdgeIds = immutable(outgoingEdgeIds);
            inputParameters = immutable(inputParameters);
            outputParameters = immutable(outputParameters);
        }
    }

    /**
     * 工作流公开边。
     *
     * @param edgeId 边 ID
     * @param edgeType 边类型
     * @param label 边展示名称
     * @param sourceNodeId 源节点 ID
     * @param targetNodeId 目标节点 ID
     * @param sourceHandle 源连接点
     * @param targetHandle 目标连接点
     * @param parentNodeId 所属父级容器节点 ID
     * @param definitionIndex 边在发布定义中的位置
     * @param dangling 是否引用了不存在的节点
     */
    public record Edge(
            String edgeId,
            String edgeType,
            String label,
            String sourceNodeId,
            String targetNodeId,
            String sourceHandle,
            String targetHandle,
            String parentNodeId,
            int definitionIndex,
            boolean dangling) implements Serializable {
    }

    /**
     * 节点输入或输出参数的安全元数据。
     *
     * @param parameterId 参数 ID
     * @param name 参数名
     * @param label 展示名称
     * @param dataType 数据类型
     * @param contentType 内容类型
     * @param required 是否必填
     * @param description 参数说明
     * @param multipartPartName 开始节点文件参数对应的 multipart Part 名
     */
    public record Parameter(
            String parameterId,
            String name,
            String label,
            String dataType,
            String contentType,
            boolean required,
            String description,
            String multipartPartName) implements Serializable {
    }

    /**
     * 将列表转换为不可变副本。
     *
     * @param source 原列表
     * @param <T> 元素类型
     * @return 不可变列表
     */
    private static <T> List<T> immutable(List<T> source) {
        return source == null ? List.of() : List.copyOf(source);
    }
}
