import React, { useCallback, useEffect, useRef, useState } from 'react';
import ReactFlow, { 
  Background,
  Controls,
  MiniMap,
  ReactFlowProvider,
  MarkerType,
  useNodesState,
  useEdgesState,
  useReactFlow
} from 'reactflow';
import dagre from 'dagre';  // 需要先安裝：npm install dagre
import 'reactflow/dist/style.css';
import axios from 'axios';

const getLayoutedElements = (nodes, edges) => {
  const dagreGraph = new dagre.graphlib.Graph();
  dagreGraph.setDefaultEdgeLabel(() => ({}));
  
  // 優化佈局配置，避免節點與連線重疊
  dagreGraph.setGraph({
    rankdir: 'TB',     // Top-to-Bottom 方向
    nodesep: 150,      // 增加節點間的水平間距
    ranksep: 200,      // 增加層級間的垂直間距
    edgesep: 80,       // 增加邊之間的間距
    marginx: 50,       // 增加圖的水平邊距
    marginy: 50,       // 增加圖的垂直邊距
    acyclicer: 'greedy', // 處理循環依賴
    ranker: 'network-simplex' // 使用更好的排序算法
  });

  // 設置節點大小 (增加節點大小，減少重疊)
  nodes.forEach((node) => {
    dagreGraph.setNode(node.id, { width: 200, height: 60 });
  });

  // 添加邊
  edges.forEach((edge) => {
    dagreGraph.setEdge(edge.source, edge.target);
  });

  // 計算布局
  dagre.layout(dagreGraph);

  // 獲取計算後的位置
  const layoutedNodes = nodes.map(node => {
    const nodeWithPosition = dagreGraph.node(node.id);
    // 根據節點大小調整中心點
    const nodeWidth = 200;
    const nodeHeight = 60;
    return {
      ...node,
      position: {
        x: Number.isFinite(nodeWithPosition.x) ? nodeWithPosition.x - nodeWidth / 2 : 0,
        y: Number.isFinite(nodeWithPosition.y) ? nodeWithPosition.y - nodeHeight / 2 : 0
      },
    };
  });

  return layoutedNodes;
};

// 定義邊的類型樣式和中文標籤
const edgeTypes = {
  'basic': {
    label: '基礎概念',
    color: '#2196f3'  // 藍色
  },
  'advanced': {
    label: '進階概念',
    color: '#f44336'  // 紅色
  },
  'related': {
    label: '相關概念',
    color: '#4caf50'  // 綠色
  },
  'contains': {
    label: '包含',
    color: '#9c27b0'  // 紫色
  },
  'example': {
    label: '案例',
    color: '#ff9800'  // 橙色
  },
  'reference': {
    label: '參考',
    color: '#795548'  // 棕色
  }
};

// 添加一個全局變量來保存圖譜數據
const graphDataCache = {
  current: null
};

// 支援的 layout 類型
const LAYOUT_OPTIONS = [
  { value: 'TB', label: '上到下（預設）' },
  { value: 'LR', label: '左到右' },
  { value: 'mindmap', label: '心智圖式' },
  { value: 'waterfall', label: '瀑布式' }
];

// 在 KnowledgeGraph 外部新增
function AutoFitView({ layoutType, flowNodes }) {
  const { fitView } = useReactFlow();
  useEffect(() => {
    if (flowNodes && flowNodes.length > 0) {
      setTimeout(() => {
        fitView({ padding: 0.2, includeHiddenNodes: true });
      }, 0);
    }
  }, [layoutType, flowNodes, fitView]);
  return null;
}

function KnowledgeGraph({ nodes, edges, onNodeClick, selectedNodeId, graphId }) {
  const containerRef = useRef(null);
  const [flowNodes, setFlowNodes] = useNodesState([]);
  const [flowEdges, setFlowEdges] = useEdgesState([]);
  const [localNodes, setLocalNodes] = useState(nodes);
  const [localEdges, setLocalEdges] = useState(edges);
  const [isLoading, setIsLoading] = useState(false);
  const [layoutType, setLayoutType] = useState('TB'); // 新增 layout 狀態

  // 當 props 中的 nodes 和 edges 變化時，更新本地狀態
  useEffect(() => {
    if (nodes && nodes.length > 0) {
      setLocalNodes(nodes);
      // 同時更新緩存
      if (graphId) {
        graphDataCache[graphId] = { nodes, edges };
      }
    }
    if (edges && edges.length > 0) {
      setLocalEdges(edges);
    }
  }, [nodes, edges, graphId]);
  
  // 如果 props 中的數據為空但有緩存，則使用緩存
  useEffect(() => {
    if ((!nodes || nodes.length === 0) && graphId && graphDataCache[graphId]) {
      console.log(`使用緩存的圖譜數據: ${graphId}`);
      setLocalNodes(graphDataCache[graphId].nodes);
      setLocalEdges(graphDataCache[graphId].edges);
    }
  }, [nodes, edges, graphId]);
  
  // 如果本地狀態為空且有 graphId，則嘗試從服務器加載
  useEffect(() => {
    if ((!localNodes || localNodes.length === 0) && graphId && !isLoading) {
      setIsLoading(true);
      console.log(`嘗試從服務器加載圖譜: ${graphId}`);
      
      axios.get(`/api/graph/${graphId}`)
        .then(response => {
          const graphData = response.data.graph;
          setLocalNodes(graphData.nodes);
          setLocalEdges(graphData.edges);
          // 更新緩存
          graphDataCache[graphId] = { 
            nodes: graphData.nodes, 
            edges: graphData.edges 
          };
          console.log(`成功從服務器加載圖譜: ${graphId}`);
        })
        .catch(error => {
          console.error(`加載圖譜失敗: ${graphId}`, error);
        })
        .finally(() => {
          setIsLoading(false);
        });
    }
  }, [localNodes, graphId, isLoading]);

  // 取得不同 layout 的節點位置
  const getLayoutedNodes = useCallback((nodes, edges, layoutType) => {
    if (layoutType === 'mindmap') {
      // 簡單心智圖：root 在左，其他節點橫向展開
      const root = nodes[0];
      return nodes.map((node, i) => ({
        ...node,
        position: {
          x: i * 250,
          y: (i % 2 === 0 ? 1 : -1) * (80 + 80 * Math.floor(i / 2))
        }
      }));
    }
    if (layoutType === 'waterfall') {
      // 簡單瀑布式：每層一行，橫向排列
      return nodes.map((node, i) => ({
        ...node,
        position: {
          x: (i % 4) * 220,
          y: Math.floor(i / 4) * 120
        }
      }));
    }
    // 其餘用 dagre
    return getLayoutedElements(
      nodes,
      edges,
      layoutType
    );
  }, []);

  // 修改 getLayoutedElements 支援 rankdir
  const getLayoutedElements = (nodes, edges, rankdir = 'TB') => {
    const dagreGraph = new dagre.graphlib.Graph();
    dagreGraph.setDefaultEdgeLabel(() => ({}));
    dagreGraph.setGraph({
      rankdir,
      nodesep: 150,
      ranksep: 200,
      edgesep: 80,
      marginx: 50,
      marginy: 50,
      acyclicer: 'greedy',
      ranker: 'network-simplex'
    });
    nodes.forEach((node) => {
      dagreGraph.setNode(node.id, { width: 200, height: 60 });
    });
    edges.forEach((edge) => {
      dagreGraph.setEdge(edge.source, edge.target);
    });
    dagre.layout(dagreGraph);
    const layoutedNodes = nodes.map(node => {
      const nodeWithPosition = dagreGraph.node(node.id);
      const nodeWidth = 200;
      const nodeHeight = 60;
      return {
        ...node,
        position: {
          x: Number.isFinite(nodeWithPosition.x) ? nodeWithPosition.x - nodeWidth / 2 : 0,
          y: Number.isFinite(nodeWithPosition.y) ? nodeWithPosition.y - nodeHeight / 2 : 0
        },
      };
    });
    return layoutedNodes;
  };

  // 使用 useEffect 來更新 ReactFlow 的節點和邊
  useEffect(() => {
    if (!localNodes || localNodes.length === 0) return;
    try {
      const validNodes = Array.isArray(localNodes) ? localNodes : Object.values(localNodes);
      const layoutedNodes = getLayoutedNodes(
        validNodes.map(node => ({
          id: node.id,
          data: { label: node.title },
          position: { x: 0, y: 0 },
          style: {
            background: selectedNodeId === node.id ? '#ff0072' : '#fff',
            border: '1px solid #777',
            padding: 10,
            width: 180,
            height: 50,
            borderRadius: 8,
            fontSize: '14px',
            textAlign: 'center'
          }
        })),
        localEdges || [],
        layoutType
      );

      const styledEdges = (localEdges || []).map(edge => ({
        ...edge,
        id: `${edge.source}-${edge.target}`,
        type: 'smoothstep',
        animated: true,
        style: {
          stroke: edgeTypes[edge.type]?.color || '#888',
          strokeWidth: 2
        },
        markerEnd: {
          type: MarkerType.ArrowClosed,
          width: 20,
          height: 20,
          color: edgeTypes[edge.type]?.color || '#888',
        },
        label: edgeTypes[edge.type]?.label || edge.type,
        labelStyle: { 
          fill: '#888', 
          fontSize: 12,
          fontWeight: 500,
          background: '#ffffff',
          padding: '4px 8px',
        },
        labelBgStyle: { 
          fill: '#ffffff',
          fillOpacity: 0.8,
          rx: 4,
          stroke: '#eee',
          strokeWidth: 1,
        },
        pathOptions: {
          offset: 30,
          borderRadius: 20
        }
      }));

      setFlowNodes(layoutedNodes);
      setFlowEdges(styledEdges);
    } catch (error) {
      console.error('處理圖譜數據時出錯:', error);
    }
  }, [localNodes, localEdges, selectedNodeId, setFlowNodes, setFlowEdges, layoutType, getLayoutedNodes]);

  // 使用 useCallback 來記憶化事件處理函數
  const handleNodeClick = useCallback((_, node) => {
    if (onNodeClick) {
      onNodeClick(node.id);
    }
  }, [onNodeClick]);

  // 如果正在加載，顯示加載指示器
  if (isLoading) {
    return (
      <div style={{ 
        width: '100%', 
        height: '100%', 
        display: 'flex', 
        justifyContent: 'center', 
        alignItems: 'center',
        backgroundColor: '#f5f5f5'
      }}>
        <div>加載圖譜中...</div>
      </div>
    );
  }

  // 如果沒有節點數據，顯示錯誤信息
  if (!flowNodes || flowNodes.length === 0) {
    return (
      <div style={{ 
        width: '100%', 
        height: '100%', 
        display: 'flex', 
        justifyContent: 'center', 
        alignItems: 'center',
        flexDirection: 'column',
        backgroundColor: '#f5f5f5'
      }}>
        <div style={{ marginBottom: '16px' }}>無法顯示圖譜</div>
        {graphId && (
          <button 
            onClick={() => {
              setIsLoading(true);
              axios.get(`/api/graph/${graphId}`)
                .then(response => {
                  const graphData = response.data.graph;
                  setLocalNodes(graphData.nodes);
                  setLocalEdges(graphData.edges);
                  graphDataCache[graphId] = { 
                    nodes: graphData.nodes, 
                    edges: graphData.edges 
                  };
                })
                .catch(error => {
                  console.error(`重新加載圖譜失敗: ${graphId}`, error);
                })
                .finally(() => {
                  setIsLoading(false);
                });
            }}
            style={{
              padding: '8px 16px',
              backgroundColor: '#2196f3',
              color: 'white',
              border: 'none',
              borderRadius: '4px',
              cursor: 'pointer'
            }}
          >
            重新加載圖譜
          </button>
        )}
      </div>
    );
  }

  return (
    <div ref={containerRef} style={{ width: '100%', height: '100%', position: 'relative' }}>
      {/* 只保留 layout 選擇器 */}
      <div style={{
        position: 'absolute',
        top: 12,
        right: 12,
        zIndex: 10,
        background: '#fff',
        borderRadius: 6,
        boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
        padding: '4px 12px'
      }}>
        <select
          value={layoutType}
          onChange={e => setLayoutType(e.target.value)}
          style={{ fontSize: 14, padding: '2px 8px' }}
        >
          {LAYOUT_OPTIONS.map(opt => (
            <option key={opt.value} value={opt.value}>{opt.label}</option>
          ))}
        </select>
      </div>
      <ReactFlowProvider>
        <div style={{ width: '100%', height: '100%' }}>
          <ReactFlow
            nodes={flowNodes}
            edges={flowEdges}
            onNodeClick={handleNodeClick}
            fitView
            fitViewOptions={{ 
              padding: 0.2,
              includeHiddenNodes: true
            }}
            minZoom={0.1}
            maxZoom={2}
            defaultViewport={{ 
              x: 0,
              y: 0,
              zoom: 1
            }}
            nodesDraggable={false}
            nodesConnectable={false}
            elementsSelectable={true}
          >
            <Background 
              color="#aaa"
              gap={16}
              size={1}
              variant="dots"
            />
            <Controls />
            <MiniMap 
              nodeStrokeColor={(n) => n.id === selectedNodeId ? '#ff0072' : '#000'}
              nodeColor={(n) => n.id === selectedNodeId ? '#ff0072' : '#fff'}
              maskColor="rgba(0, 0, 0, 0.1)"
              style={{ height: 120, width: 160 }}
            />
            {/* 這裡插入自動置中元件 */}
            <AutoFitView layoutType={layoutType} flowNodes={flowNodes} />
          </ReactFlow>
        </div>
      </ReactFlowProvider>
    </div>
  );
}

// 使用 React.memo 並提供比較函數
export default React.memo(KnowledgeGraph, (prevProps, nextProps) => {
  // 只有當這些 props 都相同時才跳過重新渲染
  return (
    prevProps.selectedNodeId === nextProps.selectedNodeId &&
    prevProps.graphId === nextProps.graphId &&
    // 如果 nodes 和 edges 為空但 graphId 相同，也視為相同
    ((prevProps.nodes === nextProps.nodes && prevProps.edges === nextProps.edges) ||
     (!prevProps.nodes && !nextProps.nodes && !prevProps.edges && !nextProps.edges && prevProps.graphId === nextProps.graphId))
  );
}); 