import dagre from 'dagre';

interface MermaidNode {
  id: string;
  label: string;
  shape: 'rect' | 'diamond' | 'ellipse' | 'circle' | 'cylinder';
}

interface MermaidEdge {
  source: string;
  target: string;
  label: string;
}

// 在节点解析中添加样式处理
const shapeMapping: Record<string, string> = {
  '[': '矩形节点',
  '(': '圆边节点',
  '([': '体育场形状节点',
  '[[': '子程序',
  '[(': '圆柱形状',
  '((': '圆形节点',
  '>': '右箭头形状',
  '{': '菱形节点',
  '{{': '六边形节点',
  '[/': '平行四边形',
  '(((': '双圆圈'
};

// 增强的正则表达式，支持更多节点类型
const NODE_REGEX = /^(\w+)(?:\[(.*?)\]|\{(.*?)\}|\((.*?)\)|\((\((.*?)\))\)|\[\[(.*?)\]\])(?!\S)/;
const EDGE_REGEX = /^(\w+(?:\[.*?\]|\{.*?\}|\(.*?\)|\(\(.*?\)\)|\[\[.*?\]\])?)\s*(-->|->)\s*(\w+(?:\[.*?\]|\{.*?\}|\(.*?\)|\(\(.*?\)\)|\[\[.*?\]\])?)(?:\s*\|(.*?)\|)?/;

function parseNode(str: string): MermaidNode | null {
  const match = str.match(NODE_REGEX);
  if (!match) return null;

  const [, id, rect, diamond, ellipse, , circle, cylinder] = match;
  
  return {
    id,
    label: rect || diamond || ellipse || circle || cylinder || id,
    shape: rect ? 'rect' 
         : diamond ? 'diamond' 
         : ellipse ? 'ellipse' 
         : circle ? 'circle' 
         : cylinder ? 'cylinder' 
         : 'rect'
  };
}

function parseMermaid(code: string): { nodes: MermaidNode[]; edges: MermaidEdge[] } {
  const nodes: MermaidNode[] = [];
  const edges: MermaidEdge[] = [];
  const nodeCache = new Set<string>();

  const ensureNode = (nodeStr: string) => {
    const node = parseNode(nodeStr) || { id: nodeStr, label: nodeStr, shape: 'rect' };
    if (!nodeCache.has(node.id)) {
      nodes.push(node);
      nodeCache.add(node.id);
    }
    return node.id;
  };

  code.split('\n').forEach(line => {
    line = line.trim();
    if (!line || line.startsWith('%%')) return;

    // 解析独立节点定义
    const node = parseNode(line);
    if (node) {
      if (!nodeCache.has(node.id)) {
        nodes.push(node);
        nodeCache.add(node.id);
      }
      return;
    }

    // 解析边定义
    const edgeMatch = line.match(EDGE_REGEX);
    if (edgeMatch) {
      const [, sourceStr, , targetStr, label] = edgeMatch;
      const source = ensureNode(sourceStr);
      const target = ensureNode(targetStr);
      edges.push({ source, target, label: label || '' });
    }
  });

  console.log('nodes', nodes, edges);
  return { nodes, edges };
}

function convertToX6Format(nodes: MermaidNode[], edges: MermaidEdge[]): any[] {
  const graph = new dagre.graphlib.Graph();
  graph.setGraph({ rankdir: 'TB', nodesep: 50, ranksep: 70 });
  graph.setDefaultEdgeLabel(() => ({}));

  // Add nodes to dagre graph
  nodes.forEach(node => {
    graph.setNode(node.id, {
      label: node.label,
      width: node.shape === 'diamond' ? 80 : 100,
      height: node.shape === 'diamond' ? 80 : 40,
      shape: node.shape
    });
  });

  // Add edges to dagre graph
  edges.forEach(edge => {
    graph.setEdge(edge.source, edge.target, { label: edge.label });
  });

  dagre.layout(graph);

  // Convert to X6 format
  const x6Nodes = graph.nodes().map((id: string) => {
    const dagreNode = graph.node(id);
    return {
      id,
      shape: dagreNode.shape,
      position: { x: dagreNode.x - dagreNode.width / 2, y: dagreNode.y - dagreNode.height / 2 },
      size: { width: dagreNode.width, height: dagreNode.height },
      attrs: { 
        label: { 
          text: dagreNode.label,
          fontSize: 14,
          fill: '#333'
        }
      }
    };
  });

  const x6Edges = graph.edges().map((edge: any, index: number) => {
    const dagreEdge = graph.edge(edge);
    return {
      id: `edge-${index}`,
      shape: 'edge',
      source: { cell: edge.v },
      target: { cell: edge.w },
      attrs: {
        line: {
          stroke: '#808080',
          strokeWidth: 2,
          targetMarker: 'classic'
        },
        label: {
          text: dagreEdge.label,
          fontSize: 12,
          fill: '#666'
        }
      }
    };
  });

  return [...x6Nodes, ...x6Edges];
}

export function mermaidToX6Json(mermaidCode: string): { isFlowchart: boolean, raw?: string, cells?: any[] } {
  if (!isMermaidFlowchart(mermaidCode)) {
    return { isFlowchart: false, raw: mermaidCode };
  }
  const { nodes, edges } = parseMermaid(mermaidCode);
  return {
    isFlowchart: true,
    cells: convertToX6Format(nodes, edges)
  }
}