
import React, { useState, useRef, useEffect, useMemo } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { ArrowLeft, Play, Save, Rocket, Plus, Bot, UserCheck, Wrench, Ban, Zap, X, Copy, MousePointer2 } from 'lucide-react';
import { Button, Input, Badge } from '../components/UI';
import { Assistant, WorkflowNode, WorkflowEdge, Workflow } from '../types';
import { DebugDrawer } from './Assistants';
import { createWorkflow, fetchAssistants, fetchWorkflowById, updateWorkflow } from '../services/backendApi';

const toWorkflowNodeType = (type: WorkflowNode['type']): WorkflowNode['type'] => {
  if (type === 'conversation') return 'assistant';
  if (type === 'human') return 'human_transfer';
  return type;
};

const nodeRef = (node: WorkflowNode): string => node.id || node.name;
const edgeFromRef = (edge: WorkflowEdge): string => edge.fromNodeId || edge.from;
const edgeToRef = (edge: WorkflowEdge): string => edge.toNodeId || edge.to;

const getTemplateNodes = (templateType: string | null): WorkflowNode[] => {
  if (templateType === 'lead') {
    return [
      {
        id: 'introduction',
        name: 'introduction',
        type: 'conversation',
        isStart: true,
        metadata: { position: { x: 100, y: 100 } },
        prompt: "You are Morgan from GrowthPartners. Start with: 'Hello, this is Morgan from GrowthPartners. We help businesses improve their operational efficiency through custom software solutions. Do you have a few minutes to chat about how we might be able to help your business?'",
        messagePlan: { firstMessage: "Hello, this is Morgan from GrowthPartners. Do you have a few minutes to chat?" }
      },
      {
        id: 'need_discovery',
        name: 'need_discovery',
        type: 'conversation',
        metadata: { position: { x: 450, y: 250 } },
        prompt: "Conduct need discovery by asking about business challenges...",
        variableExtractionPlan: {
          output: [
            { title: 'industry', type: 'string', description: 'user industry' },
            { title: 'pain_points', type: 'string', description: 'main challenges' }
          ]
        }
      },
      {
        id: 'hangup_node',
        name: 'hangup_node',
        type: 'end',
        metadata: { position: { x: 450, y: 550 } },
        tool: {
          type: 'endCall',
          function: { name: 'hangup', parameters: {} },
          messages: [{ type: 'request-start', content: 'Thank you for your time!', blocking: true }]
        }
      }
    ];
  }
  return [
    {
      id: 'start_node',
      name: 'start_node',
      type: 'conversation',
      isStart: true,
      metadata: { position: { x: 200, y: 200 } },
      prompt: '欢迎对话系统...',
      messagePlan: { firstMessage: '你好！' }
    }
  ];
};

export const WorkflowEditorPage: React.FC = () => {
  const navigate = useNavigate();
  const { id } = useParams();
  const [searchParams] = useSearchParams();
  
  // Template data for new workflows
  const templateName = searchParams.get('name');
  const templateType = searchParams.get('template');
  const [name, setName] = useState(templateName || '新工作流');
  const [nodes, setNodes] = useState<WorkflowNode[]>(() => getTemplateNodes(templateType));
  const [edges, setEdges] = useState<WorkflowEdge[]>([]);
  const [createdAt, setCreatedAt] = useState('');
  const [assistants, setAssistants] = useState<Assistant[]>([]);
  
  const [selectedNodeName, setSelectedNodeName] = useState<string | null>(null);
  const [isAddMenuOpen, setIsAddMenuOpen] = useState(false);
  const [isDebugOpen, setIsDebugOpen] = useState(false);
  const [zoom, setZoom] = useState(1);
  const [panOffset, setPanOffset] = useState({ x: 0, y: 0 });
  
  const [draggingNodeName, setDraggingNodeName] = useState<string | null>(null);
  const [isPanning, setIsPanning] = useState(false);
  const dragOffset = useRef({ x: 0, y: 0 });
  const panStart = useRef({ x: 0, y: 0 });

  const selectedNode = nodes.find(n => n.name === selectedNodeName);
  const selectedNodeRef = selectedNode ? nodeRef(selectedNode) : null;
  const outgoingEdges = selectedNodeRef
    ? edges.filter((edge) => edgeFromRef(edge) === selectedNodeRef)
    : [];
  const resolvedEdges = useMemo(() => {
    return edges
      .map((edge, index) => {
        const from = nodes.find((node) => nodeRef(node) === edgeFromRef(edge));
        const to = nodes.find((node) => nodeRef(node) === edgeToRef(edge));
        if (!from || !to) return null;
        return {
          key: edge.id || `${edgeFromRef(edge)}->${edgeToRef(edge)}:${index}`,
          edge,
          from,
          to,
        };
      })
      .filter((item): item is { key: string; edge: WorkflowEdge; from: WorkflowNode; to: WorkflowNode } => Boolean(item));
  }, [edges, nodes]);

  const workflowRuntimeMetadata = useMemo(() => {
    return {
      id: id || 'draft_workflow',
      name,
      nodes: nodes.map((node) => {
        const assistant = node.assistantId
          ? assistants.find((item) => item.id === node.assistantId)
          : undefined;
        return {
          id: nodeRef(node),
          name: node.name || nodeRef(node),
          type: toWorkflowNodeType(node.type),
          isStart: node.isStart,
          prompt: node.prompt,
          messagePlan: node.messagePlan,
          assistantId: node.assistantId,
          assistant: assistant
            ? {
                systemPrompt: node.prompt || assistant.prompt || '',
                greeting: node.messagePlan?.firstMessage || assistant.opener || '',
              }
            : undefined,
          tool: node.tool,
          metadata: node.metadata,
        };
      }),
      edges: edges.map((edge, index) => {
        const fromNodeId = edgeFromRef(edge);
        const toNodeId = edgeToRef(edge);
        return {
          id: edge.id || `edge_${index + 1}`,
          fromNodeId,
          toNodeId,
          label: edge.label,
          priority: edge.priority ?? 100,
          condition: edge.condition || (edge.label ? { type: 'contains', source: 'user', value: edge.label } : { type: 'always' }),
        };
      }),
    };
  }, [assistants, edges, id, name, nodes]);

  // Scroll Zoom handler
  const handleWheel = (e: React.WheelEvent) => {
    e.preventDefault();
    const zoomSpeed = 0.001;
    const newZoom = Math.min(Math.max(zoom - e.deltaY * zoomSpeed, 0.2), 3);
    setZoom(newZoom);
  };

  // Middle mouse click handler for panning
  const handleMouseDown = (e: React.MouseEvent) => {
    // Button 1 is middle mouse
    if (e.button === 1) {
        e.preventDefault();
        setIsPanning(true);
        panStart.current = { x: e.clientX - panOffset.x, y: e.clientY - panOffset.y };
    }
  };

  const handleNodeMouseDown = (e: React.MouseEvent, nodeName: string) => {
    if (e.button !== 0) return; // Only left click for nodes
    e.stopPropagation();
    setSelectedNodeName(nodeName);
    setDraggingNodeName(nodeName);
    const node = nodes.find(n => n.name === nodeName);
    if (node) {
        dragOffset.current = {
            x: e.clientX - node.metadata.position.x * zoom,
            y: e.clientY - node.metadata.position.y * zoom
        };
    }
  };

  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
        if (draggingNodeName) {
            setNodes(prev => prev.map(n => 
                n.name === draggingNodeName 
                ? { ...n, metadata: { ...n.metadata, position: { x: (e.clientX - dragOffset.current.x) / zoom, y: (e.clientY - dragOffset.current.y) / zoom } } } 
                : n
            ));
        } else if (isPanning) {
            setPanOffset({
                x: e.clientX - panStart.current.x,
                y: e.clientY - panStart.current.y
            });
        }
    };
    const handleMouseUp = (e: MouseEvent) => {
        setDraggingNodeName(null);
        setIsPanning(false);
    };

    window.addEventListener('mousemove', handleMouseMove);
    window.addEventListener('mouseup', handleMouseUp);
    return () => {
        window.removeEventListener('mousemove', handleMouseMove);
        window.removeEventListener('mouseup', handleMouseUp);
    };
  }, [draggingNodeName, isPanning, zoom]);

  useEffect(() => {
    const loadData = async () => {
      try {
        const assistantList = await fetchAssistants();
        setAssistants(assistantList);
      } catch (error) {
        console.error(error);
      }
    };
    loadData();
  }, []);

  useEffect(() => {
    if (!id) return;
    const loadWorkflow = async () => {
      try {
        const workflow = await fetchWorkflowById(id);
        setName(workflow.name);
        setNodes(workflow.nodes);
        setEdges(workflow.edges);
        setCreatedAt(workflow.createdAt);
      } catch (error) {
        console.error(error);
        alert('加载工作流失败。');
      }
    };

    loadWorkflow();
  }, [id]);

  const addNode = (type: WorkflowNode['type']) => {
      const nodeId = `${type}_${Date.now()}`;
      const newNode: WorkflowNode = {
          id: nodeId,
          name: nodeId,
          type,
          metadata: { position: { x: (300 - panOffset.x) / zoom, y: (300 - panOffset.y) / zoom } },
          prompt: type === 'conversation' ? '输入该节点的 Prompt...' : '',
          tool: type === 'end' ? { type: 'endCall', function: { name: 'hangup', parameters: {} } } : undefined
      };
      setNodes([...nodes, newNode]);
      setIsAddMenuOpen(false);
  };

  const updateNodeData = (field: string, value: any) => {
    if (!selectedNodeName) return;
    setNodes(prev => {
      const currentNode = prev.find((n) => n.name === selectedNodeName);
      if (!currentNode) return prev;

      const oldRef = nodeRef(currentNode);
      const updatedNodes = prev.map((node) => {
        if (node.name !== selectedNodeName) {
          if (field === 'isStart' && value === true) {
            return { ...node, isStart: false };
          }
          return node;
        }
        if (field === 'isStart' && value === true) {
          return { ...node, isStart: true };
        }
        return { ...node, [field]: value };
      });

      if (field === 'name') {
        const renamed = updatedNodes.find((n) => n.name === value);
        const newRef = renamed ? nodeRef(renamed) : String(value);
        setEdges((prevEdges) =>
          prevEdges.map((edge) => {
            const from = edgeFromRef(edge);
            const to = edgeToRef(edge);
            if (from !== oldRef && to !== oldRef) return edge;
            const nextFrom = from === oldRef ? newRef : from;
            const nextTo = to === oldRef ? newRef : to;
            return {
              ...edge,
              fromNodeId: nextFrom,
              toNodeId: nextTo,
              from: nextFrom,
              to: nextTo,
            };
          })
        );
      }

      return updatedNodes;
    });
  };

  const addEdgeFromSelected = () => {
    if (!selectedNode) return;
    const fromNodeId = nodeRef(selectedNode);
    const target = nodes.find((node) => nodeRef(node) !== fromNodeId);
    if (!target) return;
    const toNodeId = nodeRef(target);
    const edgeId = `edge_${Date.now()}`;
    setEdges((prev) => [
      ...prev,
      {
        id: edgeId,
        fromNodeId,
        toNodeId,
        from: fromNodeId,
        to: toNodeId,
        condition: { type: 'always' },
      },
    ]);
  };

  const updateOutgoingEdge = (edgeId: string, patch: Partial<WorkflowEdge>) => {
    setEdges((prev) =>
      prev.map((edge, index) => {
        const idForCompare = edge.id || `${edgeFromRef(edge)}->${edgeToRef(edge)}:${index}`;
        if (idForCompare !== edgeId) return edge;
        const next = { ...edge, ...patch };
        const fromNodeId = edgeFromRef(next);
        const toNodeId = edgeToRef(next);
        return {
          ...next,
          fromNodeId,
          toNodeId,
          from: fromNodeId,
          to: toNodeId,
        };
      })
    );
  };

  const removeOutgoingEdge = (edgeId: string) => {
    setEdges((prev) =>
      prev.filter((edge, index) => {
        const idForCompare = edge.id || `${edgeFromRef(edge)}->${edgeToRef(edge)}:${index}`;
        return idForCompare !== edgeId;
      })
    );
  };

  const handleSave = async () => {
    const now = new Date().toISOString().replace('T', ' ').substring(0, 16);
    const workflowPayload: Partial<Workflow> = {
      name,
      nodeCount: nodes.length,
      createdAt: createdAt || now,
      updatedAt: now,
      nodes,
      edges,
    };

    try {
      if (id) {
        await updateWorkflow(id, workflowPayload);
      } else {
        await createWorkflow(workflowPayload);
      }
      alert('保存成功！工作流已同步至列表。');
      navigate('/workflows');
    } catch (error) {
      console.error(error);
      alert('保存失败，请稍后重试。');
    }
  };

  return (
    <div className="flex flex-col h-[calc(100vh-6rem)] relative bg-card/10 border border-white/5 rounded-2xl overflow-hidden animate-in fade-in duration-300">
      {/* Editor Header */}
      <header className="h-14 border-b border-white/5 bg-white/[0.02] flex items-center justify-between px-4 shrink-0">
        <div className="flex items-center space-x-3">
            <Button variant="ghost" size="icon" onClick={() => navigate('/workflows')} className="h-8 w-8">
                <ArrowLeft className="h-4 w-4" />
            </Button>
            <div className="h-4 w-px bg-white/10"></div>
            <Input 
                value={name} 
                onChange={e => setName(e.target.value)} 
                className="bg-transparent border-transparent focus:bg-white/5 font-bold text-sm h-8 w-48 shadow-none text-white"
            />
        </div>
        <div className="flex items-center space-x-2">
            <Button variant="outline" size="sm" onClick={() => setIsDebugOpen(true)}>
                <Play className="mr-1.5 h-3.5 w-3.5" /> 调试
            </Button>
            <Button variant="secondary" size="sm" onClick={handleSave}>
                <Save className="mr-1.5 h-3.5 w-3.5" /> 保存
            </Button>
            <Button size="sm" onClick={() => alert('发布成功！')}>
                <Rocket className="mr-1.5 h-3.5 w-3.5" /> 发布
            </Button>
        </div>
      </header>

      {/* Canvas Area */}
      <div 
        className="flex-1 relative bg-[radial-gradient(rgba(255,255,255,0.03)_1px,transparent_1px)] bg-[size:24px_24px] overflow-hidden select-none cursor-crosshair"
        onWheel={handleWheel}
        onMouseDown={handleMouseDown}
      >
        {/* Floating Controls */}
        <div className="absolute top-4 left-4 z-10 flex flex-col items-start gap-2">
            <Button 
                className="rounded-xl shadow-lg h-10 px-5 bg-primary text-primary-foreground font-semibold hover:bg-primary/90"
                onClick={() => setIsAddMenuOpen(!isAddMenuOpen)}
            >
                <Plus className="mr-2 h-4 w-4" /> {isAddMenuOpen ? '取消' : '添加节点'}
            </Button>
            {isAddMenuOpen && (
                <div className="bg-background/90 backdrop-blur-xl border border-white/10 rounded-xl p-1.5 w-48 shadow-2xl animate-in slide-in-from-top-2">
                    <button onClick={() => addNode('conversation')} className="flex items-center w-full p-2.5 hover:bg-primary/10 rounded-lg transition-colors text-sm text-left text-white">
                        <Bot className="w-4 h-4 mr-3 text-primary" /> <span>对话节点</span>
                    </button>
                    <button onClick={() => addNode('tool')} className="flex items-center w-full p-2.5 hover:bg-purple-400/10 rounded-lg transition-colors text-sm text-left text-white">
                        <Wrench className="w-4 h-4 mr-3 text-purple-400" /> <span>工具节点</span>
                    </button>
                    <button onClick={() => addNode('human')} className="flex items-center w-full p-2.5 hover:bg-orange-400/10 rounded-lg transition-colors text-sm text-left text-white">
                        <UserCheck className="w-4 h-4 mr-3 text-orange-400" /> <span>转人工</span>
                    </button>
                    <button onClick={() => addNode('end')} className="flex items-center w-full p-2.5 hover:bg-destructive/10 rounded-lg transition-colors text-sm text-left text-destructive">
                        <Ban className="w-4 h-4 mr-3" /> <span>结束对话</span>
                    </button>
                </div>
            )}
            <div className="flex items-center gap-2 bg-white/5 border border-white/10 rounded-lg px-2 py-1 text-[10px] text-muted-foreground font-mono">
                <span>{Math.round(zoom * 100)}%</span>
                <span className="opacity-30">|</span>
                <span>POS: {Math.round(panOffset.x)}, {Math.round(panOffset.y)}</span>
            </div>
        </div>

        {/* Scalable Container */}
        <div 
            className="absolute inset-0"
            style={{ 
                transform: `translate(${panOffset.x}px, ${panOffset.y}px) scale(${zoom})`,
                transformOrigin: '0 0'
            }}
        >
            <svg className="absolute inset-0 pointer-events-none overflow-visible">
              {resolvedEdges.map(({ key, from, to, edge }) => {
                const x1 = from.metadata.position.x + 112;
                const y1 = from.metadata.position.y + 88;
                const x2 = to.metadata.position.x + 112;
                const y2 = to.metadata.position.y;
                const midY = (y1 + y2) / 2;
                const d = `M ${x1} ${y1} C ${x1} ${midY}, ${x2} ${midY}, ${x2} ${y2}`;
                return (
                  <g key={key}>
                    <path d={d} stroke="rgba(148,163,184,0.55)" strokeWidth={2} fill="none" />
                    {(edge.label || edge.condition?.value) && (
                      <text x={(x1 + x2) / 2} y={midY - 6} fill="rgba(226,232,240,0.8)" fontSize={10} textAnchor="middle">
                        {edge.label || edge.condition?.value}
                      </text>
                    )}
                  </g>
                );
              })}
            </svg>
            {nodes.map(node => (
                <div 
                    key={nodeRef(node)}
                    onMouseDown={(e) => handleNodeMouseDown(e, node.name)}
                    style={{ left: node.metadata.position.x, top: node.metadata.position.y }}
                    className={`absolute w-56 p-4 rounded-xl border bg-card/70 backdrop-blur-sm cursor-grab active:cursor-grabbing group transition-shadow ${selectedNodeName === node.name ? 'border-primary shadow-[0_0_30px_rgba(6,182,212,0.3)]' : 'border-white/10 hover:border-white/30'}`}
                >
                    <div className="flex items-center justify-between mb-3">
                        <div className="flex items-center space-x-2 overflow-hidden">
                            <NodeIcon type={node.type} />
                            <span className="font-semibold text-[10px] truncate uppercase tracking-tight text-white">{node.name}</span>
                        </div>
                        {node.isStart && <Badge variant="default" className="scale-75 origin-right">START</Badge>}
                    </div>
                    <div className="text-[10px] text-muted-foreground line-clamp-3 italic opacity-60 leading-relaxed">
                        {node.prompt || (node.tool ? `Action: ${node.tool.type}` : '待配置逻辑...')}
                    </div>

                    {/* Port simulation */}
                    <div className="absolute -bottom-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-primary rounded-full border-2 border-background opacity-0 group-hover:opacity-100 cursor-crosshair transition-opacity shadow-[0_0_5px_rgba(6,182,212,0.5)]"></div>
                    <div className="absolute -top-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-muted rounded-full border-2 border-background opacity-0 group-hover:opacity-100 cursor-crosshair transition-opacity"></div>
                </div>
            ))}
        </div>

        {/* Bottom Right: Minimap */}
        <div className="absolute bottom-6 right-6 w-48 h-32 bg-black/60 border border-white/10 rounded-2xl shadow-2xl pointer-events-none overflow-hidden flex flex-col backdrop-blur-md">
            <div className="p-2 border-b border-white/5 bg-white/5 text-[9px] text-muted-foreground font-bold tracking-[0.2em] text-center uppercase">Minimap</div>
            <div className="flex-1 relative p-3 opacity-60">
                <div className="absolute inset-0 flex items-center justify-center">
                    <div className="relative w-full h-full">
                        {nodes.map((n, i) => {
                            // Simple scaling for minimap
                            const mx = (n.metadata.position.x / 10) % 100;
                            const my = (n.metadata.position.y / 10) % 100;
                            return (
                                <div 
                                    key={i} 
                                    className={`absolute w-3 h-2 rounded-sm ${
                                      n.type === 'conversation' || n.type === 'assistant' || n.type === 'start'
                                        ? 'bg-primary'
                                        : n.type === 'end'
                                          ? 'bg-destructive'
                                          : 'bg-white/40'
                                    }`}
                                    style={{ left: `${20 + mx}%`, top: `${20 + my}%` }}
                                ></div>
                            );
                        })}
                    </div>
                </div>
                {/* Viewport visualization */}
                <div 
                  className="absolute border border-primary/40 bg-primary/5 rounded shadow-sm"
                  style={{ width: '40%', height: '40%', left: '30%', top: '30%' }}
                />
            </div>
        </div>

        {/* Navigator Guide */}
        <div className="absolute bottom-4 left-4 text-[10px] text-muted-foreground/30 font-mono flex items-center gap-2">
            <MousePointer2 className="w-3 h-3" /> 鼠标中键拖拽画布 | 滚轮缩放
        </div>
      </div>

      {/* Right Settings Panel */}
      {selectedNode && (
          <div className="absolute right-0 top-14 bottom-0 w-80 border-l border-white/10 bg-background/95 backdrop-blur-2xl flex flex-col animate-in slide-in-from-right duration-300 z-20 shadow-[-10px_0_30px_rgba(0,0,0,0.5)]">
              <div className="p-4 border-b border-white/5 flex items-center justify-between bg-white/5">
                  <h3 className="text-sm font-bold uppercase tracking-widest text-primary">节点设置</h3>
                  <Button variant="ghost" size="icon" onClick={() => setSelectedNodeName(null)} className="h-8 w-8">
                      <X className="h-4 w-4" />
                  </Button>
              </div>
              <div className="flex-1 overflow-y-auto p-5 space-y-6 custom-scrollbar">
                  <div className="space-y-2">
                      <label className="text-[10px] text-muted-foreground uppercase font-mono tracking-widest">唯一标识 (Node Name)</label>
                      <Input 
                        value={selectedNode.name} 
                        onChange={e => updateNodeData('name', e.target.value)}
                        className="h-8 text-xs font-mono text-white bg-white/10"
                      />
                  </div>

                  <div className="space-y-2">
                      <label className="text-[10px] text-muted-foreground uppercase font-mono tracking-widest">节点类型</label>
                      <Badge variant="outline" className="w-fit">{selectedNode.type.toUpperCase()}</Badge>
                  </div>

                  {(selectedNode.type === 'conversation' || selectedNode.type === 'assistant' || selectedNode.type === 'start') && (
                      <>
                        <div className="space-y-2">
                            <label className="text-[10px] text-muted-foreground uppercase font-mono tracking-widest">绑定小助手</label>
                            <select
                              value={selectedNode.assistantId || ''}
                              onChange={(e) => updateNodeData('assistantId', e.target.value || undefined)}
                              className="w-full h-8 bg-white/5 border border-white/10 rounded-md px-2 text-xs text-white focus:outline-none focus:ring-1 focus:ring-primary/50"
                            >
                              <option value="">无（仅用本节点 Prompt）</option>
                              {assistants.map((assistant) => (
                                <option key={assistant.id} value={assistant.id}>
                                  {assistant.name}
                                </option>
                              ))}
                            </select>
                        </div>
                        <div className="space-y-2">
                            <label className="text-[10px] text-muted-foreground uppercase font-mono tracking-widest">Prompt (指令)</label>
                            <textarea 
                                className="w-full h-48 bg-white/5 border border-white/10 rounded-lg p-3 text-xs focus:outline-none focus:ring-1 focus:ring-primary/50 text-white placeholder:text-muted-foreground/30 leading-relaxed"
                                value={selectedNode.prompt || ''}
                                onChange={e => updateNodeData('prompt', e.target.value)}
                                placeholder="输入该节点的业务规则、语气要求和回复逻辑..."
                            />
                        </div>
                        <div className="space-y-2">
                            <label className="text-[10px] text-muted-foreground uppercase font-mono tracking-widest">First Message (开场白)</label>
                            <Input 
                                value={selectedNode.messagePlan?.firstMessage || ''}
                                onChange={e => updateNodeData('messagePlan', { ...selectedNode.messagePlan, firstMessage: e.target.value })}
                                className="h-8 text-xs text-white"
                                placeholder="进入该节点时 AI 主动发起的消息..."
                            />
                        </div>
                      </>
                  )}

                  {selectedNode.type === 'end' && (
                      <div className="p-4 rounded-xl border border-destructive/20 bg-destructive/5 text-xs text-destructive/80 space-y-2">
                          <p className="font-bold">结束对话节点</p>
                          <p>到达此节点后，系统将根据配置执行挂断操作。</p>
                      </div>
                  )}

                  <div className="pt-4 border-t border-white/5">
                      <label className="flex items-center gap-3 cursor-pointer group">
                          <input 
                            type="checkbox" 
                            checked={selectedNode.isStart} 
                            onChange={e => updateNodeData('isStart', e.target.checked)}
                            className="w-4 h-4 rounded accent-primary border-white/10 bg-white/5"
                          />
                          <span className="text-[10px] text-muted-foreground group-hover:text-primary transition-colors uppercase font-mono tracking-widest">起始节点 (Start Node)</span>
                      </label>
                  </div>

                  <div className="pt-4 border-t border-white/5 space-y-3">
                      <div className="flex items-center justify-between">
                        <label className="text-[10px] text-muted-foreground uppercase font-mono tracking-widest">出边路由</label>
                        <Button variant="outline" size="sm" className="h-7 text-[11px]" onClick={addEdgeFromSelected}>
                          <Plus className="w-3 h-3 mr-1" /> 新增出边
                        </Button>
                      </div>
                      {outgoingEdges.length === 0 && (
                        <p className="text-[11px] text-muted-foreground">当前节点暂无出边，调试时不会发生节点转移。</p>
                      )}
                      {outgoingEdges.map((edge, index) => {
                        const edgeId = edge.id || `${edgeFromRef(edge)}->${edgeToRef(edge)}:${index}`;
                        const keyword = edge.condition?.value || edge.label || '';
                        return (
                          <div key={edgeId} className="rounded-lg border border-white/10 p-3 space-y-2 bg-white/5">
                            <div className="flex items-center justify-between">
                              <span className="text-[10px] uppercase tracking-widest text-muted-foreground">边 #{index + 1}</span>
                              <button
                                className="text-[10px] text-destructive hover:underline"
                                onClick={() => removeOutgoingEdge(edgeId)}
                              >
                                删除
                              </button>
                            </div>
                            <div className="space-y-1">
                              <label className="text-[10px] text-muted-foreground">目标节点</label>
                              <select
                                value={edgeToRef(edge)}
                                onChange={(e) =>
                                  updateOutgoingEdge(edgeId, {
                                    toNodeId: e.target.value,
                                    to: e.target.value,
                                  })
                                }
                                className="w-full h-8 bg-black/20 border border-white/10 rounded-md px-2 text-xs text-white focus:outline-none"
                              >
                                {nodes
                                  .filter((node) => nodeRef(node) !== selectedNodeRef)
                                  .map((node) => (
                                    <option key={nodeRef(node)} value={nodeRef(node)}>
                                      {node.name}
                                    </option>
                                  ))}
                              </select>
                            </div>
                            <div className="space-y-1">
                              <label className="text-[10px] text-muted-foreground">条件关键词（留空=always）</label>
                              <Input
                                value={keyword}
                                onChange={(e) => {
                                  const v = e.target.value;
                                  updateOutgoingEdge(edgeId, {
                                    label: v || undefined,
                                    condition: v
                                      ? { type: 'contains', source: 'user', value: v }
                                      : { type: 'always' },
                                  });
                                }}
                                className="h-8 text-xs"
                                placeholder="例如：退款 / 投诉 / 结束"
                              />
                            </div>
                          </div>
                        );
                      })}
                  </div>
              </div>
          </div>
      )}

      {/* Debug Side Drawer */}
      <DebugDrawer 
        isOpen={isDebugOpen} 
        onClose={() => setIsDebugOpen(false)} 
        sessionMetadataExtras={{ workflow: workflowRuntimeMetadata }}
        onProtocolEvent={(event) => {
          if (event?.type !== 'workflow.node.entered') return;
          const incomingNodeId = String(event.nodeId || '');
          const matched = nodes.find((node) => nodeRef(node) === incomingNodeId || node.name === incomingNodeId);
          if (matched) {
            setSelectedNodeName(matched.name);
          }
        }}
        assistant={assistants[0] || {
          id: 'debug',
          name: 'Debug Assistant',
          callCount: 0,
          opener: 'Hello!',
          prompt: '',
          knowledgeBaseId: '',
          language: 'zh',
          voice: '',
          speed: 1,
          hotwords: [],
        }}
        voices={[]}
        llmModels={[]}
        asrModels={[]}
      />
    </div>
  );
};

const NodeIcon = ({ type }: { type: WorkflowNode['type'] }) => {
    switch (type) {
        case 'conversation': return <Bot className="h-4 w-4 text-primary" />;
        case 'assistant': return <Bot className="h-4 w-4 text-primary" />;
        case 'start': return <Bot className="h-4 w-4 text-cyan-300" />;
        case 'human': return <UserCheck className="h-4 w-4 text-orange-400" />;
        case 'human_transfer': return <UserCheck className="h-4 w-4 text-orange-400" />;
        case 'tool': return <Wrench className="h-4 w-4 text-purple-400" />;
        case 'end': return <Ban className="h-4 w-4 text-destructive" />;
        default: return <MousePointer2 className="h-4 w-4" />;
    }
};
