import { Graph } from '@antv/x6';
import dagre from 'dagre';

interface NodeData {
    id: string;
    graph: {
        position?: {
            x: number;
            y: number;
        };
    };
}

interface RelativePosition {
    id: string;
    position: {
        x: number;
        y: number;
    };
}

/**
 * 检查是否所有节点都有位置信息
 * @param nodes 节点列表
 * @returns 是否所有节点都有位置信息
 */
const hasAllNodesPosition = (nodes: NodeData[]): boolean => {
    return nodes.every(node => {
        const graphData = node.graph;
        return graphData?.position?.x != null && 
               graphData?.position?.y != null;
    });
};

/**
 * 居中显示并适应画布大小
 * @param graph 图形实例
 */
const centerAndFit = (graph: Graph): void => {
    const nodes = graph.getNodes();
    if (nodes.length === 0) return;

    // 计算所有节点的边界
    let minX = Infinity;
    let minY = Infinity;
    let maxX = -Infinity;
    let maxY = -Infinity;

    nodes.forEach(node => {
        const position = node.getPosition();
        const size = node.getSize();
        minX = Math.min(minX, position.x);
        minY = Math.min(minY, position.y);
        maxX = Math.max(maxX, position.x + size.width);
        maxY = Math.max(maxY, position.y + size.height);
    });

    // 获取画布大小
    const container = graph.container;
    if (!container) return;

    const containerBBox = container.getBoundingClientRect();
    const padding = 40;

    // 计算图形的宽度和高度
    const graphWidth = maxX - minX;
    const graphHeight = maxY - minY;

    // 计算缩放比例
    const scaleX = (containerBBox.width - padding * 2) / graphWidth;
    const scaleY = (containerBBox.height - padding * 2) / graphHeight;
    const scale = Math.min(Math.min(scaleX, scaleY), 1);

    // 计算居中位置
    const tx = (containerBBox.width - graphWidth * scale) / 2 - minX * scale;
    const ty = (containerBBox.height - graphHeight * scale) / 2 - minY * scale;

    // 应用变换
    graph.scale(scale);
    graph.translate(tx, ty);
};

/**
 * 计算节点的相对位置
 * @param nodes 节点列表
 * @returns 节点的相对位置数组
 */
const calculateRelativePositions = (nodes: NodeData[]): RelativePosition[] | null => {
    if (nodes.length === 0) return null;

    // 计算所有节点的最小坐标
    let minX = Infinity;
    let minY = Infinity;
    nodes.forEach(node => {
        if (node.graph?.position) {
            minX = Math.min(minX, node.graph.position.x);
            minY = Math.min(minY, node.graph.position.y);
        }
    });

    // 计算相对位置
    const positions = nodes.map(node => {
        if (node.graph?.position) {
            return {
                id: node.id,
                position: {
                    x: node.graph.position.x - minX,
                    y: node.graph.position.y - minY
                }
            };
        }
        return null;
    }).filter((pos): pos is RelativePosition => pos !== null);

    return positions.length > 0 ? positions : null;
};

/**
 * 应用自动布局或居中显示
 * @param graph 图形实例
 * @param nodes 节点数据列表
 */
export const applyAutoLayout = (graph: Graph, nodes: NodeData[] = []): void => {
    // 如果所有节点都有位置信息，计算并应用相对位置
    if (nodes.length > 0 && hasAllNodesPosition(nodes)) {
        const relativePositions = calculateRelativePositions(nodes);
        if (relativePositions) {
            // 应用相对位置
            graph.getNodes().forEach(node => {
                const nodePosition = relativePositions.find(pos => pos.id === node.id);
                if (nodePosition) {
                    node.position(nodePosition.position.x, nodePosition.position.y);
                }
            });
            // 立即居中显示
            centerAndFit(graph);
        }
        return;
    }

    // 创建布局图
    const g = new dagre.graphlib.Graph();
    g.setGraph({
        rankdir: 'LR',
        align: 'UL',
        ranksep: 100,
        nodesep: 60,
        marginx: 40,
        marginy: 40,
    });
    g.setDefaultEdgeLabel(() => ({}));

    // 添加节点
    const graphNodes = graph.getNodes();
    graphNodes.forEach(node => {
        g.setNode(node.id, {
            width: node.getSize().width,
            height: node.getSize().height,
        });
    });

    // 添加边
    const edges = graph.getEdges();
    edges.forEach(edge => {
        g.setEdge(edge.getSourceCellId(), edge.getTargetCellId());
    });

    // 执行布局
    dagre.layout(g);

    // 应用布局结果
    graphNodes.forEach(node => {
        const nodeWithPosition = g.node(node.id);
        if (nodeWithPosition) {
            node.position(
                nodeWithPosition.x - nodeWithPosition.width / 2,
                nodeWithPosition.y - nodeWithPosition.height / 2
            );
        }
    });

    // 立即居中显示
    centerAndFit(graph);
}; 