import { Node, Connection, ParamItem, ExecutionNode, ExecutionContext, NodeData } from '../types/node';
import { executeFlow, executeFlowSSEWithChat, FlowExecutionCallbacks, FlowExecutionEvent, FlowExecutionResult } from '/@/api/knowledge/aiFlow';
import { generateUUID } from '/@/utils/other';

// Define the mixin as a Vue component options object
export default {
	data(): NodeData {
		return {
			conversationId: '',
			isRunning: false,
			id: null,
			form: {},
			env: [],
			nodes: [],
			connections: [],
			isStream: true,
		};
	},
	async created(this: any) {
		// 从路由参数中获取id
		this.id = this.$route.params.id;
	},
	computed: {
		/**
		 * 计算工作流的执行顺序
		 * @returns {Node[]} 按执行顺序排列的节点数组
		 */
		workflowExecutionOrder(this: any): Node[] {
			// 初始化访问记录和执行顺序数组
			const visited = new Set<string>();
			const executionOrder: Node[] = [];

			// 解构获取节点和连接信息
			const { nodes, connections } = this;

			// 查找开始节点
			const startNode = nodes.find((node: Node) => node.type === 'start');
			if (!startNode) {
				// 使用this.$log替代console以避免linter错误
				this.$log?.warn?.('未找到开始节点');
				return [];
			}

			/**
			 * 深度优先搜索遍历节点
			 * @param {string} nodeId - 当前节点ID
			 * @param {string[]} path - 当前路径
			 * @param {number|null} branchIndex - 分支索引
			 */
			const dfs = (nodeId: string, path: string[] = [], branchIndex: number | null = null): void => {
				// 检查循环依赖
				if (visited.has(nodeId)) {
					if (path.includes(nodeId)) {
						const cycleNodes: string[] = path.slice(path.indexOf(nodeId));
						// 使用this.$log替代console以避免linter错误
						this.$log?.warn?.('检测到循环依赖，涉及节点:', cycleNodes);
						return;
					}
					return;
				}

				// 获取当前节点
				const currentNode = nodes.find((node: Node) => node.id === nodeId);
				if (!currentNode) {
					// 使用this.$log替代console以避免linter错误
					this.$log?.warn?.('未找到节点:', nodeId);
					return;
				}

				// 标记节点为已访问
				visited.add(nodeId);
				path.push(nodeId);

				// 设置分支信息
				if (branchIndex !== null) {
					currentNode._branchIndex = branchIndex;
				}

				// 添加到执行顺序
				executionOrder.push(currentNode);

				// 获取所有出边并按端口索引排序
				const outgoingConnections = connections
					.filter((conn: Connection) => conn.sourceId === nodeId)
					.sort((a: Connection, b: Connection) => (a.portIndex || 0) - (b.portIndex || 0));

				// 根据节点类型处理后续节点
				if (['switch', 'question'].includes(currentNode.type)) {
					// 分支节点：为每个分支的节点添加分支索引
					outgoingConnections.forEach((conn: Connection) => {
						dfs(conn.targetId, [...path], conn.portIndex || 0);
					});
				} else {
					// 普通节点：继承当前分支索引
					outgoingConnections.forEach((conn: Connection) => {
						dfs(conn.targetId, [...path], branchIndex);
					});
				}
			};

			// 从开始节点开始遍历
			dfs(startNode.id);

			return executionOrder;
		},
	},
	methods: {
		/**
		 * 深拷贝对象
		 * @param {T} obj - 要拷贝的对象
		 * @returns {T} 拷贝后的对象
		 */
		deepClone<T>(obj: T): T {
			return JSON.parse(JSON.stringify(obj));
		},

		/**
		 * 初始化全局环境变量
		 */
		initGlobalEnv(this: any): void {
			// 确保 window.$glob 存在
			if (!window.$glob) window.$glob = {};

			// 确保 this.env 是一个数组
			if (!this.env || !Array.isArray(this.env)) {
				this.env = [];
				return;
			}

			this.env.forEach((item: { name: string; value: any }) => {
				if (item.name) window.$glob[item.name] = item.value;
			});
		},

		/**
		 * 重置会话，在关闭面板时调用
		 */
		resetConversation(this: any): void {
			this.conversationId = '';
		},

		/**
		 * 处理工具栏运行按钮点击
		 */
		handleRunClick(this: any): void {
			// 如果没有会话ID，则创建一个
			if (!this.conversationId) {
				this.conversationId = generateUUID();
			}
			// 获取开始节点
			const startNode = this.nodes.find((node: Node) => node.type === 'start');
			if (startNode?.outputParams?.length) {
				this.startNodeParams = this.deepClone(startNode.inputParams);
				this.showExecutionPanel = true;
			} else {
				// 如果没有参数，直接运行
				this.runWorkflow();
			}
		},

		/**
		 * 使用SSE运行工作流（实时状态更新版本）
		 * @param {ParamItem[] | null} params - 开始节点参数
		 * @returns {Promise<ExecutionContext>} 执行上下文
		 */
		async runWorkflowSSE(this: any, params: ParamItem[] | null = null): Promise<ExecutionContext> {
			this.isRunning = true;
			this.initGlobalEnv();
			this.showExecutionPanel = true;
			const workflowExecutionOrder = this.deepClone(this.workflowExecutionOrder);
			this.executionNodes = [];

			const workflowStartTime = performance.now();

			try {
				const executionOrder = workflowExecutionOrder;
				const firstNode = executionOrder[0];
				firstNode.inputParams = [];
				const context: ExecutionContext = {
					variables: {},
					params: {},
					envs: {},
				};

				// 如果存在环境变量，也添加到开始节点的输入参数中
				if (this.env && Array.isArray(this.env) && this.env.length > 0) {
					this.env.forEach((item: { name: string; value: any }) => {
						if (!item.name) return;
						const envKey = `global.${item.name}`;
						context.envs[envKey] = item.value;
						firstNode.inputParams!.push({ type: envKey });
					});
				}

				// 如果有开始节点参数，设置到上下文中
				if (params) {
					params.forEach((param) => {
						const key = `${firstNode.id}.${param.key || param.type}`;
						context.params[key] = param.value;
						firstNode.inputParams!.push({ type: key });
					});
				}

				// 根据isStream属性决定使用SSE还是普通请求
				if (this.isStream) {
					// 使用SSE聊天执行工作流
					await this.executeWithSSE(context);
				} else {
					// 使用普通请求
					await this.executeWithHTTP(context);
				}

				return context;
			} catch (error: any) {
				this.$log?.error?.('运行工作流失败:', error);
				this.executionResult = { error: error.message };

				const workflowEndTime = performance.now();
				const totalDuration = workflowEndTime - workflowStartTime;

				this.$nextTick(() => {
					this.executionTime = totalDuration.toFixed(3);
					this.isRunning = false;
				});

				throw error;
			}
		},

		/**
		 * 使用SSE方式执行工作流
		 * @param {ExecutionContext} context - 执行上下文
		 */
		async executeWithSSE(this: any, context: ExecutionContext): Promise<void> {
			// 初始化聊天消息累积器
			let chatMessageContent = '';
			let isChatStreaming = false;

			// 设置SSE回调函数
			const callbacks: FlowExecutionCallbacks = {
				onStart: () => {
					this.$log?.info?.('工作流开始执行');
					// 重置聊天消息
					chatMessageContent = '';
					isChatStreaming = false;
				},
				onProgress: (event: FlowExecutionEvent) => {
					this.$log?.info?.(`节点执行进度: ${event.nodeName} (${event.nodeId})`);
					
					// 更新执行节点状态
					if (event.nodeId && this.executionNodes) {
						const nodeIndex = this.executionNodes.findIndex((n: ExecutionNode) => n.id === event.nodeId);
						if (nodeIndex >= 0) {
							this.$nextTick(() => {
								this.executionNodes[nodeIndex] = {
									...this.executionNodes[nodeIndex],
									status: 'running',
									...event.data
								};
							});
						}
					}
					
					// 可以在这里添加进度条或其他UI更新
					if (event.progress !== undefined) {
						this.$log?.info?.(`执行进度: ${event.progress}%`);
					}
				},
				onChatMessage: (content: string, isComplete: boolean, tokens?: number, duration?: number, nodes?: Array<any>) => {
					// 累积聊天消息内容
					chatMessageContent += content;
					isChatStreaming = true;
					
					// 处理 tokens、duration 和 nodes 信息
					if (isComplete) {
						if (tokens) {
							this.totalTokens = tokens;
						}
						if (duration) {
							this.executionTime = duration;
						}
						if (nodes) {
							this.executionNodes = nodes;
						}
					}
					
					// 实时更新executionResult以显示聊天消息
					this.$nextTick(() => {
						this.executionResult = {
							...this.executionResult,
							chatMessage: chatMessageContent,
							isStreaming: !isComplete
						};
					});
				},
				onComplete: (result: FlowExecutionResult) => {
					this.$log?.info?.('工作流执行完成');
					
					this.$nextTick(() => {
						this.executionNodes = result.nodes;
						// 如果有聊天消息，将其合并到结果中
						if (isChatStreaming && chatMessageContent) {
							this.executionResult = {
								...result.result,
								chatMessage: chatMessageContent,
								isStreaming: false
							};
						} else {
							this.executionResult = result.result;
						}
						this.executionTime = Number(result.duration);
						this.totalTokens = Number(result.totalTokens || 0);
						this.isRunning = false;
					});
				},
				onError: (error: string) => {
					this.$log?.error?.('工作流执行失败:', error);
					
					this.$nextTick(() => {
						// 如果有部分聊天消息，也保留在错误结果中
						const errorResult: any = { error };
						if (isChatStreaming && chatMessageContent) {
							errorResult.chatMessage = chatMessageContent;
							errorResult.isStreaming = false;
						}
						this.executionResult = errorResult;
						this.isRunning = false;
					});
				},
			};

			const chatResult = await executeFlowSSEWithChat(
				{ id: this.id, conversationId: this.conversationId, params: context.params, envs: context.envs, stream: true },
				callbacks
			);

			// 将聊天结果写入executionResult
			this.$nextTick(() => {
				this.executionResult = {
					chatMessage: chatResult.chatMessage,
					result: chatResult.result,
					isStreaming: false
				};
				this.isRunning = false;
			});
		},

		/**
		 * 使用普通HTTP请求执行工作流
		 * @param {ExecutionContext} context - 执行上下文
		 */
		async executeWithHTTP(this: any, context: ExecutionContext): Promise<void> {
			const { data } = await executeFlow({ 
				id: this.id, 
				params: context.params, 
				envs: context.envs, 
				stream: false 
			});

			// 处理普通JSON响应
			this.$nextTick(() => {
				// 检查响应数据结构，支持不同的返回格式
				if (data.nodes && data.result !== undefined) {
					// 标准格式: { nodes, result, duration, totalTokens }
					this.executionNodes = data.nodes;
					this.executionResult = data.result;
					this.executionTime = Number(data.duration || 0);
					this.totalTokens = Number(data.totalTokens || 0);
				} else if (data.data) {
					// 嵌套格式: { data: { nodes, result, duration, totalTokens } }
					const responseData = data.data;
					this.executionNodes = responseData.nodes || [];
					this.executionResult = responseData.result || responseData;
					this.executionTime = Number(responseData.duration || 0);
					this.totalTokens = Number(responseData.totalTokens || 0);
				} else {
					// 直接返回格式：直接使用 data 作为结果
					this.executionNodes = data.nodes || [];
					this.executionResult = data;
					this.executionTime = Number(data.duration || 0);
					this.totalTokens = Number(data.totalTokens || 0);
				}

				// 如果结果包含聊天消息内容，也进行处理
				if (this.executionResult && typeof this.executionResult === 'object') {
					// 检查是否有聊天消息相关字段
					if (this.executionResult.chatMessage || this.executionResult.content) {
						const chatMessage = this.executionResult.chatMessage || this.executionResult.content;
						this.executionResult = {
							...this.executionResult,
							chatMessage: chatMessage,
							isStreaming: false
						};
					}
				}

				this.isRunning = false;
			});
		},

		/**
		 * 运行工作流
		 * @param {ParamItem[] | null} params - 开始节点参数
		 * @returns {Promise<ExecutionContext>} 执行上下文
		 */
		async runWorkflow(this: any, params: ParamItem[] | null = null): Promise<ExecutionContext> {
			// 默认使用SSE版本
			return this.runWorkflowSSE(params);
		},

		/**
		 * 判断节点是否应该被跳过
		 * @param {Node} node - 当前节点
		 * @param {Map<string, number>} activeBranches - 活动分支信息
		 * @returns {boolean} 是否应该跳过
		 */
		shouldSkipNode(this: any, node: Node, activeBranches: Map<string, number>): boolean {
			// 如果节点没有分支信息，不跳过
			if (node._branchIndex === undefined) {
				return false;
			}

			// 查找当前节点所属的分支节点
			const branchNodeId = this.findBranchNodeId(node);
			if (!branchNodeId) {
				return false;
			}

			// 获取活动分支索引
			const activeBranch = activeBranches.get(branchNodeId);

			// 如果找不到活动分支信息，或者分支索引匹配，则不跳过
			if (activeBranch === undefined || activeBranch === node._branchIndex) {
				return false;
			}

			return true;
		},

		/**
		 * 查找节点所属的分支节点ID
		 * @param {Node} node - 当前节点
		 * @returns {string|null} 分支节点ID
		 */
		findBranchNodeId(this: any, node: Node): string | null {
			// 遍历所有连接找到源节点
			const connection = this.connections.find((conn: Connection) => conn.targetId === node.id);
			if (!connection) {
				return null;
			}

			const sourceNode = this.nodes.find((n: Node) => n.id === connection.sourceId);
			if (!sourceNode) {
				return null;
			}

			// 如果源节点是分支节点，返回其ID
			if (['switch', 'question'].includes(sourceNode.type)) {
				return sourceNode.id;
			}

			// 递归查找
			return this.findBranchNodeId(sourceNode);
		},

		/**
		 * 解析节点的输入参数
		 * @param {Node} node - 当前节点
		 * @param {ExecutionContext} context - 执行上下文
		 * @returns {Record<string, any>} 解析后的输入参数
		 */
		resolveNodeInputParams(this: any, node: Node, context: ExecutionContext): Record<string, any> {
			const inputParams: Record<string, any> = {
				id: node.id,
			};
			let list = this.deepClone(node.inputParams || []);
			if (node.type === 'http') {
				if (node.bodyParams) list = list.concat(node.bodyParams);
				if (node.headerParams) list = list.concat(node.headerParams);
			}
			list?.forEach((ele: ParamItem) => {
				const { value, name, type } = ele;
				const key = `${node.id}.${name}`;
				if (type && type.includes('global')) {
					inputParams[type] = window.$glob[type.replace('global.', '')];
					context.params[type] = inputParams[type];
				} else if (type) {
					inputParams[type] = context.params[type];
				} else if (value) {
					inputParams[key] = value;
					context.params[key] = value;
				}
			});
			return inputParams;
		},
	},
};
