import React, { useEffect, useState, useMemo } from 'react';
import { ReactFlowProvider, ReactFlow, Background, Node, Edge, Handle, Position, BackgroundVariant } from '@xyflow/react';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Separator } from '@/components/ui/separator';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { 
  Loader2, 
  AlertCircle, 
  User, 
  Building2, 
  Layers, 
  Calendar,
  Clock,
  CheckCircle2,
  XCircle,
  AlertTriangle
} from 'lucide-react';
import { cn } from '@/lib/utils';
import '@xyflow/react/dist/style.css';
import { getDeployRecordFlowGraph } from '../service';
import type { DeployRecordFlowGraph, WorkflowNodeInstance } from '../types';
import { 
  getStatusIcon, 
  getStatusText, 
  getNodeStatusText,
  getNodeStatusColor,
  formatTime, 
  formatDuration,
  calculateRunningDuration 
} from '../utils/dashboardUtils';

interface DeployFlowGraphModalProps {
  open: boolean;
  deployRecordId: number | null;
  onOpenChange: (open: boolean) => void;
}

/**
 * 自定义流程节点组件
 */
const CustomFlowNode: React.FC<any> = ({ data }) => {
  const { nodeName, nodeType, status, startTime, endTime, duration, errorMessage, isUnreachable } = data;
  const statusColor = getNodeStatusColor(status);
  const isNotStarted = status === 'NOT_STARTED';
  const isRunning = status === 'RUNNING';
  const hasFailed = status === 'FAILED';
  
  // 计算显示的时长
  const displayDuration = useMemo(() => {
    if (duration !== null && duration !== undefined) {
      // 后端返回的 duration 单位已经是毫秒
      return formatDuration(duration);
    }
    if (isRunning && startTime) {
      const runningDuration = calculateRunningDuration(startTime);
      return formatDuration(runningDuration);
    }
    return null;
  }, [duration, isRunning, startTime]);

  const nodeContent = (
    <div
      className={cn(
        'px-4 py-3 rounded-md min-w-[160px] transition-all',
        isNotStarted && 'border-2 border-dashed',
        !isNotStarted && 'border-2 border-solid shadow-sm',
        isRunning && 'animate-pulse',
        isUnreachable && 'opacity-40' // 不可达节点半透明
      )}
      style={{
        borderColor: statusColor,
        backgroundColor: isNotStarted ? '#f9fafb' : '#ffffff',
      }}
    >
      {/* 节点名称 */}
      <div className="font-medium text-sm mb-1">{nodeName}</div>
      
      {/* 节点状态 */}
      <div 
        className="text-xs font-medium mb-1" 
        style={{ color: statusColor }}
      >
        {getNodeStatusText(status)}
      </div>
      
      {/* 时间信息 */}
      {!isNotStarted && (
        <div className="text-xs text-muted-foreground space-y-0.5">
          {startTime && <div>开始: {formatTime(startTime)}</div>}
          {endTime && <div>结束: {formatTime(endTime)}</div>}
          {displayDuration && (
            <div className="font-medium">
              {isRunning ? '运行中: ' : '时长: '}
              {displayDuration}
            </div>
          )}
        </div>
      )}
      
      {/* 错误提示 */}
      {hasFailed && errorMessage && (
        <div className="mt-2 flex items-center gap-1 text-red-600">
          <AlertCircle className="h-3 w-3" />
          <span className="text-xs">有错误</span>
        </div>
      )}
    </div>
  );

  return (
    <>
      {/* 输入连接点 */}
      {nodeType !== 'START_EVENT' && (
        <Handle type="target" position={Position.Left} />
      )}

      {/* 节点内容 - 如果有错误信息，包装在 Tooltip 中 */}
      {hasFailed && errorMessage ? (
        <TooltipProvider>
          <Tooltip>
            <TooltipTrigger asChild>
              {nodeContent}
            </TooltipTrigger>
            <TooltipContent side="top" className="max-w-sm">
              <p className="font-medium mb-1">错误信息:</p>
              <p className="text-xs">{errorMessage}</p>
            </TooltipContent>
          </Tooltip>
        </TooltipProvider>
      ) : (
        nodeContent
      )}

      {/* 输出连接点 */}
      {nodeType !== 'END_EVENT' && (
        <Handle type="source" position={Position.Right} />
      )}
    </>
  );
};

const nodeTypes = {
  custom: CustomFlowNode,
};

/**
 * 业务信息卡片
 */
const BusinessInfoCard: React.FC<{ flowData: DeployRecordFlowGraph }> = ({ flowData }) => {
  return (
    <Card>
      <CardHeader className="pb-3">
        <CardTitle className="text-sm font-medium flex items-center gap-2">
          <Building2 className="h-4 w-4" />
          业务信息
        </CardTitle>
      </CardHeader>
      <CardContent className="space-y-2 text-sm">
        <div className="flex justify-between">
          <span className="text-muted-foreground">应用名称:</span>
          <span className="font-medium">{flowData.applicationName}</span>
        </div>
        <div className="flex justify-between">
          <span className="text-muted-foreground">应用编码:</span>
          <span className="font-mono text-xs">{flowData.applicationCode}</span>
        </div>
        <Separator />
        <div className="flex justify-between">
          <span className="text-muted-foreground">部署环境:</span>
          <span className="font-medium">{flowData.environmentName}</span>
        </div>
        <div className="flex justify-between">
          <span className="text-muted-foreground">所属团队:</span>
          <span className="font-medium">{flowData.teamName}</span>
        </div>
        <Separator />
        <div className="flex justify-between">
          <span className="text-muted-foreground flex items-center gap-1">
            <User className="h-3 w-3" />
            部署人:
          </span>
          <span className="font-medium">{flowData.deployBy}</span>
        </div>
        {flowData.deployRemark && (
          <>
            <Separator />
            <div>
              <span className="text-muted-foreground">备注:</span>
              <p className="text-xs mt-1 text-muted-foreground">{flowData.deployRemark}</p>
            </div>
          </>
        )}
      </CardContent>
    </Card>
  );
};

/**
 * 进度信息卡片
 */
const ProgressCard: React.FC<{ flowData: DeployRecordFlowGraph }> = ({ flowData }) => {
  const { executedNodeCount, totalNodeCount, successNodeCount, failedNodeCount, runningNodeCount } = flowData;
  const progress = totalNodeCount > 0 ? (executedNodeCount / totalNodeCount) * 100 : 0;

  return (
    <Card>
      <CardHeader className="pb-3">
        <CardTitle className="text-sm font-medium flex items-center gap-2">
          <Layers className="h-4 w-4" />
          执行进度
        </CardTitle>
      </CardHeader>
      <CardContent className="space-y-3">
        <div>
          <div className="flex justify-between text-sm mb-2">
            <span className="text-muted-foreground">已执行</span>
            <span className="font-medium">
              {executedNodeCount} / {totalNodeCount} 节点
            </span>
          </div>
          <Progress value={progress} className="h-2" />
          <div className="text-xs text-muted-foreground mt-1 text-right">
            {Math.round(progress)}%
          </div>
        </div>
        
        <Separator />
        
        <div className="grid grid-cols-3 gap-2 text-xs">
          <div className="flex flex-col items-center p-2 rounded-md bg-green-50">
            <CheckCircle2 className="h-4 w-4 text-green-600 mb-1" />
            <span className="text-muted-foreground">成功</span>
            <span className="font-medium text-green-600">{successNodeCount}</span>
          </div>
          <div className="flex flex-col items-center p-2 rounded-md bg-red-50">
            <XCircle className="h-4 w-4 text-red-600 mb-1" />
            <span className="text-muted-foreground">失败</span>
            <span className="font-medium text-red-600">{failedNodeCount}</span>
          </div>
          <div className="flex flex-col items-center p-2 rounded-md bg-blue-50">
            <Loader2 className="h-4 w-4 text-blue-600 mb-1" />
            <span className="text-muted-foreground">运行中</span>
            <span className="font-medium text-blue-600">{runningNodeCount}</span>
          </div>
        </div>
      </CardContent>
    </Card>
  );
};

/**
 * 时长统计卡片
 */
const DurationCard: React.FC<{ flowData: DeployRecordFlowGraph }> = ({ flowData }) => {
  const { deployStartTime, deployDuration, nodeInstances, runningNodeCount } = flowData;
  const isRunning = runningNodeCount > 0;
  
  // 计算当前总时长
  const currentDuration = useMemo(() => {
    if (deployDuration) return deployDuration; // 后端返回的已经是毫秒
    if (isRunning) return calculateRunningDuration(deployStartTime);
    return 0;
  }, [deployDuration, isRunning, deployStartTime]);

  return (
    <Card>
      <CardHeader className="pb-3">
        <CardTitle className="text-sm font-medium flex items-center gap-2">
          <Clock className="h-4 w-4" />
          时长统计
        </CardTitle>
      </CardHeader>
      <CardContent className="space-y-3">
        <div className="space-y-2 text-sm">
          <div className="flex justify-between">
            <span className="text-muted-foreground flex items-center gap-1">
              <Calendar className="h-3 w-3" />
              开始时间:
            </span>
            <span className="font-medium">
              {deployStartTime ? formatTime(deployStartTime) : '-'}
            </span>
          </div>
          <div className="flex justify-between">
            <span className="text-muted-foreground">总时长:</span>
            <span className="font-medium">
              {formatDuration(currentDuration)}
              {isRunning && <span className="text-blue-600 ml-1">(运行中...)</span>}
            </span>
          </div>
        </div>

        <Separator />

        <div>
          <div className="text-xs text-muted-foreground mb-2">节点执行时长:</div>
          <div className="space-y-1.5 text-xs max-h-32 overflow-y-auto">
            {nodeInstances
              .filter(ni => ni.status !== 'NOT_STARTED')
              .map((ni) => {
                // 后端返回的 duration 单位已经是毫秒
                const nodeDuration = ni.duration 
                  ? ni.duration 
                  : (ni.status === 'RUNNING' ? calculateRunningDuration(ni.startTime) : 0);
                return (
                  <div key={ni.nodeId} className="flex justify-between items-center">
                    <span className="truncate flex-1" title={ni.nodeName}>
                      {ni.nodeName}
                    </span>
                    <span className="font-mono ml-2" style={{ color: getNodeStatusColor(ni.status) }}>
                      {formatDuration(nodeDuration)}
                      {ni.status === 'RUNNING' && '...'}
                    </span>
                  </div>
                );
              })}
          </div>
        </div>
      </CardContent>
    </Card>
  );
};

/**
 * 实时监控提示
 */
const MonitoringAlert: React.FC<{ flowData: DeployRecordFlowGraph }> = ({ flowData }) => {
  const { runningNodeCount } = flowData;

  if (runningNodeCount === 0) return null;

  return (
    <Alert className="border-blue-200 bg-blue-50">
      <Loader2 className="h-4 w-4 animate-spin text-blue-600" />
      <AlertDescription className="text-sm text-blue-900">
        <span className="font-medium">部署正在进行中</span>
        <span className="block text-xs mt-1">
          当前有 {runningNodeCount} 个节点正在执行，请稍候...
        </span>
      </AlertDescription>
    </Alert>
  );
};

/**
 * 信息面板（左侧边栏）
 */
const DeployInfoPanel: React.FC<{ flowData: DeployRecordFlowGraph }> = ({ flowData }) => {
  return (
    <div className="w-80 flex-shrink-0 border-r bg-muted/30 p-4 space-y-4 overflow-y-auto">
      <MonitoringAlert flowData={flowData} />
      <BusinessInfoCard flowData={flowData} />
      <ProgressCard flowData={flowData} />
      <DurationCard flowData={flowData} />
    </div>
  );
};

/**
 * 部署流程图模态框（主组件）
 */
export const DeployFlowGraphModal: React.FC<DeployFlowGraphModalProps> = ({
  open,
  deployRecordId,
  onOpenChange,
}) => {
  const [loading, setLoading] = useState(false);
  const [flowData, setFlowData] = useState<DeployRecordFlowGraph | null>(null);

  // 加载流程图数据
  useEffect(() => {
    if (open && deployRecordId) {
      setLoading(true);
      getDeployRecordFlowGraph(deployRecordId)
        .then((data) => {
          setFlowData(data);
        })
        .catch((error) => {
          console.error('加载部署流程图失败:', error);
        })
        .finally(() => {
          setLoading(false);
        });
    } else {
      setFlowData(null);
    }
  }, [open, deployRecordId]);

  // 创建节点ID到实例的映射
  const nodeInstanceMap = useMemo(() => {
    if (!flowData?.nodeInstances) return new Map<string, WorkflowNodeInstance>();
    const map = new Map<string, WorkflowNodeInstance>();
    flowData.nodeInstances.forEach((instance) => {
      map.set(instance.nodeId, instance);
    });
    return map;
  }, [flowData]);

  // 计算可达节点（从已执行节点出发能到达的节点）
  const reachableNodes = useMemo(() => {
    if (!flowData?.graph?.edges || !flowData?.nodeInstances) return new Set<string>();

    const executedNodeIds = flowData.nodeInstances
      .filter(ni => ni.status !== 'NOT_STARTED')
      .map(ni => ni.nodeId);

    if (executedNodeIds.length === 0) return new Set<string>();

    const reachable = new Set<string>(executedNodeIds);
    const queue = [...executedNodeIds];

    // BFS 遍历所有可达节点
    while (queue.length > 0) {
      const currentId = queue.shift()!;
      const outgoingEdges = flowData.graph.edges.filter(e => e.from === currentId);
      
      for (const edge of outgoingEdges) {
        if (!reachable.has(edge.to)) {
          reachable.add(edge.to);
          queue.push(edge.to);
        }
      }
    }

    return reachable;
  }, [flowData]);

  // 转换为 React Flow 节点（显示所有节点，但对不可达节点置灰）
  const flowNodes: Node[] = useMemo(() => {
    if (!flowData?.graph?.nodes || !flowData?.nodeInstances) return [];

    const isRunning = flowData.runningNodeCount > 0;

    // 按执行顺序排序已执行的节点
    const executedInstances = flowData.nodeInstances
      .filter(ni => ni.status !== 'NOT_STARTED')
      .sort((a, b) => {
        const timeA = a.startTime ? new Date(a.startTime.replace(' ', 'T')).getTime() : 0;
        const timeB = b.startTime ? new Date(b.startTime.replace(' ', 'T')).getTime() : 0;
        return timeA - timeB;
      });

    // 线性布局：从左到右排列
    const nodePositionMap = new Map<string, { x: number; y: number }>();
    const horizontalSpacing = 300; // 水平间距
    const verticalSpacing = 150; // 垂直间距（用于分支）
    const startX = 100; // 起始X坐标
    const startY = 150; // 起始Y坐标

    // 已执行的节点：从左到右线性排列
    executedInstances.forEach((instance, index) => {
      nodePositionMap.set(instance.nodeId, {
        x: startX + index * horizontalSpacing,
        y: startY,
      });
    });

    // 未执行的节点：根据在图中的位置和层级布局
    const notStartedNodes = flowData.graph.nodes.filter(
      node => !nodePositionMap.has(node.id)
    );

    // 简单布局：按节点在edges中的出现顺序，从左到右、上到下排列
    let currentX = startX + executedInstances.length * horizontalSpacing;
    let currentRow = 0;
    const nodesPerRow = 3;

    notStartedNodes.forEach((node, index) => {
      const row = Math.floor(index / nodesPerRow);
      const col = index % nodesPerRow;
      nodePositionMap.set(node.id, {
        x: currentX + col * horizontalSpacing,
        y: startY + row * verticalSpacing,
      });
    });

    // 生成所有节点
    return flowData.graph.nodes.map((node) => {
      const instance = nodeInstanceMap.get(node.id);
      const position = nodePositionMap.get(node.id) || { x: 0, y: 0 };
      const isReachable = reachableNodes.has(node.id);
      const isNotStarted = !instance || instance.status === 'NOT_STARTED';

      return {
        id: node.id,
        type: 'custom',
        position,
        data: {
          nodeName: node.nodeName,
          nodeType: node.nodeType,
          status: instance?.status || 'NOT_STARTED',
          startTime: instance?.startTime,
          endTime: instance?.endTime,
          duration: instance?.duration,
          errorMessage: instance?.errorMessage,
          // 新增：不可达且未执行的节点标记为置灰
          isUnreachable: isRunning && isNotStarted && !isReachable,
        },
      };
    });
  }, [flowData, nodeInstanceMap, reachableNodes]);

  // 转换为 React Flow 边
  const flowEdges: Edge[] = useMemo(() => {
    if (!flowData?.graph?.edges) return [];

    const isRunning = flowData.runningNodeCount > 0;
    const displayedNodeIds = new Set(flowNodes.map(n => n.id));

    return flowData.graph.edges
      .filter(edge => {
        // 只显示连接已显示节点的边
        return displayedNodeIds.has(edge.from) && displayedNodeIds.has(edge.to);
      })
      .map((edge, index) => {
        const source = edge.from;
        const target = edge.to;
        const sourceInstance = nodeInstanceMap.get(source);
        const targetInstance = nodeInstanceMap.get(target);
        const sourceStatus = sourceInstance?.status || 'NOT_STARTED';
        const targetStatus = targetInstance?.status || 'NOT_STARTED';
        
        // 判断这条边是否在可达路径上
        const isReachableEdge = reachableNodes.has(source) && reachableNodes.has(target);
        
        // 根据节点状态确定边的样式
        let strokeColor = '#d1d5db'; // 默认灰色
        let strokeWidth = 2;
        let animated = false;
        let opacity = 1;

        // 源节点已完成 + 目标节点也已完成/运行中 = 绿色实线
        if (sourceStatus === 'COMPLETED' && (targetStatus === 'COMPLETED' || targetStatus === 'RUNNING')) {
          strokeColor = '#10b981'; // 绿色
        } 
        // 源节点失败 = 红色
        else if (sourceStatus === 'FAILED') {
          strokeColor = '#ef4444'; // 红色
        } 
        // 源节点运行中 = 蓝色动画
        else if (sourceStatus === 'RUNNING') {
          strokeColor = '#3b82f6'; // 蓝色
          animated = true;
        }
        // 源节点完成 + 目标节点未开始
        else if (sourceStatus === 'COMPLETED' && targetStatus === 'NOT_STARTED') {
          if (isReachableEdge && isRunning) {
            strokeColor = '#9ca3af'; // 浅灰色（即将执行）
          } else {
            strokeColor = '#d1d5db'; // 默认灰色
            opacity = 0.3; // 不可达路径半透明
          }
        }
        // 两端都未执行
        else if (sourceStatus === 'NOT_STARTED' && targetStatus === 'NOT_STARTED') {
          opacity = isRunning && !isReachableEdge ? 0.3 : 0.5;
        }

        return {
          id: edge.id || `edge-${source}-${target}-${index}`,
          source,
          target,
          type: 'smoothstep',
          animated,
          style: {
            stroke: strokeColor,
            strokeWidth,
            opacity,
            strokeDasharray: (sourceStatus === 'COMPLETED' && targetStatus === 'NOT_STARTED' && isReachableEdge) ? '5,5' : undefined,
          },
          markerEnd: {
            type: 'arrowclosed',
            color: strokeColor,
            width: 20,
            height: 20,
          },
        };
      });
  }, [flowData, nodeInstanceMap, flowNodes, reachableNodes]);

  // 获取部署状态信息
  const deployStatusInfo = flowData
    ? (() => {
        const { icon: StatusIcon, color } = getStatusIcon(flowData.deployStatus);
        return {
          icon: StatusIcon,
          color,
          text: getStatusText(flowData.deployStatus),
        };
      })()
    : null;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="!max-w-7xl w-[90vw] h-[85vh] flex flex-col p-0 overflow-hidden">
        <DialogHeader className="px-6 pt-6 pb-4 border-b flex-shrink-0">
          <DialogTitle className="flex items-center gap-2">
            {flowData && (
              <span className="text-muted-foreground">
                #{flowData.deployRecordId}
              </span>
            )}
            <span>部署流程图</span>
            {deployStatusInfo && (
              <Badge
                variant="outline"
                className={cn('flex items-center gap-1', deployStatusInfo.color)}
              >
                <deployStatusInfo.icon
                  className={cn(
                    'h-3 w-3',
                    flowData?.deployStatus === 'RUNNING' && 'animate-spin'
                  )}
                />
                {deployStatusInfo.text}
              </Badge>
            )}
          </DialogTitle>
        </DialogHeader>

        <div className="flex flex-1 overflow-hidden min-h-0">
          {loading ? (
            <div className="flex items-center justify-center h-full w-full">
              <div className="text-center space-y-4">
                <Loader2 className="h-8 w-8 animate-spin mx-auto text-primary" />
                <p className="text-sm text-muted-foreground">加载流程图数据...</p>
              </div>
            </div>
          ) : flowData ? (
            <>
              {/* 左侧信息面板 */}
              <DeployInfoPanel flowData={flowData} />

              {/* 右侧流程图可视化 */}
              <div className="flex-1 relative">
                <ReactFlowProvider>
                  <ReactFlow
                    nodes={flowNodes}
                    edges={flowEdges}
                    nodeTypes={nodeTypes}
                    fitView
                    className="bg-muted/10"
                    fitViewOptions={{ padding: 0.2, maxZoom: 1, minZoom: 0.5 }}
                    panOnScroll={true}
                    zoomOnScroll={true}
                    zoomOnPinch={true}
                    preventScrolling={false}
                  >
                    <Background 
                      variant={BackgroundVariant.Dots} 
                      gap={16} 
                      size={1}
                      className="opacity-30"
                    />
                  </ReactFlow>
                </ReactFlowProvider>
              </div>
            </>
          ) : (
            <div className="flex items-center justify-center h-full w-full">
              <div className="text-center">
                <AlertTriangle className="h-12 w-12 text-muted-foreground mx-auto mb-2" />
                <p className="text-sm text-muted-foreground">暂无流程图数据</p>
              </div>
            </div>
          )}
        </div>
      </DialogContent>
    </Dialog>
  );
};
