/**
 * 流程设计画布 - 使用 React Flow
 */

'use client';

import React, { useCallback, useMemo, useRef } from 'react';
import ReactFlow, {
  Node,
  Edge,
  Connection,
  addEdge,
  Background,
  Controls,
  MiniMap,
  useNodesState,
  useEdgesState,
  MarkerType,
  NodeTypes,
  EdgeTypes,
  OnNodesChange,
  OnEdgesChange,
  OnConnect,
  ReactFlowInstance,
  ConnectionLineType,
} from 'reactflow';
import 'reactflow/dist/style.css';
import { useDroppable } from '@dnd-kit/core';
import {
  Play,
  Square,
  UserCheck,
  Send,
  GitBranch,
  GitMerge,
  X,
} from 'lucide-react';
import { useProcessDesignerStore } from './useProcessDesignerStore';
import {
  ProcessNode,
  ProcessNodeType,
  PROCESS_NODE_TYPES,
  generateNodeId,
  generateEdgeId,
} from './types';

// 图标映射
const iconMap: Record<string, React.ElementType> = {
  Play,
  Square,
  UserCheck,
  Send,
  GitBranch,
  GitMerge,
};

// 自定义节点组件
interface CustomNodeData {
  label: string;
  type: ProcessNodeType;
  config?: any;
  selected?: boolean;
}

function StartNode({ data, selected }: { data: CustomNodeData; selected?: boolean }) {
  return (
    <div
      className={`
        w-12 h-12 rounded-full bg-green-500 flex items-center justify-center
        shadow-md transition-all
        ${selected ? 'ring-2 ring-blue-500 ring-offset-2' : ''}
      `}
    >
      <Play className="w-5 h-5 text-white fill-white" />
    </div>
  );
}

function EndNode({ data, selected }: { data: CustomNodeData; selected?: boolean }) {
  return (
    <div
      className={`
        w-12 h-12 rounded-full bg-red-500 flex items-center justify-center
        shadow-md transition-all
        ${selected ? 'ring-2 ring-blue-500 ring-offset-2' : ''}
      `}
    >
      <Square className="w-4 h-4 text-white fill-white" />
    </div>
  );
}

function UserTaskNode({ data, selected }: { data: CustomNodeData; selected?: boolean }) {
  return (
    <div
      className={`
        min-w-[120px] px-4 py-3 rounded-lg bg-white border-2 shadow-md
        transition-all
        ${selected ? 'border-blue-500' : 'border-blue-300'}
      `}
    >
      <div className="flex items-center gap-2">
        <div className="w-8 h-8 rounded-md bg-blue-500 flex items-center justify-center">
          <UserCheck className="w-4 h-4 text-white" />
        </div>
        <div className="flex-1 min-w-0">
          <div className="text-sm font-medium text-gray-800 truncate">
            {data.label}
          </div>
          <div className="text-xs text-gray-500">审批节点</div>
        </div>
      </div>
    </div>
  );
}

function CCNode({ data, selected }: { data: CustomNodeData; selected?: boolean }) {
  return (
    <div
      className={`
        min-w-[120px] px-4 py-3 rounded-lg bg-white border-2 shadow-md
        transition-all
        ${selected ? 'border-purple-500' : 'border-purple-300'}
      `}
    >
      <div className="flex items-center gap-2">
        <div className="w-8 h-8 rounded-md bg-purple-500 flex items-center justify-center">
          <Send className="w-4 h-4 text-white" />
        </div>
        <div className="flex-1 min-w-0">
          <div className="text-sm font-medium text-gray-800 truncate">
            {data.label}
          </div>
          <div className="text-xs text-gray-500">抄送节点</div>
        </div>
      </div>
    </div>
  );
}

function GatewayNode({ data, selected }: { data: CustomNodeData; selected?: boolean }) {
  const isParallel = data.type === 'PARALLEL_GATEWAY';
  const Icon = isParallel ? GitMerge : GitBranch;
  const color = isParallel ? 'cyan' : 'amber';
  
  return (
    <div
      className={`
        w-12 h-12 rounded-lg transform rotate-45 flex items-center justify-center
        shadow-md transition-all
        ${selected ? 'ring-2 ring-blue-500 ring-offset-2' : ''}
        ${isParallel ? 'bg-cyan-500' : 'bg-amber-500'}
      `}
    >
      <Icon className="w-5 h-5 text-white transform -rotate-45" />
    </div>
  );
}

// 节点类型映射
const nodeTypes: NodeTypes = {
  START: StartNode,
  END: EndNode,
  USER_TASK: UserTaskNode,
  CC: CCNode,
  EXCLUSIVE_GATEWAY: GatewayNode,
  PARALLEL_GATEWAY: GatewayNode,
};

interface ProcessCanvasProps {
  onNodeDrop?: (type: ProcessNodeType, position: { x: number; y: number }) => void;
}

export function ProcessCanvas({ onNodeDrop }: ProcessCanvasProps) {
  const reactFlowWrapper = useRef<HTMLDivElement>(null);
  const [reactFlowInstance, setReactFlowInstance] = React.useState<ReactFlowInstance | null>(null);
  
  const {
    nodes: processNodes,
    edges: processEdges,
    selectedNodeId,
    addNode,
    addEdge: addProcessEdge,
    updateNode,
    removeNode,
    removeEdge,
    moveNode,
    selectNode,
    selectEdge,
  } = useProcessDesignerStore();

  // 设置 droppable
  const { setNodeRef, isOver } = useDroppable({
    id: 'process-canvas',
    data: {
      type: 'canvas',
    },
  });

  // 转换节点数据为 React Flow 格式
  const nodes: Node[] = useMemo(() => {
    return processNodes.map((node) => ({
      id: node.id,
      type: node.type,
      position: node.position,
      data: {
        label: node.name,
        type: node.type,
        config: node.config,
        selected: node.id === selectedNodeId,
      },
      selected: node.id === selectedNodeId,
    }));
  }, [processNodes, selectedNodeId]);

  // 转换连线数据为 React Flow 格式
  const edges: Edge[] = useMemo(() => {
    return processEdges.map((edge) => ({
      id: edge.id,
      source: edge.source,
      target: edge.target,
      sourceHandle: edge.sourceHandle,
      targetHandle: edge.targetHandle,
      label: edge.label,
      type: 'smoothstep',
      animated: false,
      markerEnd: {
        type: MarkerType.ArrowClosed,
        width: 15,
        height: 15,
        color: '#94a3b8',
      },
      style: {
        stroke: '#94a3b8',
        strokeWidth: 2,
      },
    }));
  }, [processEdges]);

  // 节点拖拽结束
  const onNodesChange: OnNodesChange = useCallback(
    (changes) => {
      changes.forEach((change) => {
        if (change.type === 'position' && change.position && change.dragging === false) {
          moveNode(change.id, change.position);
        }
      });
    },
    [moveNode]
  );

  // 连线变化
  const onEdgesChange: OnEdgesChange = useCallback(
    (changes) => {
      changes.forEach((change) => {
        if (change.type === 'remove') {
          removeEdge(change.id);
        }
      });
    },
    [removeEdge]
  );

  // 创建新连线
  const onConnect: OnConnect = useCallback(
    (connection: Connection) => {
      if (connection.source && connection.target) {
        addProcessEdge({
          id: generateEdgeId(),
          source: connection.source,
          target: connection.target,
          sourceHandle: connection.sourceHandle || undefined,
          targetHandle: connection.targetHandle || undefined,
        });
      }
    },
    [addProcessEdge]
  );

  // 点击节点
  const onNodeClick = useCallback(
    (_: React.MouseEvent, node: Node) => {
      selectNode(node.id);
    },
    [selectNode]
  );

  // 点击连线
  const onEdgeClick = useCallback(
    (_: React.MouseEvent, edge: Edge) => {
      selectEdge(edge.id);
    },
    [selectEdge]
  );

  // 点击画布空白处
  const onPaneClick = useCallback(() => {
    selectNode(null);
    selectEdge(null);
  }, [selectNode, selectEdge]);

  // 删除选中节点
  const onKeyDown = useCallback(
    (event: React.KeyboardEvent) => {
      if (event.key === 'Delete' || event.key === 'Backspace') {
        const { selectedNodeId, selectedEdgeId } = useProcessDesignerStore.getState();
        if (selectedNodeId) {
          removeNode(selectedNodeId);
        } else if (selectedEdgeId) {
          removeEdge(selectedEdgeId);
        }
      }
    },
    [removeNode, removeEdge]
  );

  // 处理拖放
  const onDrop = useCallback(
    (event: React.DragEvent) => {
      event.preventDefault();
      
      if (!reactFlowWrapper.current || !reactFlowInstance) return;
      
      const reactFlowBounds = reactFlowWrapper.current.getBoundingClientRect();
      const position = reactFlowInstance.project({
        x: event.clientX - reactFlowBounds.left,
        y: event.clientY - reactFlowBounds.top,
      });
      
      onNodeDrop?.('USER_TASK', position);
    },
    [reactFlowInstance, onNodeDrop]
  );

  const onDragOver = useCallback((event: React.DragEvent) => {
    event.preventDefault();
    event.dataTransfer.dropEffect = 'move';
  }, []);

  return (
    <div
      ref={(node) => {
        setNodeRef(node);
        if (reactFlowWrapper) {
          (reactFlowWrapper as any).current = node;
        }
      }}
      className={`
        flex-1 h-full bg-gray-50
        ${isOver ? 'ring-2 ring-blue-500 ring-inset' : ''}
      `}
      onKeyDown={onKeyDown}
      tabIndex={0}
    >
      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        onConnect={onConnect}
        onNodeClick={onNodeClick}
        onEdgeClick={onEdgeClick}
        onPaneClick={onPaneClick}
        onInit={setReactFlowInstance}
        onDrop={onDrop}
        onDragOver={onDragOver}
        nodeTypes={nodeTypes}
        fitView
        snapToGrid
        snapGrid={[10, 10]}
        defaultViewport={{ x: 0, y: 0, zoom: 1 }}
        connectionLineStyle={{ stroke: '#94a3b8', strokeWidth: 2 }}
        connectionLineType={ConnectionLineType.SmoothStep}
      >
        <Background gap={20} size={1} color="#e5e7eb" />
        <Controls />
        <MiniMap
          nodeColor={(node) => {
            const config = PROCESS_NODE_TYPES.find(
              (c) => c.type === node.type
            );
            return config?.color || '#94a3b8';
          }}
          maskColor="rgb(240, 240, 240, 0.8)"
        />
      </ReactFlow>
    </div>
  );
}
