local M = {}

local json = require("dkjson")
local aubo = require("aubo")
local sched = sched or aubo.sched
local math = aubo.math or math
local sleep = sched.sleep
local thread = sched.thread
local sync = sched.sync
local run = sched.run
local kill = sched.kill
local halt = sched.halt
-- 导入焊接算法模块 aubo_math
local aubo_math = require("aubo_math")

-- 导入子模块
local welding_common = require("welding_common")
local welding_config = require("welding_config")
local welding_arc = require("welding_arc")
local welding_motion = require("welding_motion")
local welding_weave = require("welding_weave")
local welding_laser = require("welding_laser")
local welding_utils = require("welding_utils")
local welding_types = require("welding_types")
local welding_helpers = require("welding_helpers")
local welding_stitch = require("welding_stitch")
local welding_multipass = require("welding_multipass")
local welding_resume = require("welding_resume")

-- 全局变量
local program_normal_stop = true
local laser_points_db_ = {}
local handler_laser_thread_move_5 = nil
local handler_label_cache_thread_ = nil
local cached_label_comment_ = nil
local default_welding_options_ = {
	state = nil,
	shared_params = nil,
	language = "en",
	runtime_options = { rollback_distance = -1 },
}

local function cloneTable(t)
	if type(t) ~= "table" then
		return t
	end
	local out = {}
	for k, v in pairs(t) do
		out[k] = cloneTable(v)
	end
	return out
end

local function isLabelCommentValid(label)
	if type(label) ~= "table" then
		return false
	end
	local idx = label.point_index
	if idx == nil or idx == "" then
		return false
	end
	return true
end

local function startLabelCacheThread()
	if handler_label_cache_thread_ ~= nil then
		kill(handler_label_cache_thread_)
		handler_label_cache_thread_ = nil
	end

	handler_label_cache_thread_ = thread(function()
		while true do
			local label = welding_utils.getAuboLabelComment(false)
			if isLabelCommentValid(label) then
				cached_label_comment_ = cloneTable(label)
			end
			sched.sleep(0.05)
		end
	end, "Label_Cache_Thread")
	run(handler_label_cache_thread_)
	log_info(welding_common.log_prefix .. "label cache thread started")
end

local function stopLabelCacheThread()
	if handler_label_cache_thread_ ~= nil then
		kill(handler_label_cache_thread_)
		handler_label_cache_thread_ = nil
		log_info(welding_common.log_prefix .. "label cache thread stopped")
	end
end

local function getCachedAuboLabelComment()
	return cloneTable(cached_label_comment_)
end

-- 初始化默认运行参数（给多焊缝多次 generateAction 复用）
-- 支持两种调用：
-- 1) initWelding({ state=..., shared_params=..., language=..., runtime_options=... })
-- 2) initWelding(state, shared_params, language, runtime_options)
local function initWelding(state, shared_params, language, runtime_options, enable_laser)
	local _ENV = sched.select_robot(1)
	local cfg = nil
	if type(state) == "table" then
		cfg = state
	else
		cfg = {
			state = state,
			shared_params = shared_params,
			language = language,
			runtime_options = runtime_options,
		}
	end

	if cfg.state ~= nil then
		default_welding_options_.state = cfg.state
	end
	if cfg.shared_params ~= nil then
		default_welding_options_.shared_params = cloneTable(cfg.shared_params)
	end
	if cfg.language ~= nil then
		default_welding_options_.language = cfg.language
	end
	if cfg.runtime_options ~= nil then
		default_welding_options_.runtime_options = cloneTable(cfg.runtime_options)
	end

	if type(default_welding_options_.runtime_options) ~= "table" then
		default_welding_options_.runtime_options = { rollback_distance = -1 }
	elseif default_welding_options_.runtime_options.rollback_distance == nil then
		default_welding_options_.runtime_options.rollback_distance = -1
	end

	-- initResumeContext 里可能直接弹错，需提前设置语言
	welding_common.language = default_welding_options_.language or "en"
	local rollback_distance = tonumber(default_welding_options_.runtime_options.rollback_distance) or -1
	welding_resume.initResumeContext(
		rollback_distance,
		default_welding_options_.shared_params,
		default_welding_options_.state
	)
	startLabelCacheThread()

	log_info(
		welding_common.log_prefix
			.. "initWelding updated defaults: state="
			.. tostring(default_welding_options_.state)
			.. ", language="
			.. tostring(default_welding_options_.language)
			.. ", rollback_distance="
			.. tostring(default_welding_options_.runtime_options.rollback_distance)
	)

	if enable_laser then
		-- 设置手眼数据
		local laser_config, decode_err = json.decode(_G.laser_device_config_)
		welding_laser.setLaserDeviceConfig(laser_config)
		welding_laser.connectDevice(welding_laser.getLaserDeviceConfig())
	end
end

local function getTrackingTargetPose(uuid, pose_name)
	if not uuid or uuid == "" then
		return nil, pose_name .. " uuid is empty"
	end

	local point_data = welding_laser.getLaserData(uuid)
	if not point_data then
		return nil, "missing cached laser data for " .. pose_name .. ": " .. tostring(uuid)
	end

	if type(point_data.tcp_pose) ~= "table" or #point_data.tcp_pose < 6 then
		return nil, "invalid cached tcp_pose for " .. pose_name .. ": " .. tostring(uuid)
	end

	return point_data.tcp_pose, nil
end

local function initTrackingSession(action)
	-- 在开始采集前先把跟踪线段的起止目标点传给算法。
	local start_pose, start_err = getTrackingTargetPose(action.tracking_start_target_uuid, "tracking start target")
	if start_err then
		return false, start_err
	end

	local end_pose, end_err = getTrackingTargetPose(action.tracking_end_target_uuid, "tracking end target")
	if end_err then
		return false, end_err
	end

	log_info(welding_common.log_prefix .. "tracking init start pose=" .. welding_motion.formatPoseString(start_pose))
	log_info(welding_common.log_prefix .. "tracking init end pose=" .. welding_motion.formatPoseString(end_pose))

	local result = welding_laser.trackingInit({ start_pose, end_pose }, 0.003)
	if result == nil then
		return false, "trackingInit rpc failed"
	end

	return true, nil
end

-- ==================== 核心功能函数 ====================
local function processInstruction(inst_type, action, params, state, context, is_welding_endpoints)
	local _ENV = sched.select_robot(1)
	local points = action.roadpoints or {}

	local motion_param = action.motion_param or {}
	local welder_param = action.welder_param or {}
	local prev_action = context and context.prev_action
	local resume_run_state, execute_motion, should_skip_instruction =
		welding_resume.resolveResumeExecutionState(inst_type)

	if should_skip_instruction then
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	end

	-- 运动指令处理
	-- 轴动
	if inst_type == "Robot_MoveJoint" then
		log_info(welding_common.log_prefix .. "Processing Robot_MoveJoint instruction")
		if not points or #points < 1 then
			return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
		end
		local valid, err = welding_motion.validatePoint(points[1])
		if not valid then
			return "", err
		end

		return welding_motion.generateMoveJoint(points[1], params, motion_param.weld_type, execute_motion),
			welding_common.ErrorCode.COMMON.SUCCESS
	--设置行号
	elseif inst_type == "Set_Lable" then
		local line_num = action.index
		welding_utils.auboSetLabel(line_num)
		return "setLabel", welding_common.ErrorCode.COMMON.SUCCESS
	-- 轴动到准备点
	elseif inst_type == "Robot_MoveJointToReadyPoint" then
		log_info(welding_common.log_prefix .. "Processing Robot_MoveJointToReadyPoint instruction")

		local target_point = {}

		if action.roadpoints[1].type ~= "Common" then
			-- 处理激光路点
			if state == "raw_point_sim" then
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end

			local target_uuid = action.roadpoints[1].uuid

			target_point = welding_laser.getLaserData(target_uuid)
		else
			if not points or #points < 1 then
				return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
			end
			local valid, err = welding_motion.validatePoint(points[1])
			if not valid then
				return "", err
			end
			target_point.tcp_pose = points[1].tcp_pose
			target_point.joint_angles = points[1].q
		end

		local offset_distance = tonumber(params.offset_distance) or 0
		local offset = { 0, 0, -offset_distance, 0, 0, 0 }
		local prepare_point = {
			tcp_pose = math.poseTrans(target_point.tcp_pose, offset),
			q = target_point.joint_angles,
		}
		return welding_motion.generateMoveJoint(prepare_point, params, motion_param.weld_type, execute_motion),
			welding_common.ErrorCode.COMMON.SUCCESS
	-- 直线至准备点
	elseif inst_type == "Robot_MoveLineToReadyPoint" then
		log_info(welding_common.log_prefix .. "Processing Robot_MoveLineToReadyPoint instruction")

		local target_point = {}

		local target_point_data

		if action.event == 15 then
			-- 跟踪开始：第1个是目标点要跳过，取第2个拍照点
			if action.roadpoints and #action.roadpoints >= 2 then
				target_point_data = action.roadpoints[2]
			end
		elseif action.event == 16 then
			-- 跟踪结束：没有拍照点，直接取第1个目标点
			if action.roadpoints and #action.roadpoints >= 1 then
				target_point_data = action.roadpoints[1]
			end
		end

		if target_point_data then
			if target_point_data.type ~= "Common" then
				if state == "raw_point_sim" then
					return "", welding_common.ErrorCode.COMMON.SUCCESS
				end

				target_point = welding_laser.getLaserData(target_point_data.uuid)
			else
				target_point.tcp_pose = target_point_data.tcp_pose
				target_point.joint_angles = target_point_data.q
			end
		elseif
			prev_action
			and prev_action.roadpoints
			and prev_action.roadpoints[1]
			and prev_action.roadpoints[1].type ~= "Common"
		then
			-- 处理激光路点
			if state == "raw_point_sim" then
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end

			local target_uuid = prev_action.roadpoints[#prev_action.roadpoints].uuid

			target_point = welding_laser.getLaserData(target_uuid)
		else
			target_point.tcp_pose = prev_action.roadpoints[#prev_action.roadpoints].tcp_pose
			target_point.joint_angles = prev_action.roadpoints[#prev_action.roadpoints].q
		end

		local offset = { 0, 0, -params.offset_distance or 20.0, 0, 0, 0 }

		local prepare_point = {
			tcp_pose = math.poseTrans(target_point.tcp_pose, offset),
			q = target_point.joint_angles,
		}

		return welding_motion.generateMoveLine(
			prepare_point,
			params.motion_parameters.tool_speed,
			params,
			state,
			false,
			motion_param.weld_type,
			true,
			execute_motion
		),
			welding_common.ErrorCode.COMMON.SUCCESS
	-- 空走直线
	elseif inst_type == "Robot_AirMoveLine" then
		log_info(welding_common.log_prefix .. "Processing Robot_AirMoveLine instruction")

		local target_point = {}

		if action.roadpoints[1].type ~= "Common" then
			-- 处理激光路点
			if state == "raw_point_sim" then
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end

			local target_uuid = action.roadpoints[1].uuid

			if action.event == 15 then
				local photo_uuid = nil
				for _, point in ipairs(action.roadpoints or {}) do
					if point and point.type == "Laser_Photo_Point" then
						photo_uuid = point.uuid
						break
					end
				end
				if not photo_uuid then
					log_error(welding_common.log_prefix .. "Missing Laser_Photo_Point uuid for event 15")
					return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
				end
				-- 激光跟踪起始点是拍照点
				target_point = welding_laser.getLaserData(photo_uuid)
			else
				target_point = welding_laser.getLaserData(target_uuid)
			end
		else
			if not points or #points < 1 then
				return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
			end
			local valid, err = welding_motion.validatePoint(points[1])
			if not valid then
				return "", err
			end
			target_point.tcp_pose = points[1].tcp_pose
			target_point.joint_angles = points[1].q
		end

		return welding_motion.generateMoveLine(
			target_point.tcp_pose,
			params.motion_parameters.tool_speed,
			params,
			state,
			is_welding_endpoints,
			motion_param.weld_type,
			true,
			execute_motion
		),
			welding_common.ErrorCode.COMMON.SUCCESS
	-- 直线运动
	elseif inst_type == "Robot_MoveLine" then
		log_info(welding_common.log_prefix .. "Processing Robot_MoveLine instruction")

		local target_point = {}
		local target_index = 1

		-- 激光跟踪时候需要运动到拍照点
		if action.event == 15 and #points > 2 then
			target_index = #points
		end

		--激光探寻结束点特殊处理
		if action.roadpoints[target_index].type ~= "Common" then
			-- 处理激光路点
			if state == "raw_point_sim" then
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end

			local target_uuid = action.roadpoints[target_index].uuid
			target_point = welding_laser.getLaserData(target_uuid)
		else
			if not points or #points < target_index then
				return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
			end
			local valid, err = welding_motion.validatePoint(points[target_index])
			if not valid then
				return "", err
			end
			target_point.tcp_pose = points[target_index].tcp_pose
			target_point.joint_angles = points[target_index].q

			if state ~= "raw_point_sim" and action.event == 14 then
				handler_laser_thread_move_5 = thread(function()
					sched.INST([[flag_laser_thread_move_5 = 1]], _ENV)
					welding_motion.generateMoveLine(
						target_point.tcp_pose,
						action.laser_param.laser_until_speed,
						params,
						state,
						false,
						motion_param.weld_type,
						true,
						execute_motion
					)
					sched.INST([[flag_laser_thread_move_5 = 2]], _ENV)
				end, "laser_thread_move_5")
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end
		end

		local move_speed = motion_param.welding_speed
		if action.event == 15 then
			move_speed = (action.laser_param.laser_pretrack_speed or 7) / 1000.0
		end

		return welding_motion.generateMoveLine(
			target_point.tcp_pose,
			move_speed,
			params,
			state,
			is_welding_endpoints,
			motion_param.weld_type,
			true,
			execute_motion
		),
			welding_common.ErrorCode.COMMON.SUCCESS
	-- moveP运动
	elseif inst_type == "Robot_MoveP" then
		log_info(welding_common.log_prefix .. "Processing Robot_MoveP instruction")

		local target_point = {}

		--激光探寻结束点特殊处理
		if action.roadpoints[1].type ~= "Common" then
			-- 处理激光路点
			if state == "raw_point_sim" then
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end

			local target_uuid = action.roadpoints[1].uuid
			target_point = welding_laser.getLaserData(target_uuid)
		else
			if not points or #points < 1 then
				return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
			end
			local valid, err = welding_motion.validatePoint(points[1])
			if not valid then
				return "", err
			end
			target_point.tcp_pose = points[1].tcp_pose
			target_point.joint_angles = points[1].q
		end

		return welding_motion.generateMoveP(
			target_point.tcp_pose,
			motion_param.welding_speed,
			params,
			state,
			is_welding_endpoints,
			motion_param.weld_type,
			execute_motion
		),
			welding_common.ErrorCode.COMMON.SUCCESS

	-- 空走圆弧
	elseif inst_type == "Robot_AirMoveArc" then
		if #points < 2 then
			return "", welding_common.ErrorCode.WAYPOINT.DIMENSION_ERR_WAYPOINT
		end

		local point_2 = {}
		local point_3 = {}

		if action.roadpoints[1].type ~= "Common" then
			-- 处理激光路点
			if state == "raw_point_sim" then
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end

			point_2 = welding_laser.getLaserData(action.roadpoints[2].uuid)
			point_3 = welding_laser.getLaserData(action.roadpoints[3].uuid)
		else
			local valid1, err1 = welding_motion.validatePoint(action.roadpoints[2])
			local valid2, err2 = welding_motion.validatePoint(action.roadpoints[3])
			if not valid1 then
				return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
			end
			if not valid2 then
				return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
			end

			point_2 = action.roadpoints[2]
			point_3 = action.roadpoints[3]
		end

		if execute_motion then
			local resume_arc = welding_resume.consumeResumeArcContinuation
					and welding_resume.consumeResumeArcContinuation()
				or nil
			if resume_arc and type(resume_arc.via_pose) == "table" and type(resume_arc.end_pose) == "table" then
				point_2 = resume_arc.via_pose
				point_3 = resume_arc.end_pose
				log_info(welding_common.log_prefix .. "apply resume moveC continuation in air move arc")
			end
		end

		return welding_motion.generateMoveArc(
			point_2,
			point_3,
			params.motion_parameters.tool_speed,
			params,
			state,
			is_welding_endpoints,
			motion_param.weld_type,
			true,
			execute_motion
		),
			welding_common.ErrorCode.COMMON.SUCCESS
	-- 圆弧运动
	elseif inst_type == "Robot_MoveArc" then
		if #points < 2 then
			return "", welding_common.ErrorCode.WAYPOINT.DIMENSION_ERR_WAYPOINT
		end

		local point_2 = {}
		local point_3 = {}

		if action.roadpoints[1].type ~= "Common" then
			-- 处理激光路点
			if state == "raw_point_sim" then
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end

			point_2 = welding_laser.getLaserData(action.roadpoints[2].uuid)
			point_3 = welding_laser.getLaserData(action.roadpoints[3].uuid)
		else
			local valid1, err1 = welding_motion.validatePoint(action.roadpoints[2])
			local valid2, err2 = welding_motion.validatePoint(action.roadpoints[3])
			if not valid1 then
				return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
			end
			if not valid2 then
				return "", welding_common.ErrorCode.WAYPOINT.EMPTY_WAYPOINT
			end

			point_2 = action.roadpoints[2]
			point_3 = action.roadpoints[3]
		end

		if execute_motion then
			local resume_arc = welding_resume.consumeResumeArcContinuation
					and welding_resume.consumeResumeArcContinuation()
				or nil
			if resume_arc and type(resume_arc.via_pose) == "table" and type(resume_arc.end_pose) == "table" then
				point_2 = resume_arc.via_pose
				point_3 = resume_arc.end_pose
				log_info(welding_common.log_prefix .. "apply resume moveC continuation in processInstruction")
			end
		end

		return welding_motion.generateMoveArc(
			point_2,
			point_3,
			motion_param.welding_speed,
			params,
			state,
			is_welding_endpoints,
			motion_param.weld_type,
			true,
			execute_motion
		),
			welding_common.ErrorCode.COMMON.SUCCESS
	-- 等待到位
	elseif inst_type == "Robot_WaitArrival" then
		local needs_wait = is_welding_endpoints
			or action.event == 12
			or action.event == 13
			or action.event == 14
			or action.event == 15
			or action.event == 16
		if not needs_wait then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end

		log_info(welding_common.log_prefix .. "Processing Robot_WaitArrival instruction")
		welding_arc.syncProgramPoint()
		return "sched.sync_program_point()", welding_common.ErrorCode.COMMON.SUCCESS
	-- 开启摆动
	elseif inst_type == "Robot_WeaveStart" then
		-- 在 raw_point_sim 状态下跳过摆动指令
		if state == "raw_point_sim" then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end

		if not motion_param.weave then
			return "", welding_common.ErrorCode.WEAVE.TYPE_ERR
		end
		if not motion_param.amplitude then
			return "", welding_common.ErrorCode.WEAVE.AMPLITUDE_ERR
		end
		if not motion_param.frequency then
			return "", welding_common.ErrorCode.WEAVE.FREQUENCY_ERR
		end
		local weave_param = welding_weave.getSwingParams(motion_param)
		log_info(welding_common.log_prefix .. "weave start")
		weaveStart(weave_param)
		return string.format("WeaveStart(%s)", weave_param), welding_common.ErrorCode.COMMON.SUCCESS

	-- 结束摆动
	elseif inst_type == "Robot_WeaveEnd" then
		-- 在 raw_point_sim 状态下跳过摆动指令
		if state == "raw_point_sim" then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end
		log_info(welding_common.log_prefix .. "weave end")
		weaveEnd()
		return "weaveEnd()", welding_common.ErrorCode.COMMON.SUCCESS
	-- 焊接指令处理
	-- 起弧
	elseif inst_type == "Welder_ArcOn" then
		if not (state == "raw_path_weld") then
			return "", welding_common.ErrorCode.COMMON.SUCCESS -- 模拟状态下跳过ArcOn
		end
		log_info(welding_common.log_prefix .. "Processing W elder_ArcOn instruction")
		local valid, err = welding_motion.validateWeldingParams(welder_param)
		if not valid then
			return "", err
		end
		welding_arc.startArc()
		return "startArc()", welding_common.ErrorCode.COMMON.SUCCESS
	-- 熄弧
	elseif inst_type == "Welder_ArcOff" then
		if not (state == "raw_path_weld") then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end
		log_info(welding_common.log_prefix .. "Processing Welder_ArcOff instruction")
		welding_arc.stopArc()
		return "stopArc()", welding_common.ErrorCode.COMMON.SUCCESS
	-- 更新焊机参数
	elseif inst_type == "Welder_UpdateParameter" then
		if not (state == "raw_path_weld") then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end
		log_info(welding_common.log_prefix .. "Processing Welder_UpdateParameter instruction")
		welding_config.updateWeldingParameters(
			welder_param.current or 0,
			welder_param.voltage or 0,
			welder_param.off_voltage or 0,
			welder_param.off_current or 0,
			welder_param.arc_extinguishing_time or 0,
			welder_param.delivery_time or 0,
			welder_param.arc_voltage or 0,
			welder_param.arc_current or 0,
			welder_param.starting_arc_time or 0
		)
		return string.format(
			"updateWeldingParameters(%s,%s,%s,%s,%s,%s,%s,%s,%s)",
			welder_param.current or 0,
			welder_param.voltage or 0,
			welder_param.off_voltage or 0,
			welder_param.off_current or 0,
			welder_param.arc_extinguishing_time or 0,
			welder_param.delivery_time or 0,
			welder_param.arc_voltage or 0,
			welder_param.arc_current or 0,
			welder_param.starting_arc_time or 0
		),
			welding_common.ErrorCode.COMMON.SUCCESS
	-- 熄弧 使用上个动作组的熄弧参数
	elseif inst_type == "Welder_ArcOffPra" then
		if not (state == "raw_path_weld") then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end
		log_info(welding_common.log_prefix .. "Processing Welder_ArcOffPra instruction")
		local pre_welder_param = prev_action.welder_param or {}
		welding_config.updateWeldingParameters(
			pre_welder_param.current or 1,
			pre_welder_param.voltage or 2,
			pre_welder_param.off_voltage or 3,
			pre_welder_param.off_current or 4,
			pre_welder_param.arc_extinguishing_time or 0,
			pre_welder_param.delivery_time or 0,
			pre_welder_param.arc_voltage or 0,
			pre_welder_param.arc_current or 0,
			pre_welder_param.starting_arc_time or 0
		)
		welding_arc.stopArc()
		return "stopArc()", welding_common.ErrorCode.COMMON.SUCCESS

	-- 摆动指令组
	elseif inst_type == "Robot_MoveWeave" then
		-- 在 raw_point_sim 状态下跳过摆动指令
		if state == "raw_point_sim" then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end
		-- 验证必需参数
		if not motion_param.weave then
			return "", welding_common.ErrorCode.WEAVE.TYPE_ERR
		end
		if not motion_param.amplitude then
			return "", welding_common.ErrorCode.WEAVE.AMPLITUDE_ERR
		end
		if not motion_param.frequency then
			return "", welding_common.ErrorCode.WEAVE.FREQUENCY_ERR
		end

		-- 计算points数量
		local count = 0
		for _ in pairs(points) do
			count = count + 1
		end
		log_info(
			welding_common.log_prefix .. string.format("count: %d, motion_param.weave: %d", count, motion_param.weave)
		)

		-- 主处理逻辑
		if count == 1 and motion_param.weave == 3 then
			local valid, err = welding_weave.validateWeaveInputParameters(prev_action, points)
			if not valid then
				return "", err
			end
			local lastRoadpoint = prev_action.roadpoints[#prev_action.roadpoints]
			local start_pose = welding_weave.getPoseFromPoint(lastRoadpoint)
			local resumed = welding_resume.consumeResumeJustRestoredFlag
					and welding_resume.consumeResumeJustRestoredFlag()
				or false
			if resumed then
				start_pose = getTcpPose()
				log_info(
					welding_common.log_prefix
						.. "resume weave from current tcp pose (crescent): "
						.. welding_motion.formatPoseString(start_pose)
				)
			end
			local target_pose = welding_weave.getPoseFromPoint(points[1])
			return welding_weave.linearCrescentOscillation(motion_param, start_pose, target_pose, params, state)
		elseif count == 1 and motion_param.weave == 4 then
			local valid, err = welding_weave.validateWeaveInputParameters(prev_action, points)
			if not valid then
				return "", err
			end
			local lastRoadpoint = prev_action.roadpoints[#prev_action.roadpoints]
			local start_pose = welding_weave.getPoseFromPoint(lastRoadpoint)
			local resumed = welding_resume.consumeResumeJustRestoredFlag
					and welding_resume.consumeResumeJustRestoredFlag()
				or false
			if resumed then
				start_pose = getTcpPose()
				log_info(
					welding_common.log_prefix
						.. "resume weave from current tcp pose (straight): "
						.. welding_motion.formatPoseString(start_pose)
				)
			end
			local target_pose = welding_weave.getPoseFromPoint(points[1])
			return welding_weave.handleStraightWeave(motion_param, start_pose, target_pose, params, state)
		elseif count == 3 and motion_param.weave == 3 then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		elseif count == 3 and motion_param.weave == 4 then
			local swing_points = {}
			table.insert(swing_points, welding_weave.getPoseFromPoint(points[1]))
			table.insert(swing_points, welding_weave.getPoseFromPoint(points[2]))
			table.insert(swing_points, welding_weave.getPoseFromPoint(points[3]))
			return welding_weave.handleCircularWeave(motion_param, swing_points, params, state)
		else
			return "", welding_common.ErrorCode.COMMON.UNKNOWN_ERROR
		end

	-- 断续焊指令组
	elseif inst_type == "Robot_MoveStitchWeld" then
		-- 1. 验证是否开启断续焊
		local is_intermittent = motion_param.is_intermittent_welding or false
		if not is_intermittent then
			log_info(welding_common.log_prefix .. "断续焊未开启，跳过解析")
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end

		-- 2. 验证断续焊核心参数（与提供的参数命名对应）
		local inter_mode = 1 -- 工作模式默认为1
		local weld_len = motion_param.intermittent_weld_length -- 长度m
		local non_weld_len = motion_param.intermittent_non_weld_length

		-- 2.1 验证必需参数是否存在
		if weld_len == nil then
			return "", welding_common.ErrorCode.INTERMITTENT.WELD_LEN_ERR
		end
		if non_weld_len == nil then
			return "", welding_common.ErrorCode.INTERMITTENT.NON_WELD_LEN_ERR
		end

		-- 2.2 验证参数值有效性
		if weld_len <= 0 or non_weld_len < 0 then
			return "", welding_common.ErrorCode.INTERMITTENT.PARAM_VALUE_ERR
		end
		if inter_mode < 0 or inter_mode > 1 then
			return "", welding_common.ErrorCode.INTERMITTENT.MODE_ERR
		end

		log_info(welding_common.log_prefix .. "=== 断续焊核心配置参数 ===")
		log_info(
			welding_common.log_prefix
				.. string.format("断续焊模式: %d (0=先空走后焊接, 1=先焊接后空走)", inter_mode)
		)
		log_info(
			welding_common.log_prefix
				.. string.format(
					"焊接段长度: %.3f m (原始参数: %.1f mm)",
					weld_len,
					motion_param.intermittent_weld_length
				)
		)
		log_info(
			welding_common.log_prefix
				.. string.format(
					"空走段长度: %.3f m (原始参数: %.1f mm)",
					non_weld_len,
					motion_param.intermittent_non_weld_length
				)
		)
		log_info(
			welding_common.log_prefix
				.. string.format(
					"摆焊模式: %d (0=无摆焊, 1=正弦摆焊, 2=螺旋摆焊, 3=月牙摆焊, 4=直线摆焊)",
					motion_param.weave or 0
				)
		)

		-- 计算points数量
		local count = 0
		for _ in pairs(points) do
			count = count + 1
		end
		log_info(
			welding_common.log_prefix
				.. string.format("目标点数量: %d, 摆焊模式: %d", count, motion_param.weave or 0)
		)

		-- 主处理逻辑
		if count == 1 then
			local valid, err = welding_weave.validateWeaveInputParameters(prev_action, points)
			if not valid then
				return "", err
			end
			local lastRoadpoint = prev_action.roadpoints[#prev_action.roadpoints]
			local start_point = welding_weave.getPoseFromPoint(lastRoadpoint)
			local end_point = welding_weave.getPoseFromPoint(points[1])

			log_info(welding_common.log_prefix .. "=== 断续焊路径端点 ===")
			log_info(
				welding_common.log_prefix
					.. string.format("路径起点位姿: %s", welding_motion.formatPoseString(start_point))
			)
			log_info(
				welding_common.log_prefix
					.. string.format("路径终点位姿: %s", welding_motion.formatPoseString(end_point))
			)
			log_info(welding_common.log_prefix .. string.format("weld_len (焊接段长度): %.3f m", weld_len))
			log_info(welding_common.log_prefix .. string.format("non_weld_len (空走段长度): %.3f m", non_weld_len))
			-- motion_param（运动参数）
			log_info(welding_common.log_prefix .. "6. motion_param (运动参数关键字段):")
			log_info(
				welding_common.log_prefix
					.. string.format("   - welding_speed (焊接速度): %.3f m/s", motion_param.welding_speed or 0.0)
			)
			log_info(
				welding_common.log_prefix .. string.format("   - weave (摆焊模式): %d", motion_param.weave or 0)
			)
			log_info(
				welding_common.log_prefix
					.. string.format("   - amplitude (摆焊幅度): %.3f m", motion_param.amplitude or 0.0)
			)
			log_info(
				welding_common.log_prefix
					.. string.format("   - frequency (摆焊频率): %.1f Hz", motion_param.frequency or 0.0)
			)
			-- params（全局参数）
			log_info(welding_common.log_prefix .. "7. params (全局参数关键字段):")
			log_info(
				welding_common.log_prefix
					.. string.format(
						"   - joint_acc (关节加速度): %.3f rad/s²",
						params.motion_parameters.joint_acc or 0.0
					)
			)
			log_info(
				welding_common.log_prefix
					.. string.format(
						"   - joint_speed (关节速度): %.3f rad/s",
						params.motion_parameters.joint_speed or 0.0
					)
			)
			log_info(
				welding_common.log_prefix
					.. string.format(
						"   - tool_acc (工具加速度): %.3f m/s²",
						params.motion_parameters.tool_acc or 0.0
					)
			)
			log_info(
				welding_common.log_prefix
					.. string.format(
						"   - tool_speed (工具空走速度): %.3f m/s",
						params.motion_parameters.tool_speed or 0.0
					)
			)
			log_info(
				welding_common.log_prefix
					.. string.format(
						"   - blend_radius (交融半径): %.3f m",
						params.motion_parameters.blend_radius or 0.0
					)
			)
			-- state（运行状态：如raw_path_sim/raw_path_weld）
			log_info(welding_common.log_prefix .. string.format("state (运行状态): %s", state or "未知状态"))
			-- is_welding_endpoints（端点平滑标记）
			log_info(
				welding_common.log_prefix
					.. string.format(
						"is_welding_endpoints (端点平滑标记): %s",
						tostring(is_welding_endpoints or false)
					)
			)
			log_info(welding_common.log_prefix .. "===============================================")

			welding_stitch.intermittentWeldingProcess(
				start_point,
				end_point,
				inter_mode,
				weld_len,
				non_weld_len,
				motion_param,
				params,
				state,
				is_welding_endpoints,
				welder_param
			)
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		else
			return "", welding_common.ErrorCode.COMMON.UNKNOWN_ERROR
		end
	--打开线激光
	elseif inst_type == "LineLaser_Open" then
		if state == "raw_point_sim" then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end
		log_info(welding_common.log_prefix .. "Open laser")

		-- event=12 寻位模式：到达寻位点后等待配置的时间（默认2秒），确保机器人停稳后再打开激光
		if action.event == 12 then
			local wait_time = (action.laser_param and action.laser_param.laser_seek_wait_time) or 0.0
			sched.sleep(wait_time)
			log_info(
				welding_common.log_prefix
					.. string.format(
						"Wait %.1fs before open laser (event=12 seek mode), robot should be stable now",
						wait_time
					)
			)
		end

		--开启激光
		if not welding_laser.operateLaserStatus(1) then
			log_info(welding_common.log_prefix .. "Failed to activate laser")
			return "", welding_common.ErrorCode.LINELASER.OPEN_LASER_ERR
		end
		--设置任务号
		if action.event == 12 or action.event == 13 then
			local task_number = action.laser_param.laser_channel
			log_info(welding_common.log_prefix .. "Task_number:" .. task_number)
			log_info(welding_common.log_prefix .. "GetJobNumber:" .. welding_laser.getJobNumber())
			if task_number ~= welding_laser.getJobNumber() and not welding_laser.setJobNumber(task_number) then
				return "", welding_common.ErrorCode.LINELASER.SET_TEMPLATE_ERR
			end
		end

		-- 提取拍照点位的uuid
		local photo_uuid = nil
		for _, point in ipairs(action.laser_point_ids or {}) do
			if point and point[1] == "Laser_Photo_Point" then
				-- uuid
				photo_uuid = point[2]
				break
			end
		end

		-- 提取拍照点位的位姿
		local photo_point = nil
		for _, point in ipairs(action.roadpoints or {}) do
			if point and point.tcp_pose and point.q then
				photo_point = point
				break
			end
		end

		-- 激光跟踪时候存储拍照点，供激光跟踪开始的时候使用
		if action.event ~= 15 and photo_uuid and photo_point then
			welding_laser.addLaserData(photo_uuid, photo_point.tcp_pose, photo_point.q)
		end

		return "", welding_common.ErrorCode.COMMON.SUCCESS

	--关闭线激光
	elseif inst_type == "LineLaser_Close" then
		if state == "raw_point_sim" then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end
		log_info(welding_common.log_prefix .. "Close laser")
		--关闭激光
		if not welding_laser.operateLaserStatus(0) then
			log_info(welding_common.log_prefix .. "Laser shutdown failed")
			return "", welding_common.ErrorCode.LINELASER.CLOSE_LASER_ERR
		end
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	--开始采集数据
	elseif inst_type == "Collect_Start" then
		log_info(welding_common.log_prefix .. "Processing Collect_Start instruction")
		local ok, tracking_err = initTrackingSession(action)
		if not ok then
			log_error(welding_common.log_prefix .. "Tracking session init failed: " .. tostring(tracking_err))
			return "", welding_common.ErrorCode.COMMON.UNKNOWN_ERROR
		end
		run(handler_laser_track_record)
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	--停止采集数据
	elseif inst_type == "Collect_Stop" then
		log_info(welding_common.log_prefix .. "Processing Collect_Stop instruction")
		kill(handler_laser_track_record)
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	elseif inst_type == "Track_Start" then
		log_info(welding_common.log_prefix .. "Processing Track_Start instruction")
		local filter_result = welding_laser.setFilter(
			action.laser_param.laser_filter_type or 0,
			action.laser_param.laser_filter_window_size or 15
		)
		if filter_result == nil then
			log_error(welding_common.log_prefix .. "Failed to set laser filter before Track_Start")
			return "", welding_common.ErrorCode.COMMON.UNKNOWN_ERROR
		end

		local max_history_result = welding_laser.setLaserTcpCacheSize(action.laser_param.laser_tcp_cache_size or 100)
		if max_history_result == nil then
			log_error(welding_common.log_prefix .. "Failed to set laser tcp cache size before Track_Start")
			return "", welding_common.ErrorCode.COMMON.UNKNOWN_ERROR
		end

		local offset_result = welding_laser.setPoseMatchOffsetTime(action.laser_param.laser_match_pose_offset_time or 0)
		if offset_result == nil then
			log_error(welding_common.log_prefix .. "Failed to set laser time offset before Track_Start")
			return "", welding_common.ErrorCode.COMMON.UNKNOWN_ERROR
		end
		run(handler_laser_track_exec)
		pathOffsetEnable()
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	elseif inst_type == "Track_Stop" then
		log_info(welding_common.log_prefix .. "Processing Track_Stop instruction")
		kill(handler_laser_track_exec)
		pathOffsetDisable()
		welding_laser.trackingDeinit()
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	elseif inst_type == "Sleep" then
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	--等待到位或识别到焊缝
	elseif inst_type == "WaitTimeoutOrFound" or inst_type == "Robot_WaitArrivalOrFound" then
		if state == "raw_point_sim" then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end
		if resume_run_state == 1 then
			if action.event == 12 then
				welding_arc.syncProgramPoint()
			elseif action.event == 14 then
				log_info(welding_common.log_prefix .. "Resume state: run explore move thread only")
				flag_laser_thread_move_5 = 0
				if handler_laser_thread_move_5 then
					run(handler_laser_thread_move_5)
					while flag_laser_thread_move_5 ~= 2 do
						sleep(0.03)
						sync()
					end
					kill(handler_laser_thread_move_5)
				end
			end
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end

		if action.event == 12 then
			welding_arc.syncProgramPoint()
			local timeout_sec = action.laser_param.laser_seek_holdtime
			welding_helpers.waitForCondition(timeout_sec)
		elseif action.event == 14 then
			log_info(welding_common.log_prefix .. "Start exploring")
			flag_laser_thread_move_5 = 0
			run(handler_laser_thread_move_5)
			local hit_0 = 0
			while flag_laser_thread_move_5 ~= 2 do
				sleep(0.03)
				if flag_laser_thread_move_5 == 1 and welding_laser.getTargetPosInDeviceValidity() == true then
					hit_0 = hit_0 + 1
				else
					hit_0 = 0
				end
				if hit_0 > 5 then
					stopLine(0.1)
					hit_0 = 0
					flag_laser_thread_move_5 = 2
					break
				end
				sync()
			end
			kill(handler_laser_thread_move_5)

			if not welding_laser.getTargetPosInDeviceValidity() then
				local timeout_sec = welding_laser.getLaserDeviceConfig().explore_waiting_time
				welding_helpers.waitForCondition(timeout_sec)
			end
		end
		--循环结束到焊缝
		if welding_laser.getTargetPosInDeviceValidity() then
			log_info(welding_common.log_prefix .. "Identified weld seam")
			welding_helpers.calculateAndAddTargetPose(action)
		else
			welding_common.showErrorMessage(welding_common.ERROR_ENUM.NO_WELD_SEAM)
			log_error(welding_common.log_prefix .. "Line laser did not identify a weld seam")
			local fallback_point_index = welding_utils.getAuboLabelComment().point_index - 1
			if fallback_point_index ~= nil then
				welding_utils.setAuboLabelPointIndex(fallback_point_index)
				log_info(welding_common.log_prefix .. "Rollback point_index to: " .. tostring(fallback_point_index))
			end
			abort()
		end
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	-- 计算交叉线
	elseif inst_type == "Calculate_Intersection" then
		if state == "raw_point_sim" then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end

		local intersection_ref_lines = action.intersection_ref_lines
		local temp_offset = welding_helpers.createCoordinateOffset(0, 0, 0, 0, 0, 0)

		local ref_line_1 = intersection_ref_lines["ref_line1"]
		local p1_uuid = ref_line_1[1]
		local p2_uuid = ref_line_1[2]

		local ref_line_2 = intersection_ref_lines["ref_line2"]
		local p3_uuid = ref_line_2[1]
		local p4_uuid = ref_line_2[2]

		local p1_point = welding_laser.getLaserData(p1_uuid).tcp_pose
		local p2_point = welding_laser.getLaserData(p2_uuid).tcp_pose
		local p3_point = welding_laser.getLaserData(p3_uuid).tcp_pose
		local p4_point = welding_laser.getLaserData(p4_uuid).tcp_pose

		log_info("========交叉计算点=======")
		log_info(welding_common.log_prefix .. welding_motion.formatPoseString(p1_point))
		log_info(welding_common.log_prefix .. welding_motion.formatPoseString(p2_point))
		log_info(welding_common.log_prefix .. welding_motion.formatPoseString(p3_point))
		log_info(welding_common.log_prefix .. welding_motion.formatPoseString(p4_point))
		log_info("==========================")

		-- 直线1
		local line1 = { p1_point, p2_point }
		-- 直线2
		local line2 = { p3_point, p4_point }
		-- 调用函数
		local coord_vector = aubo_math.buildCoordinateVector(line1, line2, temp_offset)
		log_info(welding_common.log_prefix .. "coord_vector:" .. welding_motion.formatPoseString(coord_vector))
		local q = getJointPositions()

		if action.laser_point_ids and action.laser_point_ids[1] and action.laser_point_ids[1][2] then
			welding_laser.addLaserData(action.laser_point_ids[1][2], coord_vector, q)
		else
			-- 错误处理: laser_point_ids结构不符合预期
			log_error(
				welding_common.log_prefix
					.. "Invalid action.laser_point_ids structure: cannot find UUID for data addition"
			)
		end

		if action.laser_point_ids and action.laser_point_ids[2] and action.laser_point_ids[2][2] then
			welding_laser.addLaserData(action.laser_point_ids[2][2], coord_vector, q)
			local str = string.format(
				"{%f,%f,%f,%f,%f,%f}|{%f,%f,%f,%f,%f,%f}",
				coord_vector[1],
				coord_vector[2],
				coord_vector[3],
				coord_vector[4],
				coord_vector[5],
				coord_vector[6],
				q[1],
				q[2],
				q[3],
				q[4],
				q[5],
				q[6]
			)
			popup(TraceLevel.INFO, action.laser_point_ids[2][2], str, 2001)
		end
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	--计算偏移点
	elseif inst_type == "Calculate_Offset" then
		if state == "raw_point_sim" then
			return "", welding_common.ErrorCode.COMMON.SUCCESS
		end

		local offset_ref_pts = action.offset_ref_pts

		local p1_uuid = offset_ref_pts["ref_pt1"]
		local p2_uuid = offset_ref_pts["ref_pt2"]

		local p1 = welding_laser.getLaserData(p1_uuid)
		local p2 = welding_laser.getLaserData(p2_uuid)
		log_info(welding_common.log_prefix .. "ref_pt1-uuid" .. p1_uuid)
		log_info(welding_common.log_prefix .. "ref_pt2-uuid" .. p2_uuid)

		local p1_tcp_pose = {}
		local p2_tcp_pose = {}

		if p1 then
			p1_tcp_pose = p1.tcp_pose
		else
			p1 = laser_points_db_[offset_ref_pts["ref_pt1"]]
			if p1 then
				p1_tcp_pose = p1["tcp_pose"]
			else
				log_error(welding_common.log_prefix .. "Search for offset point p1 failed")
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end
		end

		if p2 then
			p2_tcp_pose = p2.tcp_pose
		else
			p2 = laser_points_db_[offset_ref_pts["ref_pt2"]]
			if p2 then
				p2_tcp_pose = p2[tcp_pose]
			else
				log_error(welding_common.log_prefix .. "Search for offset point p2 failed")
				return "", welding_common.ErrorCode.COMMON.SUCCESS
			end
		end

		welding_config.global_offset_ = { true, p1_tcp_pose, p2_tcp_pose }
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	else
		log_info(welding_common.log_prefix .. "Unsupported instruction type:", inst_type)
		return "", welding_common.ErrorCode.COMMON.SUCCESS
	end
end

local function generateAction(data, state, sharedParams, language, enable_laser)
	local _ENV = sched.select_robot(1)
	welding_common.setMainThreadId(sched.current_thread_id())

	log_info(welding_common.log_prefix .. "==== Starting generateAction ====")
	local effective_state = state
	if effective_state == nil then
		effective_state = default_welding_options_.state
	end
	local effective_shared_params = sharedParams
	if effective_shared_params == nil then
		effective_shared_params = default_welding_options_.shared_params
	end
	local effective_language = language
	if effective_language == nil then
		effective_language = default_welding_options_.language
	end

	if effective_state == nil then
		log_error(
			welding_common.log_prefix .. "generateAction failed: welding state is nil, call initWelding or pass state"
		)
		return false, {
			error_code = 1003,
			error = "Missing welding state",
		}
	end

	-- 兼容上位机旧版本
	if enable_laser then
		-- 设置手眼数据
		local laser_config, decode_err = json.decode(_G.laser_device_config_)
		welding_laser.setLaserDeviceConfig(laser_config)
		welding_laser.connectDevice(welding_laser.getLaserDeviceConfig())
	end

	welding_common.language = effective_language or "en"

	local action_command, err = json.decode(data)
	if not action_command then
		log_error(welding_common.log_prefix .. "JSON decode failed:", err)
		return false, {
			error_code = 1001,
			error = "JSON decode failed: " .. tostring(err),
		}
	end

	local instructions = action_command[1]
	laser_points_db_ = action_command[2]

	log_info(welding_common.log_prefix .. "Decoded instructions count:", #instructions)

	-- 状态验证
	if
		not (
			effective_state == "raw_path_weld"
			or effective_state == "raw_path_sim"
			or effective_state == "raw_point_sim"
		)
	then
		log_error(welding_common.log_prefix .. "Incorrect running status :" .. tostring(effective_state))
		return false, {
			error_code = 1002,
			error = "Invalid welding state",
		}
	end

	-- 每次生成指令前刷新当前运行模式，避免恢复状态机使用陈旧状态。
	if welding_resume.setCurrentProgramState then
		welding_resume.setCurrentProgramState(effective_state)
	end

	-- 设置默认参数
	local params = {
		motion_parameters = {
			joint_acc = effective_shared_params and effective_shared_params.joint_acc,
			joint_speed = effective_shared_params and effective_shared_params.joint_speed,
			tool_acc = effective_shared_params and effective_shared_params.tool_acc,
			tool_speed = effective_shared_params and effective_shared_params.tool_speed,
		},
		blend_radius = effective_shared_params and effective_shared_params.blend_radius,
		offset_distance = effective_shared_params and effective_shared_params.offset_distance,
		back_off_distance = effective_shared_params and effective_shared_params.back_off_distance,
	}

	local results = {}
	local collected_instructions = {} -- 用于存储收集到的指令
	local is_collecting = false -- 标记是否正在收集

	-- 处理每条指令
	for i, instr in ipairs(instructions) do
		-- 结构验证
		if not (instr.type_ and instr.action_) then
			log_info(welding_common.log_prefix .. "Missing type_ or action_ in instruction", i)
			return false,
				{
					error_code = 2001,
					error = "Missing type_ or action_ field",
					instruction_index = i,
				}
		end

		--多道开始
		if instr.action_.event == 8 then
			welding_arc.syncProgramPoint()
			is_collecting = true
			collected_instructions = {} -- 清空之前的收集结果
			table.insert(collected_instructions, instr)
			goto continue -- 跳过当前指令的后续处理
		end

		-- 多道结束
		if instr.action_.event == 9 then
			if is_collecting then
				table.insert(collected_instructions, instr)
				is_collecting = false

				log_info(welding_common.log_prefix .. "Start multiple paths")
				welding_arc.syncProgramPoint()
				welding_multipass.multiProcessProcessing(collected_instructions, params, effective_state)
				log_info(welding_common.log_prefix .. "End multiple paths")
				-- 跳过后续处理
				goto continue
			else
				log_error(welding_common.log_prefix .. "Found MultiLayerClosure without matching startup", i)
				return false,
					{
						error_code = 2002,
						error = "MultiLayerClosure without matching startup",
						instruction_index = i,
					}
			end
		end

		-- 如果正在收集，则添加到收集列表
		if is_collecting then
			table.insert(collected_instructions, instr)
			goto continue -- 跳过当前指令的后续处理
		end

		-- 获取前后action数据
		local instr = instructions[i]
		if not instr then
			return
		end -- 当前指令不存在，直接返回

		-- 当前指令的 action 和 event
		local current_action = instr.action_
		local current_event = current_action and current_action.event or nil

		-- 前后指令的 action
		local prev_action = (i > 1) and instructions[i - 1].action_ or nil
		local next_action = (i < #instructions) and instructions[i + 1].action_ or nil

		-- 是否在序列开始/结束（无前/后指令）
		local is_at_start = (prev_action == nil)
		local is_at_end = (next_action == nil)

		-- 当前是否是焊接动作（直线1、圆弧2、包角18）
		local is_welding_action = (current_event == 1 or current_event == 2 or current_event == 18)

		-- 前一个指令是否为非焊接动作（或不存在）
		local is_prev_non_welding = is_at_start
			or (prev_action and (prev_action.event ~= 1 and prev_action.event ~= 2 and prev_action.event ~= 18))

		-- 后一个指令是否为非焊接动作（或不存在）
		local is_next_non_welding = is_at_end
			or (next_action and (next_action.event ~= 1 and next_action.event ~= 2 and next_action.event ~= 18))

		-- 最终判断：当前是焊接动作，且前后至少有一个是非焊接或边界 → 是焊接端点
		local is_welding_endpoints = is_welding_action and (is_prev_non_welding or is_next_non_welding)

		log_info(welding_common.log_prefix .. "Is_welding_endpoints", is_welding_endpoints)

		-- 打印指令列表
		for subIdx, inst_type in ipairs(instr.type_) do
			local context = {
				prev_action = prev_action,
				next_action = next_action,
				instructionIndex = i,
				subInstructionIndex = subIdx,
			}
			log_info(welding_common.log_prefix .. "++++++++++指令序列:", inst_type)
		end
		-- 处理子指令序列
		for subIdx, inst_type in ipairs(instr.type_) do
			local context = {
				prev_action = prev_action,
				next_action = next_action,
				instructionIndex = i,
				subInstructionIndex = subIdx,
			}

			local cmd, err =
				processInstruction(inst_type, instr.action_, params, effective_state, context, is_welding_endpoints)

			if err and err ~= welding_common.ErrorCode.COMMON.SUCCESS then
				log_error(welding_common.log_prefix .. "Instruction processing failed:", err)
				return false,
					{
						error_code = 3000 + (welding_types.MetaInstructionType[inst_type] or 0),
						error = err,
						instruction_index = i,
						sub_instruction_index = subIdx,
					}
			end

			if cmd then
				table.insert(results, {
					seq = i,
					sub_seq = subIdx,
					type = inst_type,
					command = cmd,
					timestamp = os.time(),
				})
			else
				log_error(welding_common.log_prefix .. "No command generated for instruction type:", inst_type)
			end
		end
		::continue::
	end

	log_info(welding_common.log_prefix .. "Generated commands count:" .. #results)
	return true,
		{
			state = effective_state,
			commands = results,
			motion_parameters = params.motion_parameters,
			process_parameters = {
				offset_distance = params.offset_distance,
				blend_radius = params.blend_radius,
			},
			start_time = os.time(),
			end_time = os.time(),
		}
end

-- 暂不删除兼容旧版上位机(后续考虑移除)
local function emergencyStopArcExtinguishing()
	welding_arc.stopArc(true)
end

local function onProgramStop(is_normal)
	program_normal_stop = is_normal

	welding_resume.onProgramStop(program_normal_stop)
	if not program_normal_stop then
		welding_arc.stopArc(true)
	end
	stopLabelCacheThread()
end

local function onProgramPause()
	welding_resume.onProgramPause()
	welding_arc.stopArc(true)
end

function getProgramNormalStopState()
	return program_normal_stop
end

-- 核心功能相关
M.initWelding = initWelding
M.generateAction = generateAction
M.emergencyStopArcExtinguishing = emergencyStopArcExtinguishing
M.onProgramStop = onProgramStop
M.onProgramPause = onProgramPause
M.getProgramNormalStopState = getProgramNormalStopState
M.getCachedAuboLabelComment = getCachedAuboLabelComment

return M
