<template>
	<div class="workflow-canvas-page">
		<!-- 工具栏 -->
		<div class="toolbar">
			<div class="toolbar-left">
				<h2>工作流画布编辑器</h2>
				<span class="info">节点: {{ nodes.length }} / 连线: {{ edges.length }}</span>
			</div>
			<div class="toolbar-right">
				<el-button size="small" @click="createNewWorkflow">新建工作流</el-button>
				<el-button size="small" type="danger" :disabled="!selectedNode" @click="deleteSelectedNode">删除选中</el-button>
				<el-button size="small" type="primary" @click="saveWorkflowAction" :loading="saving">保存工作流</el-button>
			</div>
		</div>

		<!-- 主内容区：三栏布局 -->
		<div class="content">
			<!-- 左侧：配置面板 -->
			<NodeConfigPanel
				:selected-node="selectedNode"
				:available-params="availableParams"
				:node-config="currentNodeConfig"
				:all-nodes="nodes"
				:all-edges="edges"
				@update:selected-node="updateSelectedNode"
				@add-param="addParam"
				@open-model-selector="showModelSelector = true"
				@remove-model="handleRemoveModel"
				@open-skill-selector="showSkillSelector = true"
				@remove-skill="handleRemoveSkill"
				@remove-field="handleRemoveField"
				@toggle-output="handleToggleOutput"
				@add-param-by-value="handleAddParamByValue"
			/>

			<!-- 中间：VueFlow 画布（节点库在画布内） -->
			<div class="flow-wrapper">
				<NodeLibraryPanel
					:node-library-groups="filteredNodeLibraryGroups"
					:collapsed="nodeLibraryCollapsed"
					@update:collapsed="nodeLibraryCollapsed = $event"
					@add-node="addNodeFromLibrary"
				/>

				<!-- VueFlow 画布 -->
				<VueFlow
					v-model:nodes="nodes"
					v-model:edges="edges"
					:default-viewport="{ zoom: 1 }"
					:nodes-connectable="true"
					:edges-updatable="true"
					@connect="onConnect"
					@node-click="onNodeClick"
				>
					<Background pattern-color="#cbd5e1" :gap="16" />
					<Controls />
					<MiniMap />
				</VueFlow>
			</div>

			<!-- 右侧：工作流列表 -->
			<WorkflowListPanel
				:user-workflow-list="userWorkflowList"
				:template-workflow-list="templateWorkflowList"
				:current-editing-id="currentEditingWorkflowId"
				:loading="workflowListLoading"
				@edit="editWorkflow"
				@delete="deleteWorkflowAction"
				@create="createNewWorkflow"
			/>
		</div>

		<!-- 保存工作流对话框 -->
		<SaveWorkflowDialog
			v-model="saveDialogVisible"
			:save-form="saveForm"
			:current-editing-workflow-id="currentEditingWorkflowId"
			:saving="saving"
			@confirm="confirmSaveWorkflow"
		/>

		<!-- 模型选择器 -->
		<ModelSelector v-model="showModelSelector" :default-model="selectedModelData" :model-type="currentNodeModelType" @confirm="handleModelConfirm" />

		<!-- 技能选择器 -->
		<SkillSelector v-model="showSkillSelector" :default-skill="selectedSkillData" @confirm="handleSkillConfirm" />
	</div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import { VueFlow, useVueFlow } from '@vue-flow/core';
import { Background } from '@vue-flow/background';
import { Controls } from '@vue-flow/controls';
import { MiniMap } from '@vue-flow/minimap';
import { ElMessage, ElMessageBox } from 'element-plus';
import type { Node, Edge, Connection } from '@vue-flow/core';
import {
	getNodeLibraryList,
	getWorkflowList,
	getWorkflowDetail,
	saveWorkflow,
	updateWorkflow,
	deleteWorkflow,
	type NodeLibraryGroup,
	type WorkflowItem,
} from '/@/api/settings/creation';
import NodeConfigPanel from './component/NodeConfigPanel.vue';
import NodeLibraryPanel from './component/NodeLibraryPanel.vue';
import WorkflowListPanel from './component/WorkflowListPanel.vue';
import SaveWorkflowDialog from './component/SaveWorkflowDialog.vue';
import ModelSelector from '/@/components/model/ModelSelector.vue';
import SkillSelector from '/@/components/skill/SkillSelector.vue';

interface NodeData {
	label?: string;
	nodeCode?: string;
	inputSource?: Array<{ nodeId: string; field: string[]; quoteOutput?: boolean }> | null;
	formConfig?: any[];
	modelConfig?: any;
	skillName?: string;
}

interface ParamRef {
	id: string;
	label: string;
}

const { addNodes, addEdges, findNode, removeNodes, getNodes, updateNode } = useVueFlow();

// 常量定义
const START_NODE_CODE = '__start__';
const JUDGE_KEYWORDS = ['判断', 'judge', 'condition', 'if', 'branch', 'gateway'];

// 节点库相关状态
const nodeLibraryGroups = ref<NodeLibraryGroup[]>([]);
const nodeLibraryCollapsed = ref(false);

const filteredNodeLibraryGroups = computed(() => {
	return nodeLibraryGroups.value;
});

// 节点配置映射：nodeCode -> 节点配置
const nodeConfigMap = computed(() => {
	const map = new Map<string, { formConfig: any[]; modelConfig: any[]; skillOption: boolean }>();
	nodeLibraryGroups.value.forEach((group) => {
		group.items.forEach((item) => {
			map.set(item.nodeCode, {
				formConfig: item.formConfig || [],
				modelConfig: item.modelConfig || [],
				skillOption: item.skillOption || false,
			});
		});
	});
	return map;
});

// 当前选中节点的配置
const currentNodeConfig = computed(() => {
	if (!selectedNode.value?.data?.nodeCode) return null;
	return nodeConfigMap.value.get(selectedNode.value.data.nodeCode) || null;
});

// 工作流列表相关状态
const workflowListLoading = ref(false);
const userWorkflowList = ref<WorkflowItem[]>([]);
const templateWorkflowList = ref<WorkflowItem[]>([]);
const currentEditingWorkflowId = ref<string | null>(null);

// 保存对话框相关状态
const saveDialogVisible = ref(false);
const saving = ref(false);
const saveForm = ref({
	flowName: '',
	description: '',
});

const nodes = ref<Node<NodeData, any, string>[]>([]);
const edges = ref<Edge[]>([]);
const selectedNode = ref<Node<NodeData, any, string> | null>(null);
let nodeId = 0;

// 模型选择器相关状态
const showModelSelector = ref(false);
const selectedModelData = ref<any>(null);
const currentNodeModelType = computed(() => {
	if (!selectedNode.value || !currentNodeConfig.value) return 0;
	const modelConfig = currentNodeConfig.value.modelConfig;
	if (modelConfig && modelConfig.length > 0) {
		return modelConfig[0].modelType || 0;
	}
	return 0;
});

// 技能选择器相关状态
const showSkillSelector = ref(false);
const selectedSkillData = ref<any>(null);

const deleteSelectedNode = async () => {
	if (!selectedNode.value?.data) return;

	if (selectedNode.value.data.nodeCode === '__start__') {
		ElMessage.warning('开始节点不能删除');
		return;
	}

	try {
		await ElMessageBox.confirm('确定要删除选中的节点吗？', '删除确认', {
			confirmButtonText: '确定',
			cancelButtonText: '取消',
			type: 'warning',
		});

		removeNodes([selectedNode.value.id]);
		selectedNode.value = null;
		ElMessage.success('节点已删除');
	} catch {
		// 用户取消删除
	}
};

const onConnect = (connection: Connection) => {
	const source = findNode(connection.source);
	const target = findNode(connection.target);

	if (!source?.data || !target?.data) return;

	if (target.data.nodeCode === '__start__') {
		ElMessage.warning('开始节点不能被连接');
		return;
	}

	if (source.data.nodeCode === '__start__' && target.data.nodeCode === 'judge') {
		ElMessage.warning('开始节点后不能接判断节点');
		return;
	}

	addEdges([
		{
			id: `edge-${connection.source}-${connection.target}`,
			source: connection.source,
			target: connection.target,
			type: 'smoothstep',
			animated: true,
			style: { stroke: '#3b82f6', strokeWidth: 2 },
		},
	]);
	ElMessage.success('连接成功');
};

const onNodeClick = (event: { node: Node<NodeData, any, string> }) => {
	selectedNode.value = event.node;
};

const updateSelectedNode = (updatedNode: Node<NodeData, any, string>) => {
	selectedNode.value = updatedNode;
	// 使用 VueFlow 的 API 更新节点，确保内部状态同步
	updateNode(updatedNode.id, updatedNode);
	// 同步更新到 nodes 数组
	const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
	if (index >= 0) {
		nodes.value[index] = updatedNode;
	}
};

const availableParams = computed(() => {
	if (!selectedNode.value) return [];
	const parents: ParamRef[] = [];
	const findParents = (nodeId: string, visited = new Set<string>()) => {
		if (visited.has(nodeId)) return;
		visited.add(nodeId);
		edges.value
			.filter((e) => e.target === nodeId)
			.forEach((edge) => {
				const parent = findNode(edge.source);
				if (parent?.data && parent.data.nodeCode !== '__start__' && parent.data.nodeCode !== 'judge') {
					parents.push({ id: parent.id, label: `${parent.data.label}.output` });
				}
				findParents(edge.source, visited);
			});
	};
	findParents(selectedNode.value.id);
	return parents;
});

const addParam = (param: ParamRef) => {
	if (!selectedNode.value?.data) return;

	const updatedNode: Node<NodeData> = {
		...selectedNode.value,
		data: {
			...selectedNode.value.data,
			inputSource: selectedNode.value.data.inputSource || [],
		},
	};

	// 查找是否已存在该节点的引用
	const existingIndex = updatedNode.data.inputSource!.findIndex((item) => item.nodeId === param.id);

	if (existingIndex >= 0) {
		// 已存在，添加 output 到 field 数组
		const existing = updatedNode.data.inputSource![existingIndex];
		if (!existing.field.includes('output')) {
			existing.field.push('output');
			selectedNode.value = updatedNode;
			// 同步更新到 VueFlow 内部状态
			updateNode(updatedNode.id, updatedNode);
			const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
			if (index >= 0) {
				nodes.value[index] = updatedNode;
			}
			ElMessage.success('已添加参数引用');
		} else {
			ElMessage.info('该参数已被引用');
		}
	} else {
		// 不存在，创建新的引用
		updatedNode.data.inputSource!.push({
			nodeId: param.id,
			field: ['output'],
			quoteOutput: false,
		});
		selectedNode.value = updatedNode;
		// 同步更新到 VueFlow 内部状态
		updateNode(updatedNode.id, updatedNode);
		const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
		if (index >= 0) {
			nodes.value[index] = updatedNode;
		}
		ElMessage.success('已添加参数引用');
	}
};

// 模型选择确认
const handleModelConfirm = (model: any) => {
	if (!selectedNode.value?.data) return;

	const updatedNode: Node<NodeData> = {
		...selectedNode.value,
		data: {
			...selectedNode.value.data,
			modelConfig: {
				modelName: model.modelName,
				modelApiKey: '',
				modelForm: model.modelForm || [],
				modelResponse: model.responseBody || {},
			},
		},
	};

	selectedNode.value = updatedNode;
	selectedModelData.value = model;
	// 同步更新到 VueFlow 内部状态
	updateNode(updatedNode.id, updatedNode);

	const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
	if (index >= 0) {
		nodes.value[index] = updatedNode;
	}

	ElMessage.success('模型已选择');
};

// 移除模型
const handleRemoveModel = () => {
	if (!selectedNode.value?.data) return;

	const updatedNode: Node<NodeData> = {
		...selectedNode.value,
		data: {
			...selectedNode.value.data,
			modelConfig: undefined,
		},
	};

	selectedNode.value = updatedNode;
	selectedModelData.value = null;
	// 同步更新到 VueFlow 内部状态
	updateNode(updatedNode.id, updatedNode);

	const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
	if (index >= 0) {
		nodes.value[index] = updatedNode;
	}

	ElMessage.success('模型已移除');
};

// 技能选择确认
const handleSkillConfirm = (skill: any) => {
	if (!selectedNode.value?.data) return;

	const updatedNode: Node<NodeData> = {
		...selectedNode.value,
		data: {
			...selectedNode.value.data,
			skillName: skill.name,
		},
	};

	selectedNode.value = updatedNode;
	selectedSkillData.value = skill;
	// 同步更新到 VueFlow 内部状态
	updateNode(updatedNode.id, updatedNode);

	const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
	if (index >= 0) {
		nodes.value[index] = updatedNode;
	}

	ElMessage.success('技能已选择');
};

// 移除技能
const handleRemoveSkill = () => {
	if (!selectedNode.value?.data) return;

	const updatedNode: Node<NodeData> = {
		...selectedNode.value,
		data: {
			...selectedNode.value.data,
			skillName: undefined,
		},
	};

	selectedNode.value = updatedNode;
	selectedSkillData.value = null;
	// 同步更新到 VueFlow 内部状态
	updateNode(updatedNode.id, updatedNode);

	const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
	if (index >= 0) {
		nodes.value[index] = updatedNode;
	}

	ElMessage.success('技能已移除');
};

// 删除上级参数字段
const handleRemoveField = (nodeId: string, fieldName: string) => {
	if (!selectedNode.value?.data) return;

	const inputSource = selectedNode.value.data.inputSource || [];
	const nodeIndex = inputSource.findIndex((item) => item.nodeId === nodeId);
	if (nodeIndex < 0) return;

	const node = inputSource[nodeIndex];
	const newField = node.field.filter((f) => f !== fieldName);

	let updatedInputSource;
	if (newField.length > 0) {
		updatedInputSource = [...inputSource];
		updatedInputSource[nodeIndex] = { ...node, field: newField };
	} else {
		updatedInputSource = inputSource.filter((_, idx) => idx !== nodeIndex);
	}

	const updatedNode: Node<NodeData> = {
		...selectedNode.value,
		data: {
			...selectedNode.value.data,
			inputSource: updatedInputSource.length > 0 ? updatedInputSource : null,
		},
	};

	selectedNode.value = updatedNode;
	// 同步更新到 VueFlow 内部状态
	updateNode(updatedNode.id, updatedNode);
	const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
	if (index >= 0) {
		nodes.value[index] = updatedNode;
	}

	ElMessage.success(`已删除参数：${fieldName}`);
};

// 切换节点输出引用
const handleToggleOutput = (nodeId: string, enabled: boolean) => {
	if (!selectedNode.value?.data) return;

	const inputSource = selectedNode.value.data.inputSource || [];
	const nodeIndex = inputSource.findIndex((item) => item.nodeId === nodeId);

	let updatedInputSource;
	if (nodeIndex >= 0) {
		updatedInputSource = [...inputSource];
		updatedInputSource[nodeIndex] = {
			...updatedInputSource[nodeIndex],
			quoteOutput: enabled,
		};
	} else {
		updatedInputSource = [
			...inputSource,
			{
				nodeId: nodeId,
				field: [],
				quoteOutput: enabled,
			},
		];
	}

	const updatedNode: Node<NodeData> = {
		...selectedNode.value,
		data: {
			...selectedNode.value.data,
			inputSource: updatedInputSource,
		},
	};

	selectedNode.value = updatedNode;
	// 同步更新到 VueFlow 内部状态
	updateNode(updatedNode.id, updatedNode);
	const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
	if (index >= 0) {
		nodes.value[index] = updatedNode;
	}

	const parentNode = nodes.value.find((n) => n.id === nodeId);
	const nodeName = parentNode?.data?.label || '节点';
	ElMessage.success(enabled ? `已开启引入 ${nodeName} 的输出` : `已关闭引入 ${nodeName} 的输出`);
};

// 通过参数值添加上级参数
const handleAddParamByValue = (paramValue: string) => {
	if (!selectedNode.value?.data) return;

	const match = paramValue.match(/\$\{([^.]+)\.(.+)\}/);
	if (!match) return;

	const nodeId = match[1];
	const paramName = match[2];

	const inputSource = selectedNode.value.data.inputSource || [];
	const existingIndex = inputSource.findIndex((item) => item.nodeId === nodeId);

	let updatedInputSource;
	if (existingIndex >= 0) {
		const existing = inputSource[existingIndex];
		if (!existing.field.includes(paramName)) {
			updatedInputSource = [...inputSource];
			updatedInputSource[existingIndex] = {
				...existing,
				field: [...existing.field, paramName],
			};
		} else {
			ElMessage.info('该参数已被引用');
			return;
		}
	} else {
		updatedInputSource = [
			...inputSource,
			{
				nodeId: nodeId,
				field: [paramName],
				quoteOutput: false,
			},
		];
	}

	const updatedNode: Node<NodeData> = {
		...selectedNode.value,
		data: {
			...selectedNode.value.data,
			inputSource: updatedInputSource,
		},
	};

	selectedNode.value = updatedNode;
	// 同步更新到 VueFlow 内部状态
	updateNode(updatedNode.id, updatedNode);
	const index = nodes.value.findIndex((n) => n.id === updatedNode.id);
	if (index >= 0) {
		nodes.value[index] = updatedNode;
	}

	ElMessage.success(`已添加上级参数：${paramName}`);
};

// 辅助函数：判断是否为开始节点
const isStartNode = (node: Node<NodeData, any, string>) => {
	return node.data?.nodeCode === START_NODE_CODE;
};

// 辅助函数：判断是否为判断节点
const isJudgeNode = (node: Node<NodeData, any, string>) => {
	const nodeCode = (node.data?.nodeCode || '').toLowerCase();
	const nodeName = (node.data?.label || '').toLowerCase();
	return JUDGE_KEYWORDS.some((k) => nodeCode.includes(k) || nodeName.includes(k));
};

// 约束校验函数
const validateFlowConstraints = () => {
	const currentNodes = nodes.value;
	const currentEdges = edges.value;

	if (!currentNodes.length) return { ok: true };

	// 创建节点映射
	const nodeMap = new Map(currentNodes.map((n) => [n.id, n]));

	// 检查是否有开始节点
	const startNode = currentNodes.find((n) => isStartNode(n));
	if (!startNode) {
		return { ok: false, message: '工作流必须包含开始节点' };
	}

	// 检查边的约束
	for (const edge of currentEdges) {
		const targetNode = nodeMap.get(edge.target);

		// 开始节点不能被其他节点链接
		if (targetNode && isStartNode(targetNode)) {
			return { ok: false, message: '开始节点不能被其他节点链接' };
		}

		// 开始节点后不能接判断节点
		const sourceNode = nodeMap.get(edge.source);
		if (sourceNode && targetNode && isStartNode(sourceNode) && isJudgeNode(targetNode)) {
			return { ok: false, message: '开始节点下一个节点不能是判断节点' };
		}
	}

	// 检查结尾节点不能是判断节点
	const hasOutEdge = new Set(currentEdges.map((e) => e.source));
	const endNodes = currentNodes.filter((n) => !hasOutEdge.has(n.id));
	if (endNodes.some((n) => isJudgeNode(n))) {
		return { ok: false, message: '结尾节点不能是判断节点' };
	}

	return { ok: true };
};

// 获取节点库
const getNodeLibrary = async () => {
	try {
		const res = await getNodeLibraryList();
		nodeLibraryGroups.value = res.data?.groups || [];
	} catch {
		nodeLibraryGroups.value = [];
	}
};

// 从节点库添加节点
const addNodeFromLibrary = (nodeCode: string, nodeName: string) => {
	const existingNodes = getNodes.value;
	let spawnX = 250;
	let spawnY = 140;

	if (existingNodes.length > 0) {
		const lastNode = existingNodes[existingNodes.length - 1];
		spawnX = (lastNode.position?.x || 250) + 180;
		spawnY = lastNode.position?.y || 140;

		if (spawnX > 800) {
			spawnX = 250;
			spawnY += 120;
		}
	}

	addNodes([
		{
			id: `node-${++nodeId}`,
			type: 'default',
			position: { x: spawnX, y: spawnY },
			data: { label: nodeName, nodeCode, inputSource: null },
			style: { background: '#fff', border: '2px solid #3b82f6', borderRadius: '8px', padding: '10px 20px' },
		},
	]);
	ElMessage.success(`已添加${nodeName}`);
};

// 获取工作流列表
const fetchWorkflowList = async () => {
	workflowListLoading.value = true;
	try {
		const res = await getWorkflowList();
		userWorkflowList.value = res.data?.listFlowUserRes?.list || [];
		templateWorkflowList.value = res.data?.listFlowTemplateRes?.list || [];
	} catch {
		userWorkflowList.value = [];
		templateWorkflowList.value = [];
	} finally {
		workflowListLoading.value = false;
	}
};

// 添加默认开始节点
const addDefaultStartNode = () => {
	const startNode = {
		id: 'start-node',
		type: 'input',
		position: { x: 200, y: 200 },
		data: { label: '开始', nodeCode: '__start__', inputSource: null },
		style: { background: '#10b981', color: '#fff', border: '2px solid #059669', borderRadius: '8px', padding: '10px 20px' },
	};
	addNodes([startNode]);
	nodes.value.push(startNode);
};

// 新建工作流
const createNewWorkflow = () => {
	currentEditingWorkflowId.value = null;
	nodes.value = [];
	edges.value = [];
	selectedNode.value = null;
	nodeId = 0;

	// 添加默认开始节点
	addDefaultStartNode();

	ElMessage.success('已清空画布，可以开始创建新工作流');
};

// 编辑工作流
const editWorkflow = async (workflow: WorkflowItem) => {
	try {
		const res = await getWorkflowDetail(workflow.id);
		if (res.data?.flowContent) {
			loadWorkflowFromDsl(res.data.flowContent);
			currentEditingWorkflowId.value = res.data.id;
			saveForm.value.flowName = res.data.flowName || res.data.flowTemplateName || '';
			saveForm.value.description = res.data.description || '';
			ElMessage.success('工作流已加载');
		}
	} catch {
		// 错误已由全局拦截器处理
	}
};

// 从 DSL 加载工作流
const loadWorkflowFromDsl = (dsl: any) => {
	if (!dsl) return;

	try {
		const loadedNodes = (dsl.nodes || []).map((n: any) => {
			// 确保 inputSource 使用新结构
			let normalizedInputSource: Array<{ nodeId: string; field: string[]; quoteOutput?: boolean }> | null = null;

			if (n.inputSource) {
				if (Array.isArray(n.inputSource)) {
					// 检查是否为新结构（对象数组）
					if (n.inputSource.length > 0 && typeof n.inputSource[0] === 'object' && n.inputSource[0].nodeId) {
						// 已经是新结构
						normalizedInputSource = n.inputSource;
					} else {
						// 旧结构（字符串数组），需要转换
						normalizedInputSource = [];
						// 旧结构不再支持，设为空
					}
				}
			}

			return {
				id: n.id,
				type: 'default',
				position: { x: n.config?.x || 220, y: n.config?.y || 140 },
				data: {
					label: n.name || '',
					nodeCode: n.nodeCode,
					inputSource: normalizedInputSource,
					formConfig: n.formConfig || null,
					modelConfig: n.modelConfig || null,
					skillName: n.skillName || null,
				},
				style: { background: '#fff', border: '2px solid #3b82f6', borderRadius: '8px', padding: '10px 20px' },
			};
		});

		const loadedEdges = (dsl.edges || []).map((e: any) => ({
			id: e.id,
			source: e.from,
			target: e.to,
			type: 'smoothstep',
			animated: true,
			style: { stroke: '#3b82f6', strokeWidth: 2 },
		}));

		nodes.value = loadedNodes;
		edges.value = loadedEdges;

		if (loadedNodes.length > 0) {
			nodeId = Math.max(
				...loadedNodes.map((n: any) => {
					const match = n.id.match(/node-(\d+)/);
					return match ? parseInt(match[1]) : 0;
				})
			);
		}
	} catch (error) {
		ElMessage.error('工作流加载失败');
	}
};

// 保存工作流
const saveWorkflowAction = () => {
	if (nodes.value.length === 0) {
		ElMessage.warning('画布为空，无法保存');
		return;
	}

	// 保存前进行约束校验
	const validateResult = validateFlowConstraints();
	if (!validateResult.ok) {
		ElMessage.warning(validateResult.message);
		return;
	}

	saveDialogVisible.value = true;
};

// 确认保存工作流
const confirmSaveWorkflow = async () => {
	if (!saveForm.value.flowName.trim()) {
		ElMessage.warning('请输入工作流名称');
		return;
	}

	const workflowDsl = {
		version: '1.0.0',
		startNodeId: nodes.value[0]?.id || '',
		nodes: nodes.value.map((n) => ({
			id: n.id,
			nodeCode: n.data?.nodeCode || 'unknown',
			name: n.data?.label || '',
			type: n.type || 'default',
			skillName: n.data?.skillName || null,
			config: {
				nodeCode: n.data?.nodeCode || 'unknown',
				x: n.position?.x || 0,
				y: n.position?.y || 0,
			},
			inputSource: n.data?.inputSource || null,
			formConfig: n.data?.formConfig || null,
			modelConfig: n.data?.modelConfig || null,
			outputResult: null,
		})),
		edges: edges.value.map((e) => ({
			id: e.id,
			from: e.source,
			to: e.target,
			type: e.type || 'smoothstep',
			mapping: {},
		})),
	};

	saving.value = true;
	try {
		if (currentEditingWorkflowId.value) {
			await updateWorkflow({
				id: currentEditingWorkflowId.value,
				flowName: saveForm.value.flowName,
				description: saveForm.value.description,
				flowContent: workflowDsl,
			});
			ElMessage.success('工作流更新成功');
		} else {
			await saveWorkflow({
				flowName: saveForm.value.flowName,
				description: saveForm.value.description,
				flowContent: workflowDsl,
			});
			ElMessage.success('工作流保存成功');
		}
		saveDialogVisible.value = false;
		saveForm.value.flowName = '';
		saveForm.value.description = '';
		currentEditingWorkflowId.value = null;
		await fetchWorkflowList();
	} catch {
		// 错误已由全局拦截器处理
	} finally {
		saving.value = false;
	}
};

// 删除工作流
const deleteWorkflowAction = async (workflow: WorkflowItem) => {
	try {
		await ElMessageBox.confirm(`确定要删除工作流"${workflow.flowName}"吗？`, '删除确认', {
			confirmButtonText: '确定',
			cancelButtonText: '取消',
			type: 'warning',
		});

		await deleteWorkflow(workflow.id);
		ElMessage.success('工作流删除成功');

		if (currentEditingWorkflowId.value === workflow.id) {
			currentEditingWorkflowId.value = null;
			saveForm.value.flowName = '';
			saveForm.value.description = '';
		}

		await fetchWorkflowList();
	} catch (error) {
		if (error !== 'cancel') {
			// 错误已由全局拦截器处理
		}
	}
};

// 初始化
onMounted(async () => {
	await getNodeLibrary();
	await fetchWorkflowList();

	// 添加默认开始节点（固定在页面中间偏左）
	addDefaultStartNode();
	nodeId = 0;
});
</script>

<style scoped lang="scss">
.workflow-canvas-page {
	height: calc(100vh - 100px);
	display: flex;
	flex-direction: column;
	background: #f3f5f9;
	position: relative;
}

.toolbar {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 14px 20px;
	background: #ffffff;
	border-bottom: 1px solid #e6eaf0;
	box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
	position: relative;
	z-index: 10;

	h2 {
		margin: 0;
		font-size: 18px;
		font-weight: 700;
		color: #1f2937;
		letter-spacing: 0;
	}

	.toolbar-left {
		display: flex;
		align-items: center;
		gap: 12px;
	}

	.info {
		font-size: 12px;
		color: #475569;
		padding: 4px 10px;
		background: #f8fafc;
		border: 1px solid #e2e8f0;
		border-radius: 14px;
		font-weight: 500;
	}

	.toolbar-right {
		display: flex;
		gap: 8px;

		:deep(.el-button) {
			border-radius: 6px;
			font-weight: 600;
			padding: 8px 14px;
			transition: all 0.2s ease;
		}
	}
}

.content {
	flex: 1;
	display: grid;
	grid-template-columns: 340px 1fr 380px;
	gap: 12px;
	min-height: 0;
	padding: 12px;
	position: relative;
	z-index: 1;
}

// 中间：画布区域
.flow-wrapper {
	position: relative;
	background: #ffffff;
	border-radius: 10px;
	box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
	border: 1px solid #e6eaf0;
	overflow: hidden;
}

@media (max-width: 1400px) {
	.content {
		grid-template-columns: 300px 1fr 340px;
		gap: 12px;
		padding: 12px;
	}
}

@media (max-width: 1200px) {
	.content {
		grid-template-columns: 1fr;
		grid-template-rows: auto 1fr;
	}
}
</style>

<style>
@import '@vue-flow/core/dist/style.css';
@import '@vue-flow/core/dist/theme-default.css';
@import '@vue-flow/controls/dist/style.css';
@import '@vue-flow/minimap/dist/style.css';

/* 连接点样式优化 - 更大尺寸，hover 放大但不位移 */
.vue-flow__handle {
	width: 14px !important;
	height: 14px !important;
	background: #3b82f6 !important;
	border: 2px solid #fff !important;
	opacity: 1 !important;
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2) !important;
	cursor: crosshair !important;
	z-index: 10 !important;
	transition: all 0.15s ease !important;
	margin: 0 !important;
}

.vue-flow__handle:hover {
	width: 22px !important;
	height: 22px !important;
	margin: -4px !important;
	background: #2563eb !important;
	box-shadow: 0 3px 12px rgba(37, 99, 235, 0.6) !important;
}

/* 节点悬停时确保连接点可见 */
.vue-flow__node:hover .vue-flow__handle {
	opacity: 1 !important;
}

/* 连接线样式 */
.vue-flow__edge-path {
	stroke-width: 2px;
}

.vue-flow__edge.selected .vue-flow__edge-path {
	stroke: #ef4444 !important;
	stroke-width: 3px;
}

/* 节点样式优化 */
.vue-flow__node {
	cursor: move;
}

.vue-flow__node:hover {
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
}

/* 确保连接线在拖动时可见 */
.vue-flow__connection-path {
	stroke: #3b82f6 !important;
	stroke-width: 2px !important;
}
</style>
