import { useState, useRef, useEffect, useCallback } from "react";
import { Search, Network, ZoomIn, ZoomOut, Maximize2, Plus, Download, Trash2, Edit, Eye } from "lucide-react";
import { motion } from "motion/react";
import { toast } from "sonner";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../../components/ui/dialog";
import * as d3 from "d3";

interface GraphNode extends d3.SimulationNodeDatum {
  id: number;
  label: string;
  type: string;
  description: string;
  connections: number;
}

interface GraphEdge extends d3.SimulationLinkDatum<GraphNode> {
  source: number | GraphNode;
  target: number | GraphNode;
  label: string;
}

const steelNodeTypeConfig = {
  fault: { label: "故障", color: "#ef4444", gradient: "from-red-500 to-orange-500" },
  symptom: { label: "症状", color: "#f59e0b", gradient: "from-yellow-500 to-amber-500" },
  cause: { label: "原因", color: "#3b82f6", gradient: "from-blue-500 to-cyan-500" },
  solution: { label: "解决方案", color: "#10b981", gradient: "from-green-500 to-emerald-500" },
  prevention: { label: "预防措施", color: "#a855f7", gradient: "from-purple-500 to-pink-500" },
};

const aluminaNodeTypeConfig = {
  equipment: { label: "设备", color: "#0ea5e9", gradient: "from-sky-500 to-blue-500" },
  material: { label: "原料", color: "#22c55e", gradient: "from-green-500 to-emerald-500" },
  parameter: { label: "工艺参数", color: "#f59e0b", gradient: "from-amber-500 to-orange-500" },
  quality: { label: "质量指标", color: "#a855f7", gradient: "from-purple-500 to-pink-500" },
  process: { label: "工序", color: "#ec4899", gradient: "from-pink-500 to-rose-500" },
};

const initialNodes: GraphNode[] = [
  { id: 1, label: "给煤机故障", type: "fault", description: "给煤机无法正常启动或运行中断", connections: 4 },
  { id: 2, label: "跳闸", type: "symptom", description: "设备意外停机保护动作", connections: 3 },
  { id: 3, label: "皮带松紧不当", type: "cause", description: "输送带张力异常导致打滑", connections: 2 },
  { id: 4, label: "检查皮带", type: "solution", description: "调整皮带张紧装置", connections: 1 },
  { id: 5, label: "定期维护", type: "prevention", description: "建立周期性检修计划", connections: 1 },
  { id: 6, label: "电机过热", type: "fault", description: "电机温度超过额定值", connections: 3 },
  { id: 7, label: "停机", type: "symptom", description: "系统停止运行", connections: 2 },
  { id: 8, label: "散热不良", type: "cause", description: "冷却系统效率下降", connections: 2 },
  { id: 9, label: "清理风扇", type: "solution", description: "清除散热器灰尘杂物", connections: 1 },
  { id: 10, label: "冷却水不足", type: "cause", description: "冷却液位过低或循环不畅", connections: 2 },
  { id: 11, label: "补充冷却液", type: "solution", description: "添加或更换冷却液", connections: 1 },
  { id: 12, label: "磨损严重", type: "fault", description: "部件磨损导致性能下降", connections: 2 },
];

const initialEdges: GraphEdge[] = [
  { source: 1, target: 2, label: "表现" },
  { source: 1, target: 3, label: "由于" },
  { source: 2, target: 4, label: "对策" },
  { source: 3, target: 5, label: "预防" },
  { source: 6, target: 7, label: "表现" },
  { source: 6, target: 8, label: "由于" },
  { source: 8, target: 9, label: "对策" },
  { source: 6, target: 10, label: "由于" },
  { source: 10, target: 11, label: "对策" },
  { source: 12, target: 7, label: "导致" },
];

const aluminaNodes: GraphNode[] = [
  { id: 1, label: "溶出釜", type: "equipment", description: "高压溶出铝土矿的核心设备", connections: 5 },
  { id: 2, label: "铝土矿", type: "material", description: "主要原料铝硅比A/S=8.5", connections: 4 },
  { id: 3, label: "配碱量", type: "parameter", description: "碱液与矿石比例210kg/t", connections: 3 },
  { id: 4, label: "溶出率", type: "quality", description: "目标溶出率≥95%", connections: 4 },
  { id: 5, label: "溶出工序", type: "process", description: "高压碱液溶出铝土矿", connections: 3 },
  { id: 6, label: "沉降槽", type: "equipment", description: "分离赤泥和铝酸钠溶液", connections: 4 },
  { id: 7, label: "种子分解", type: "process", description: "添加晶种分解氢氧化铝", connections: 3 },
  { id: 8, label: "蒸发器", type: "equipment", description: "浓缩母液的设备", connections: 3 },
  { id: 9, label: "煅烧炉", type: "equipment", description: "焙烧氢氧化铝成氧化铝", connections: 4 },
  { id: 10, label: "电解槽", type: "equipment", description: "电解生产金属铝的核心设备", connections: 5 },
  { id: 11, label: "槽电压", type: "parameter", description: "正常范围3.8-4.2V", connections: 4 },
  { id: 12, label: "分子比", type: "parameter", description: "电解质分子比2.2-2.4", connections: 3 },
];

const aluminaEdges: GraphEdge[] = [
  { source: 1, target: 5, label: "属于" },
  { source: 2, target: 1, label: "输入" },
  { source: 3, target: 1, label: "作用于" },
  { source: 1, target: 4, label: "产出" },
  { source: 4, target: 6, label: "输送至" },
  { source: 6, target: 7, label: "进入" },
  { source: 7, target: 8, label: "产出" },
  { source: 8, target: 9, label: "输送至" },
  { source: 9, target: 10, label: "原料" },
  { source: 10, target: 11, label: "监测" },
  { source: 10, target: 12, label: "影响" },
];

const statsDataSteel = [
  { label: "实体总数", value: "1,067" },
  { label: "关系总数", value: "1,249" },
  { label: "故障类型", value: "45种" },
  { label: "图谱类型", value: "钢铁" },
];

const statsDataAlumina = [
  { label: "实体总数", value: "2,458" },
  { label: "关系总数", value: "3,102" },
  { label: "工序覆盖", value: "6大工序" },
  { label: "图谱类型", value: "铝冶炼" },
];

const queryHistoryData = [
  { query: "给煤机皮带跑偏", result: "已找到5个相关节点", timestamp: "10:30" },
  { query: "过热器故障", result: "已找到3个相关节点", timestamp: "10:25" },
  { query: "磨煤机跳闸", result: "已找到4个相关节点", timestamp: "10:20" },
];

export function KnowledgeGraph() {
  const [searchQuery, setSearchQuery] = useState("");
  const [selectedNode, setSelectedNode] = useState<GraphNode | null>(null);
  const [showNodeDialog, setShowNodeDialog] = useState(false);
  const [searchHistory, setSearchHistory] = useState(queryHistoryData);
  const [isSearching, setIsSearching] = useState(false);
  const [hoveredNode, setHoveredNode] = useState<number | null>(null);
  const [highlightedNodes, setHighlightedNodes] = useState<Set<number>>(new Set());
  const [typeFilter, setTypeFilter] = useState<Set<string>>(new Set(Object.keys(steelNodeTypeConfig)));
  const [simulation, setSimulation] = useState<d3.Simulation<any, any> | null>(null);
  const [industry, setIndustry] = useState<"steel" | "alumina">("steel");
  
  const svgRef = useRef<SVGSVGElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);

  const currentStatsData = industry === "steel" ? statsDataSteel : statsDataAlumina;
  const currentNodes = industry === "steel" ? initialNodes : aluminaNodes;
  const currentEdges = industry === "steel" ? initialEdges : aluminaEdges;
  const currentNodeTypeConfig = industry === "steel" ? steelNodeTypeConfig : aluminaNodeTypeConfig;

  const initGraph = useCallback(() => {
    if (!svgRef.current || !containerRef.current) return;

    const svg = d3.select(svgRef.current);
    svg.selectAll("*").remove();

    const width = containerRef.current.clientWidth;
    const height = containerRef.current.clientHeight;

    svg.attr("width", width).attr("height", height);

    const g = svg.append("g");

    const zoom = d3.zoom<SVGSVGElement, unknown>()
      .scaleExtent([0.3, 3])
      .on("zoom", (event) => {
        g.attr("transform", event.transform);
      });

    svg.call(zoom);

    const defs = svg.append("defs");
    const configToUse = industry === "steel" ? steelNodeTypeConfig : aluminaNodeTypeConfig;
    
    Object.entries(configToUse).forEach(([type, config]) => {
      const gradient = defs.append("radialGradient")
        .attr("id", `gradient-${type}`)
        .attr("cx", "30%")
        .attr("cy", "30%");
      
      gradient.append("stop")
        .attr("offset", "0%")
        .attr("stop-color", config.color)
        .attr("stop-opacity", 0.8);
      
      gradient.append("stop")
        .attr("offset", "100%")
        .attr("stop-color", config.color)
        .attr("stop-opacity", 0.4);
    });

    const nodesToUse = industry === "steel" ? initialNodes : aluminaNodes;
    const edgesToUse = industry === "steel" ? initialEdges : aluminaEdges;
    const filteredNodes = nodesToUse.filter(n => typeFilter.has(n.type));
    const filteredNodeIds = new Set(filteredNodes.map(n => n.id));
    const filteredEdges = edgesToUse.filter(e => {
      const sourceId = typeof e.source === 'number' ? e.source : (e.source as GraphNode).id;
      const targetId = typeof e.target === 'number' ? e.target : (e.target as GraphNode).id;
      return filteredNodeIds.has(sourceId) && filteredNodeIds.has(targetId);
    });

    const nodes = filteredNodes.map(n => ({ ...n }));
    const links = filteredEdges.map(e => ({ ...e }));

    const newSimulation = d3.forceSimulation(nodes)
      .force("link", d3.forceLink(links).id((d: any) => d.id).distance(150))
      .force("charge", d3.forceManyBody().strength(-400))
      .force("center", d3.forceCenter(width / 2, height / 2))
      .force("collision", d3.forceCollide().radius(60));

    setSimulation(newSimulation);

    const link = g.append("g")
      .attr("class", "links")
      .selectAll("line")
      .data(links)
      .enter()
      .append("g")
      .attr("class", "link-group");

    const linkLine = link.append("line")
      .attr("stroke", "#475569")
      .attr("stroke-width", 2)
      .attr("stroke-opacity", 0.6);

    const linkLabel = link.append("text")
      .attr("fill", "#94a3b8")
      .attr("font-size", 10)
      .attr("text-anchor", "middle")
      .attr("dy", -5)
      .text((d: any) => d.label);

    const nodeGroup = g.append("g")
      .attr("class", "nodes")
      .selectAll("g")
      .data(nodes)
      .enter()
      .append("g")
      .attr("class", "node-group")
      .style("cursor", "pointer")
      .call(d3.drag<any, any>()
        .on("start", (event, d: any) => {
          if (!event.active) newSimulation.alphaTarget(0.3).restart();
          d.fx = d.x;
          d.fy = d.y;
        })
        .on("drag", (event, d: any) => {
          d.fx = event.x;
          d.fy = event.y;
        })
        .on("end", (event, d: any) => {
          if (!event.active) newSimulation.alphaTarget(0);
          d.fx = null;
          d.fy = null;
        })
      );

    nodeGroup.append("circle")
      .attr("r", 40)
      .attr("fill", (d: any) => `url(#gradient-${d.type})`)
      .attr("stroke", (d: any) => configToUse[d.type as keyof typeof configToUse]?.color || "#fff")
      .attr("stroke-width", 3)
      .attr("stroke-opacity", 0.8);

    nodeGroup.append("text")
      .attr("text-anchor", "middle")
      .attr("dy", "0.35em")
      .attr("fill", "#fff")
      .attr("font-size", 11)
      .attr("font-weight", "bold")
      .text((d: any) => d.label.length > 8 ? d.label.slice(0, 8) + "..." : d.label);

    nodeGroup.on("mouseover", function(event, d: any) {
      d3.select(this).select("circle")
        .transition()
        .duration(200)
        .attr("r", 50)
        .attr("stroke-width", 4);
      
      setHoveredNode(d.id);
      
      const connectedIds = new Set<number>();
      connectedIds.add(d.id);
      links.forEach((l: any) => {
        if (l.source.id === d.id) connectedIds.add(l.target.id);
        if (l.target.id === d.id) connectedIds.add(l.source.id);
      });
      setHighlightedNodes(connectedIds);
    });

    nodeGroup.on("mouseout", function() {
      d3.select(this).select("circle")
        .transition()
        .duration(200)
        .attr("r", 40)
        .attr("stroke-width", 3);
      
      setHoveredNode(null);
      setHighlightedNodes(new Set());
    });

    nodeGroup.on("click", function(event, d: any) {
      event.stopPropagation();
      setSelectedNode(d);
      setShowNodeDialog(true);
      toast.success(`已选择节点: ${d.label}`, { duration: 2000 });
    });

    nodeGroup.on("dblclick", function(event, d: any) {
      event.stopPropagation();
      const connectedIds = new Set<number>();
      connectedIds.add(d.id);
      links.forEach((l: any) => {
        if (l.source.id === d.id) connectedIds.add(l.target.id);
        if (l.target.id === d.id) connectedIds.add(l.source.id);
      });
      
      nodes.forEach(n => {
        const nodeG = g.selectAll(".node-group").filter((nd: any) => nd.id === n.id);
        if (connectedIds.has(n.id)) {
          nodeG.select("circle")
            .transition()
            .duration(300)
            .attr("stroke-width", 4)
            .attr("stroke", configToUse[n.type as keyof typeof configToUse]?.color || "#fff");
        } else {
          nodeG.select("circle")
            .transition()
            .duration(300)
            .attr("stroke-width", 1)
            .attr("stroke", "#475569")
            .attr("opacity", 0.3);
        }
      });

      toast.info(`已展开 ${d.label} 的关联节点`, { duration: 1500 });
    });

    svg.on("click", () => {
      setSelectedNode(null);
      setShowNodeDialog(false);
      nodeGroup.select("circle")
        .transition()
        .duration(300)
        .attr("stroke-width", 3)
        .attr("stroke", (d: any) => configToUse[d.type as keyof typeof configToUse]?.color || "#fff")
        .attr("opacity", 1);
    });

    newSimulation.on("tick", () => {
      linkLine
        .attr("x1", (d: any) => d.source.x)
        .attr("y1", (d: any) => d.source.y)
        .attr("x2", (d: any) => d.target.x)
        .attr("y2", (d: any) => d.target.y);

      linkLabel
        .attr("x", (d: any) => (d.source.x + d.target.x) / 2)
        .attr("y", (d: any) => (d.source.y + d.target.y) / 2);

      nodeGroup.attr("transform", (d: any) => `translate(${d.x},${d.y})`);
    });

    svg.call(zoom.transform, d3.zoomIdentity.translate(0, 0).scale(1));

  }, [typeFilter, industry]);

  useEffect(() => {
    initGraph();
  }, [industry, initGraph]);

  useEffect(() => {
    if (!simulation) return;
    return () => {
      simulation.stop();
    };
  }, [simulation]);

  useEffect(() => {
    const handleResize = () => {
      if (containerRef.current && svgRef.current) {
        const svg = d3.select(svgRef.current);
        svg.attr("width", containerRef.current.clientWidth)
           .attr("height", containerRef.current.clientHeight);
      }
    };

    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  const handleSearch = () => {
    if (searchQuery.trim()) {
      setIsSearching(true);
      
      toast.promise(
        new Promise((resolve) => setTimeout(resolve, 1200)),
        {
          loading: "正在搜索知识图谱...",
          success: () => {
            const newEntry = {
              query: searchQuery,
              result: `已找到 ${Math.floor(Math.random() * 5) + 3} 个相关节点`,
              timestamp: new Date().toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" }),
            };
            setSearchHistory((prev) => [newEntry, ...prev.slice(0, 4)]);
            
            const foundNode = initialNodes.find(
              (n) => n.label.includes(searchQuery) || n.description.includes(searchQuery)
            );
            
            if (foundNode) {
              setSelectedNode(foundNode);
              setShowNodeDialog(true);
            }
            
            setSearchQuery("");
            setIsSearching(false);
            return `找到相关节点`;
          },
          error: "搜索失败",
        }
      );
    }
  };

  const handleExport = () => {
    toast.promise(
      new Promise((resolve) => setTimeout(resolve, 1500)),
      {
        loading: "正在导出图谱数据...",
        success: "导出成功！文件已保存",
        error: "导出失败",
      }
    );
  };

  const handleNewTask = () => {
    toast.info("新建抽取任务窗口即将打开", { duration: 2000 });
  };

  const handleViewResults = () => {
    toast.info("查看抽取结果", { duration: 2000 });
  };

  const handleKnowledgeFusion = () => {
    toast.promise(
      new Promise((resolve) => setTimeout(resolve, 2000)),
      {
        loading: "正在执行知识融合...",
        success: "知识融合完成！新增实体 12 个",
        error: "融合失败",
      }
    );
  };

  const handleQualityEval = () => {
    toast.promise(
      new Promise((resolve) => setTimeout(resolve, 1800)),
      {
        loading: "正在正在进行质量评估...",
        success: "评估完成！质量得分: 92/100",
        error: "评估失败",
      }
    );
  };

  const handleTypeFilterToggle = (type: string) => {
    setTypeFilter((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(type)) {
        if (newSet.size > 1) {
          newSet.delete(type);
        }
      } else {
        newSet.add(type);
      }
      return newSet;
    });
    toast.info("图谱筛选已更新", { duration: 1000 });
  };

  const getConnectedNodes = (nodeId: number) => {
    const connected: number[] = [];
    initialEdges.forEach((e) => {
      const sourceId = typeof e.source === 'number' ? e.source : (e.source as GraphNode).id;
      const targetId = typeof e.target === 'number' ? e.target : (e.target as GraphNode).id;
      if (sourceId === nodeId) connected.push(targetId);
      if (targetId === nodeId) connected.push(sourceId);
    });
    return connected;
  };

  return (
    <div className="h-full p-6 space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold text-white mb-1">工业知识图谱</h1>
          <div className="flex items-center gap-3 mt-2">
            <button
              onClick={() => {
                setIndustry("steel");
                setTypeFilter(new Set(Object.keys(steelNodeTypeConfig)));
              }}
              className={`px-3 py-1 rounded-lg text-sm font-medium transition-all ${
                industry === "steel"
                  ? "bg-orange-500/20 text-orange-400 border border-orange-500/50"
                  : "bg-slate-800/50 text-slate-400 border border-slate-700/50 hover:bg-slate-800"
              }`}
            >
              钢铁行业
            </button>
            <button
              onClick={() => {
                setIndustry("alumina");
                setTypeFilter(new Set(Object.keys(aluminaNodeTypeConfig)));
              }}
              className={`px-3 py-1 rounded-lg text-sm font-medium transition-all ${
                industry === "alumina"
                  ? "bg-cyan-500/20 text-cyan-400 border border-cyan-500/50"
                  : "bg-slate-800/50 text-slate-400 border border-slate-700/50 hover:bg-slate-800"
              }`}
            >
              铝冶炼行业
            </button>
          </div>
        </div>
        <div className="flex items-center gap-2">
          <motion.button
            whileHover={{ scale: 1.05 }}
            whileTap={{ scale: 0.95 }}
            onClick={handleExport}
            className="px-3 py-1.5 rounded-lg bg-slate-800/50 hover:bg-slate-800 text-sm text-slate-300 flex items-center gap-2 transition-colors"
          >
            <Download className="w-4 h-4" />
            导出
          </motion.button>
          <span className="text-sm text-slate-400">D3.js 力导向图引擎</span>
        </div>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-4 gap-6 h-[calc(100%-6rem)]">
        <div className="space-y-6 overflow-y-auto">
          <motion.div
            initial={{ opacity: 0, x: -20 }}
            animate={{ opacity: 1, x: 0 }}
            className="rounded-xl bg-slate-900/50 border border-slate-800/50 backdrop-blur-sm p-6"
          >
            <h3 className="font-semibold text-white mb-4">图谱统计概览</h3>
            <div className="space-y-3">
              {currentStatsData.map((stat) => (
                <div key={stat.label} className="flex justify-between items-center">
                  <span className="text-sm text-slate-400">{stat.label}</span>
                  <span className="text-lg font-bold text-white">{stat.value}</span>
                </div>
              ))}
            </div>
          </motion.div>

          <motion.div
            initial={{ opacity: 0, x: -20 }}
            animate={{ opacity: 1, x: 0 }}
            transition={{ delay: 0.1 }}
            className="rounded-xl bg-slate-900/50 border border-slate-800/50 backdrop-blur-sm p-6"
          >
            <h3 className="font-semibold text-white mb-4">图谱搜索</h3>
            <div className="relative">
              <input
                type="text"
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                onKeyPress={(e) => e.key === "Enter" && handleSearch()}
                placeholder="输入故障现象..."
                disabled={isSearching}
                className="w-full px-4 py-2 pl-10 rounded-lg bg-slate-800/50 border border-slate-700/50 text-white placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-blue-500/50 disabled:opacity-50"
              />
              <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" />
            </div>
            <motion.button
              whileHover={{ scale: 1.02 }}
              whileTap={{ scale: 0.98 }}
              onClick={handleSearch}
              disabled={!searchQuery.trim() || isSearching}
              className="w-full mt-3 px-4 py-2 rounded-lg bg-gradient-to-r from-blue-600 to-purple-600 text-white text-sm font-medium hover:shadow-lg hover:shadow-blue-500/20 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
            >
              {isSearching ? "搜索中..." : "🔍 搜索"}
            </motion.button>
          </motion.div>

          <motion.div
            initial={{ opacity: 0, x: -20 }}
            animate={{ opacity: 1, x: 0 }}
            transition={{ delay: 0.15 }}
            className="rounded-xl bg-slate-900/50 border border-slate-800/50 backdrop-blur-sm p-6"
          >
            <h3 className="font-semibold text-white mb-4">节点类型筛选</h3>
            <div className="space-y-2">
              {Object.entries(currentNodeTypeConfig).map(([type, config]) => (
                <motion.button
                  key={type}
                  whileHover={{ scale: 1.02 }}
                  whileTap={{ scale: 0.98 }}
                  onClick={() => handleTypeFilterToggle(type)}
                  className={`w-full px-3 py-2 rounded-lg transition-all flex items-center gap-2 ${
                    typeFilter.has(type)
                      ? "bg-slate-800/80 border border-slate-600"
                      : "bg-slate-800/30 border border-transparent opacity-50"
                  }`}
                >
                  <div
                    className="w-3 h-3 rounded-full"
                    style={{ backgroundColor: config.color }}
                  />
                  <span className="text-sm text-slate-300 flex-1 text-left">{config.label}</span>
                  {typeFilter.has(type) && (
                    <span className="text-xs text-green-400">✓</span>
                  )}
                </motion.button>
              ))}
            </div>
          </motion.div>

          <motion.div
            initial={{ opacity: 0, x: -20 }}
            animate={{ opacity: 1, x: 0 }}
            transition={{ delay: 0.2 }}
            className="rounded-xl bg-slate-900/50 border border-slate-800/50 backdrop-blur-sm p-6"
          >
            <h3 className="font-semibold text-white mb-4">搜索历史</h3>
            <div className="space-y-2">
              {searchHistory.map((item, index) => (
                <motion.div
                  key={index}
                  initial={{ opacity: 0, x: -10 }}
                  animate={{ opacity: 1, x: 0 }}
                  transition={{ delay: index * 0.05 }}
                  className="p-3 rounded-lg bg-slate-800/50 hover:bg-slate-800 transition-colors cursor-pointer"
                  whileHover={{ x: 5 }}
                  onClick={() => setSearchQuery(item.query)}
                >
                  <div className="text-sm text-white mb-1">{item.query}</div>
                  <div className="flex items-center justify-between">
                    <div className="text-xs text-slate-400">{item.result}</div>
                    <div className="text-xs text-slate-500">{item.timestamp}</div>
                  </div>
                </motion.div>
              ))}
            </div>
          </motion.div>

          <motion.div
            initial={{ opacity: 0, x: -20 }}
            animate={{ opacity: 1, x: 0 }}
            transition={{ delay: 0.3 }}
            className="rounded-xl bg-slate-900/50 border border-slate-800/50 backdrop-blur-sm p-6"
          >
            <h3 className="font-semibold text-white mb-4">知识抽取任务</h3>
            <div className="space-y-2">
              <motion.button
                whileHover={{ scale: 1.02, x: 5 }}
                whileTap={{ scale: 0.98 }}
                onClick={handleNewTask}
                className="w-full px-4 py-2 rounded-lg bg-slate-800/50 hover:bg-slate-800 text-sm text-slate-300 text-left transition-colors flex items-center gap-2"
              >
                <Plus className="w-4 h-4" />
                新建抽取任务
              </motion.button>
              <motion.button
                whileHover={{ scale: 1.02, x: 5 }}
                whileTap={{ scale: 0.98 }}
                onClick={handleViewResults}
                className="w-full px-4 py-2 rounded-lg bg-slate-800/50 hover:bg-slate-800 text-sm text-slate-300 text-left transition-colors"
              >
                📊 查看抽取结果
              </motion.button>
              <motion.button
                whileHover={{ scale: 1.02, x: 5 }}
                whileTap={{ scale: 0.98 }}
                onClick={handleKnowledgeFusion}
                className="w-full px-4 py-2 rounded-lg bg-slate-800/50 hover:bg-slate-800 text-sm text-slate-300 text-left transition-colors"
              >
                🔀 知识融合
              </motion.button>
              <motion.button
                whileHover={{ scale: 1.02, x: 5 }}
                whileTap={{ scale: 0.98 }}
                onClick={handleQualityEval}
                className="w-full px-4 py-2 rounded-lg bg-slate-800/50 hover:bg-slate-800 text-sm text-slate-300 text-left transition-colors"
              >
                ✓ 质量评估
              </motion.button>
            </div>
          </motion.div>
        </div>

        <div className="lg:col-span-3 rounded-xl bg-slate-900/50 border border-slate-800/50 backdrop-blur-sm overflow-hidden flex flex-col">
          <div className="px-6 py-4 border-b border-slate-800/50 bg-slate-900/30 flex items-center justify-between">
            <h2 className="font-semibold text-white flex items-center gap-2">
              <Network className="w-5 h-5 text-blue-400" />
              知识图谱可视化区域
              {hoveredNode && (
                <motion.span
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  className="ml-2 px-2 py-1 rounded bg-blue-500/20 text-blue-400 text-xs"
                >
                  悬停: {initialNodes.find((n) => n.id === hoveredNode)?.label}
                </motion.span>
              )}
            </h2>
            <div className="flex items-center gap-2 text-xs text-slate-400">
              <span>拖拽节点移动 | 双击展开关联</span>
            </div>
          </div>

          <div
            ref={containerRef}
            className="flex-1 relative bg-slate-950/50 overflow-hidden"
          >
            <svg ref={svgRef} className="w-full h-full" />

            <div className="absolute bottom-4 right-4 flex flex-col gap-2">
              <motion.button
                whileHover={{ scale: 1.1 }}
                whileTap={{ scale: 0.9 }}
                onClick={() => {
                  if (svgRef.current) {
                    const svg = d3.select(svgRef.current);
                    svg.transition().call(
                      d3.zoom<SVGSVGElement, unknown>().transform as any,
                      d3.zoomIdentity.scale(1.2)
                    );
                  }
                }}
                className="p-2 rounded-lg bg-slate-800/80 hover:bg-slate-700 transition-colors"
              >
                <ZoomIn className="w-4 h-4 text-slate-300" />
              </motion.button>
              <motion.button
                whileHover={{ scale: 1.1 }}
                whileTap={{ scale: 0.9 }}
                onClick={() => {
                  if (svgRef.current) {
                    const svg = d3.select(svgRef.current);
                    svg.transition().call(
                      d3.zoom<SVGSVGElement, unknown>().transform as any,
                      d3.zoomIdentity.scale(0.8)
                    );
                  }
                }}
                className="p-2 rounded-lg bg-slate-800/80 hover:bg-slate-700 transition-colors"
              >
                <ZoomOut className="w-4 h-4 text-slate-300" />
              </motion.button>
              <motion.button
                whileHover={{ scale: 1.1 }}
                whileTap={{ scale: 0.9 }}
                onClick={() => initGraph()}
                className="p-2 rounded-lg bg-slate-800/80 hover:bg-slate-700 transition-colors"
              >
                <Maximize2 className="w-4 h-4 text-slate-300" />
              </motion.button>
            </div>
          </div>

          <div className="px-6 py-4 border-t border-slate-800/50 bg-slate-900/30 flex items-center gap-6 flex-wrap">
            {Object.entries(currentNodeTypeConfig).map(([type, config]) => (
              <div
                key={type}
                className={`flex items-center gap-2 transition-opacity ${
                  typeFilter.has(type) ? "opacity-100" : "opacity-40"
                }`}
              >
                <div
                  className="w-3 h-3 rounded-full"
                  style={{ backgroundColor: config.color }}
                />
                <span className="text-xs text-slate-400">{config.label}</span>
              </div>
            ))}
            <div className="ml-auto text-xs text-slate-500">
              当前显示 {currentNodes.filter((n) => typeFilter.has(n.type)).length} 个节点 |{" "}
              {currentEdges.filter(
                (e) => typeFilter.has(currentNodes.find((n) => n.id === e.source)?.type || "") &&
                        typeFilter.has(currentNodes.find((n) => n.id === e.target)?.type || "")
              ).length} 条关系
            </div>
          </div>
        </div>
      </div>

      <Dialog open={showNodeDialog} onOpenChange={setShowNodeDialog}>
        <DialogContent className="bg-slate-900 border-slate-800">
          <DialogHeader>
            <DialogTitle className="text-white flex items-center gap-2">
              <Network className="w-5 h-5 text-blue-400" />
              {selectedNode?.label}
            </DialogTitle>
            <DialogDescription className="text-slate-400">
              节点详情信息
            </DialogDescription>
          </DialogHeader>
          {selectedNode && (
            <div className="space-y-4 mt-4">
              <div className="flex items-center gap-3">
                <div
                  className={`inline-flex px-3 py-1 rounded-full bg-gradient-to-br ${
                    currentNodeTypeConfig[selectedNode.type]?.gradient || "from-gray-500 to-gray-600"
                  } text-white text-sm`}
                >
                  {currentNodeTypeConfig[selectedNode.type]?.label || selectedNode.type}
                </div>
                <div className="text-sm text-slate-400">
                  关联节点: {getConnectedNodes(selectedNode.id).length} 个
                </div>
              </div>

              <div>
                <div className="text-sm text-slate-400 mb-2">详细描述</div>
                <div className="text-sm text-slate-300 p-3 rounded-lg bg-slate-800/50">
                  {selectedNode.description}
                </div>
              </div>

              {getConnectedNodes(selectedNode.id).length > 0 && (
                <div>
                  <div className="text-sm text-slate-400 mb-2">关联节点</div>
                  <div className="flex flex-wrap gap-2">
                    {getConnectedNodes(selectedNode.id).map((id) => {
                      const node = initialNodes.find((n) => n.id === id);
                      if (!node) return null;
                      return (
                        <motion.span
                          key={id}
                          whileHover={{ scale: 1.05 }}
                          className={`px-2 py-1 rounded text-xs cursor-pointer ${
                            highlightedNodes.has(id)
                              ? "bg-blue-500/30 text-blue-300 border border-blue-500/50"
                              : "bg-slate-800 text-slate-300 border border-slate-700"
                          }`}
                          onClick={() => {
                            const newNode = initialNodes.find((n) => n.id === id);
                            if (newNode) {
                              setSelectedNode(newNode);
                            }
                          }}
                        >
                          {node.label}
                        </motion.span>
                      );
                    })}
                  </div>
                </div>
              )}

              <div className="flex gap-2 pt-2">
                <motion.button
                  whileHover={{ scale: 1.05 }}
                  whileTap={{ scale: 0.95 }}
                  onClick={() => toast.info("编辑功能开发中")}
                  className="flex-1 px-4 py-2 rounded-lg bg-blue-600 hover:bg-blue-700 text-white text-sm transition-colors flex items-center justify-center gap-1"
                >
                  <Edit className="w-4 h-4" />
                  编辑节点
                </motion.button>
                <motion.button
                  whileHover={{ scale: 1.05 }}
                  whileTap={{ scale: 0.95 }}
                  onClick={() => {
                    setShowNodeDialog(false);
                    toast.success("已定位节点");
                  }}
                  className="flex-1 px-4 py-2 rounded-lg bg-slate-700 hover:bg-slate-600 text-white text-sm transition-colors flex items-center justify-center gap-1"
                >
                  <Eye className="w-4 h-4" />
                  定位节点
                </motion.button>
                <motion.button
                  whileHover={{ scale: 1.05 }}
                  whileTap={{ scale: 0.95 }}
                  onClick={() => {
                    setShowNodeDialog(false);
                    toast.error("删除功能已禁用");
                  }}
                  className="px-4 py-2 rounded-lg bg-red-600/50 text-red-300 text-sm transition-colors flex items-center justify-center gap-1 cursor-not-allowed"
                  disabled
                >
                  <Trash2 className="w-4 h-4" />
                </motion.button>
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>
    </div>
  );
}
