#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
机器人调度处理器模块
提供与机器人调度操作相关的各种处理器
"""

import json
import asyncio
import aiohttp
import uuid
from typing import Dict, Any, List, Optional
from services.execution.task_context import TaskContext
from .base import BlockHandler, register_handler
from config.settings import settings
from utils.logger import get_logger
from .model.block_name import RobotBlockName
from typing import Tuple

# 获取日志记录器
logger = get_logger("services.execution.handlers.robot_scheduling")

# 提取公共的API调用函数
# async def call_robot_api(api_name: str, params: Dict[str, Any]) -> Dict[str, Any]:
#     """
#     调用机器人调度服务API的通用函数
    
#     Args:
#         api_name: API名称，对应API_ENDPOINTS中的键
#         params: API参数
        
#     Returns:
#         API响应结果
#     """
#     # 获取API端点和方法
#     endpoint = settings.ROBOT_API_ENDPOINTS.get(api_name)
#     method = settings.ROBOT_API_METHODS.get(api_name)
    
#     if not endpoint or not method:
#         logger.error(f"未找到API端点或方法：{api_name}")
#         return {
#             "success": False,
#             "message": f"未找到API配置: {api_name}"
#         }

        
#     # 构建完整的URL
#     url = f"{settings.ROBOT_API_BASE_URL}{endpoint}"
    
#     # 准备请求头
#     headers = {"Content-Type": "application/json"}
#     if settings.ROBOT_API_TOKEN:
#         headers["Authorization"] = f"Bearer {settings.ROBOT_API_TOKEN}"
        
#     logger.debug(f"调用外部API {api_name} - {method} {url}, 参数: {params}")
    
#     try:
#         async with aiohttp.ClientSession() as session:
#             # 根据HTTP方法选择相应的请求方式
#             if method == "GET":
#                 # 对于GET请求，将params转换为URL参数
#                 async with session.get(
#                     url, 
#                     params=params, 
#                     headers=headers, 
#                     timeout=settings.ROBOT_API_TIMEOUT
#                 ) as response:
#                     result = await response.json()
#             elif method == "POST":
#                 # 对于POST请求，将params作为JSON数据发送
#                 async with session.post(
#                     url, 
#                     json=params, 
#                     headers=headers, 
#                     timeout=settings.ROBOT_API_TIMEOUT
#                 ) as response:
#                     result = await response.json()
#             elif method == "PUT":
#                 # 对于PUT请求，将params作为JSON数据发送
#                 async with session.put(
#                     url, 
#                     json=params, 
#                     headers=headers, 
#                     timeout=settings.ROBOT_API_TIMEOUT
#                 ) as response:
#                     result = await response.json()
#             else:
#                 logger.error(f"不支持的HTTP方法: {method}")
#                 return {
#                     "success": False,
#                     "message": f"不支持的HTTP方法: {method}"
#                 }
                
#             # 检查响应状态码
#             if response.status != 200:
#                 logger.error(f"API调用失败: {url}, 状态码: {response.status}, 响应: {result}")
#                 return {
#                     "success": False,
#                     "message": f"API调用失败, 状态码: {response.status}",
#                     "data": result
#                 }
            
#             logger.debug(f"API调用成功: {url}, 响应: {result}")
#             return result
            
#     except aiohttp.ClientError as e:
#         logger.error(f"API调用客户端错误: {url}, 错误: {str(e)}")
#         return {
#             "success": False,
#             "message": f"API调用客户端错误: {str(e)}"
#         }
#     except asyncio.TimeoutError:
#         logger.error(f"API调用超时: {url}")
#         return {
#             "success": False,
#             "message": "API调用超时"
#         }
#     except json.JSONDecodeError:
#         logger.error(f"API响应解析失败: {url}")
#         return {
#             "success": False,
#             "message": "API响应格式错误，无法解析JSON"
#         }
#     except Exception as e:
#         logger.error(f"API调用异常: {url}, 错误: {str(e)}")
#         return {
#             "success": False,
#             "message": f"API调用异常: {str(e)}"
#         }


class RobotBlockHandler(BlockHandler):
    """机器人调度处理器基类，提供公共的API调用方法"""

    async def _validate_and_convert_key_route(self, key_route: str, map_id: str, flag: bool = False) -> tuple[bool, str, str, bool]:
        """
        校验并转换keyRoute参数

        Args:
            key_route: 传入的关键路径，可能是动作点名称或库位名称
            map_id: 地图ID，用于校验场景ID
            
        Returns:
            tuple: (是否成功, 最终的station_name, 错误消息)
        """
        try:
            from sqlalchemy.ext.asyncio import AsyncSession
            from data.session import get_async_session
            from data.models.operate_point import OperatePoint
            from data.models.operate_point_layer import OperatePointLayer
            from sqlalchemy import select
            
            async with get_async_session() as session:
                session: AsyncSession = session
                
                # 首先检查是否是动作点（operate_point表的station_name字段）
                stmt = select(OperatePoint).where(
                    OperatePoint.station_name == key_route,
                    OperatePoint.is_disabled == False,
                    OperatePoint.scene_id == map_id
                )
                result = await session.execute(stmt)
                operate_point = result.scalar_one_or_none()
                # print(operate_point, "=============")
                if operate_point:
                    logger.debug(f"keyRoute '{key_route}' 识别为动作点，场景ID: {map_id}")
                    return True, key_route, "", True
                
                # 如果不是动作点，检查是否是库位（operate_point_layer表的layer_name字段）
                # print("key_route:::::::::", key_route, "=======================", "map_id:::", map_id)
                stmt = select(OperatePointLayer).where(
                    OperatePointLayer.layer_name == key_route,
                    OperatePointLayer.is_disabled == False,
                    OperatePointLayer.scene_id == map_id
                )
                # print(stmt.params())
                result = await session.execute(stmt)
                # print(result.fetchall())
                operate_point_layer = result.scalar_one_or_none()
                
                if operate_point_layer:
                    station_name = operate_point_layer.station_name
                    logger.debug(f"keyRoute '{key_route}' 识别为库位，对应的动作点: {station_name}，场景ID: {map_id}")
                    return True, station_name, "", False
                if flag:
                    return True, key_route, "", True
                return True, key_route, "", False

        except Exception as e:
            error_msg = f"校验keyRoute时发生异常: {str(e)}"
            logger.error(error_msg)
            return False, "", error_msg, True
        
    def _analyze_affected_blocks(self, block: Dict[str, Any], current_block_id: str, current_block_name: str) -> List[Dict[str, Any]]:
        """
        分析当前块的结构，找出受当前选择机器人块影响的所有下级块
        
        Args:
            block: 当前块的定义
            current_block_id: 当前块的ID
            current_block_name: 当前块的名称
            
        Returns:
            List[Dict[str, Any]]: 受影响的块列表，每个元素包含块的ID、名称、类型和与当前块的关系
        """
        affected_blocks = []
        
        # 检查当前块是否有子块
        if "children" in block and "default" in block["children"]:
            children = block["children"]["default"]
            logger.debug(f"块 {current_block_name}(ID:{current_block_id}) 有 {len(children)} 个子块")
            
            # 分析每个子块
            for child in children:
                child_id = child.get("id", "unknown")
                child_name = child.get("name", f"b{child_id}")
                child_type = child.get("blockType", "unknown")
                
                # 记录子块信息
                affected_blocks.append({
                    "id": child_id,
                    "name": child_name,
                    "type": child_type,
                    "relation": "direct_child",
                    "parent_id": current_block_id,
                    "parent_name": current_block_name
                })
                
                # 如果子块不是CSelectAgvBp类型，则继续分析其子块
                # 如果子块是CSelectAgvBp类型，则停止分析该分支，因为该分支将由子块的CSelectAgvBp负责
                if child_type != "CSelectAgvBp" and "children" in child and "default" in child["children"]:
                    # 递归分析子块的子块
                    nested_affected = self._analyze_affected_blocks(child, child_id, child_name)
                    
                    # 将所有嵌套子块添加到结果中
                    for nested_block in nested_affected:
                        # 添加到结果列表中，标记为嵌套关系
                        nested_block["relation"] = "nested_child"
                        affected_blocks.append(nested_block)
        
        return affected_blocks
        
    def _get_robot_id_for_block(self, block_id: str, block_name: str, context: TaskContext) -> Tuple[Optional[str], Optional[str]]:
        """
        获取适用于当前块的机器人ID
        
        首先检查是否有专门为该块设置的机器人ID变量
        如果没有则尝试获取全局机器人ID
        
        Args:
            block_id: 当前块ID
            block_name: 当前块名称
            context: 任务上下文
            
        Returns:
            Optional[str]: 机器人ID，如果没有找到则返回None
        """
        # 首先检查是否有专门为该块设置的机器人ID
        robot_id = context.get_variable(f"agv_for_block_{block_id}")
        agv_task_id = context.get_variable(f"agv_task_id_{block_id}")
        if robot_id:
            logger.debug(f"找到块 {block_name}(ID:{block_id}) 专用的机器人ID: {robot_id}")
            return robot_id, agv_task_id
            
        # 检查是否有按名称设置的机器人ID
        robot_id = context.get_variable(f"agv_for_{block_name}")
        if robot_id:
            logger.debug(f"找到块 {block_name} 专用的机器人ID: {robot_id}")
            return robot_id, agv_task_id
            
        # 如果没有专用设置，尝试获取全局机器人ID
        robot_id = context.get_variable("selectedAgvId")
        if robot_id:
            logger.debug(f"使用全局机器人ID: {robot_id} 用于块 {block_name}(ID:{block_id})")
            return robot_id, agv_task_id
            
        # 如果仍未找到，尝试从所有块输出中查找最近的selectedAgvId
        # 这是兜底策略，保持向后兼容
        for out_block_name, outputs in context.block_outputs.items():
            if isinstance(outputs, dict) and "selectedAgvId" in outputs:
                robot_id = outputs.get("selectedAgvId")
                logger.debug(f"从块 {out_block_name} 输出中获取机器人ID: {robot_id} 用于块 {block_name}(ID:{block_id})")
                return robot_id, agv_task_id
                
        # 未找到任何机器人ID
        # logger.warning(f"未找到块 {block_name}(ID:{block_id}) 可用的机器人ID")
        return None, None
    
    async def _update_task_record_agv_id(self, task_record_id: str, amr_id: str) -> None:
        """
        更新任务记录中的agv_id字段
        
        Args:
            task_record_id: 任务记录ID
            amr_id: 机器人ID
            
        Returns:
            None
        """
        try:
            from sqlalchemy.ext.asyncio import AsyncSession
            from data.session import get_async_session
            from data.models.taskrecord import VWEDTaskRecord
            from sqlalchemy import select, update
            
            if not amr_id:
                logger.warning(f"未提供AMR ID，无法更新任务记录 {task_record_id}")
                return
                
            # 将多个AMR ID用逗号连接
            logger.debug(f"准备更新任务 {task_record_id} 的机器人ID: {amr_id}")
            
            # 先查询当前任务记录中是否已有agv_id
            async with get_async_session() as session:
                session: AsyncSession = session
                
                # 查询当前记录
                stmt = select(VWEDTaskRecord.agv_id).where(VWEDTaskRecord.id == task_record_id)
                result = await session.execute(stmt)
                current_agv_id = result.scalar_one_or_none()
                
                # 确定最终要存储的agv_id值
                if current_agv_id:
                    # 如果已经有值，需要合并并去重
                    logger.debug(f"任务 {task_record_id} 当前已存在的机器人IDs: {current_agv_id}")
                    current_ids = current_agv_id.split(",")
                    all_ids = current_ids + [amr_id]
                    # 去重并过滤空值
                    unique_ids = list(set([id for id in all_ids if id]))
                    final_agv_id = ",".join(unique_ids)
                    logger.debug(f"合并后的机器人IDs: {final_agv_id}")
                else:
                    final_agv_id = amr_id
                
                # 更新记录
                stmt = update(VWEDTaskRecord).where(VWEDTaskRecord.id == task_record_id).values(agv_id=final_agv_id)
                await session.execute(stmt)
                await session.commit()
                
                logger.info(f"成功更新任务记录 {task_record_id} 的agv_id字段: {final_agv_id}")
        except Exception as e:
            logger.error(f"更新任务记录 {task_record_id} 的agv_id字段时发生错误: {str(e)}")
    async def update_block_record(self, block_record_id: str, agv_id: str = None) -> None:
        """
        更新块记录的通用方法
        
        Args:
            block_record_id: 块记录ID
            status: 状态码
            message: 消息
        """
        try:
            from sqlalchemy.ext.asyncio import AsyncSession
            from data.session import get_async_session
            from data.models.blockrecord import VWEDBlockRecord
            from sqlalchemy import select, update
            from data.enum.task_block_record_enum import TaskBlockRecordStatus
            if not block_record_id:
                logger.warning(f"未提供块记录ID，无法更新块记录")
                return
            stmt = update(VWEDBlockRecord).where(VWEDBlockRecord.id == block_record_id).values(
                status=TaskBlockRecordStatus.SUCCESS,
                ended_reason="执行成功",
                remark="执行成功"
            )
            async with get_async_session() as session:
                session: AsyncSession = session
                await session.execute(stmt)
                await session.commit()
        except Exception as e:
            logger.error(f"更新块记录 {block_record_id} 时发生错误: {str(e)}")

# 机器人通用动作处理器
@register_handler(RobotBlockName.AGV_OPERATION)
class AgvOperationBlockHandler(RobotBlockHandler):
    """机器人通用动作处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """执行机器人通用动作操作"""
        from services.sync_service import wait_for_task_block_action_completion
        try:
            
            # 获取关键参数用于验证
            target_site_label = input_params.get("targetSiteLabel")
            script_name = input_params.get("task", "Wait")
            map_id = context.map_id
            param = input_params.get("param", "")
            inspired_unique = input_params.get("inspired_unique", "")
            unique_file = input_params.get("unique_file", "")
            targetHeight = input_params.get("targetHeight", "")
            params = {}
            if param.strip():
                params["param"] = param
            if inspired_unique.strip():
                params["inspired_unique"] = inspired_unique
            if unique_file.strip():
                params["unique_file"] = unique_file
            if targetHeight.strip():
                params["targetHeight"] = targetHeight
            # 参数检查
            if not target_site_label:
                result = {
                    "success": False,
                    "message": "目标站点名不能为空"
                }
                await self._record_task_log(block, result, context)
                return result

            # 校验并转换target_site_label参数
            is_valid, validated_station_name, error_msg, is_type = await self._validate_and_convert_key_route(target_site_label, map_id)

            # 获取当前块信息
            current_block_id = block.get("id", "unknown")
            current_block_name = block.get("name", f"b{current_block_id}")
            
            # 如果没有提供，尝试获取适用于当前块的机器人ID
            vehicle, agv_task_id = self._get_robot_id_for_block(current_block_id, current_block_name, context)
            if vehicle:
                # 设置到输入参数中
                input_params["vehicle"] = vehicle
            
            # 记录使用的机器人ID
            if vehicle:
                logger.debug(f"执行机器人通用动作，块 {current_block_name}(ID:{current_block_id}) 使用机器人: {vehicle}, 目标站点: {validated_station_name} (原始输入: {target_site_label})")
            else:
                error_msg = f"执行机器人通用动作失败：未指定机器人ID，目标站点: {validated_station_name}"
                logger.error(error_msg)
                result = {
                    "success": False,
                    "message": error_msg
                }
                await self._record_task_log(block, result, context)
                return result
            # context.task_record_id
            from services.sync_service import add_action
            # result = {}
            if is_type:
                result = await add_action(
                    task_id=agv_task_id,
                    station_name=validated_station_name,  # 使用校验后的站点名称
                    action=script_name,
                    token=context.token,
                    param=params,
                    store="",
                )
            else:
                result = await add_action(
                    task_id=agv_task_id,
                    station_name=validated_station_name,  # 使用校验后的站点名称
                    action=script_name,
                    token=context.token,
                    param=params,
                    store=target_site_label)

            # 调用外部API执行机器人通用动作
            if result.get("success", False):
                # 获取任务ID
                task_id = result.get("result", {}).get("id", "")
                task_block_result = await wait_for_task_block_action_completion(task_id, context.token, context)
                # result =
                if task_block_result.get("is_canceled", False):
                    # result = task_block_result
                    # await self._record_task_log(block, result, context)

                    return {"success": True, "message": f"机器人通用动作取消，目标站点: {validated_station_name} 执行动作: {script_name}，块id：{current_block_name}", "is_canceled": True}
                if task_block_result.get("is_failed", False):
                    await self._record_task_log(block, task_block_result, context)
                    return {"success": False, "is_failed": True, "message": task_block_result.get("message", "")}
                    # return result
                if task_block_result.get("success", False):
                    task_block_status = task_block_result.get("result", {}).get("status", "")
                    if task_block_status == 3:
                        result["message"] = f"机器人通用动作成功，目标站点: {validated_station_name} 执行动作: {script_name}，块id：{current_block_name}"
                    elif task_block_status == 4:
                        result["message"] = f"机器人通用动作失败，目标站点: {validated_station_name} 执行动作: {script_name}:{task_block_result.get('message', '')}，块id：{current_block_name}"
                        result["success"] = False
                    elif task_block_status == 5:
                        result["message"] = f"机器人通用动作终止，目标站点: {validated_station_name} 执行动作: {script_name}，块id：{current_block_name}"
            else:
                result["message"] = f"机器人通用动作失败: {result.get('message', '未知错误')}，块id：{current_block_name}"
            # print("result::", result, "==============================")
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"机器人通用动作执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

# 获取机器人位置处理器
@register_handler(RobotBlockName.VEHICLE_STATION)
class VehicleStationBlockHandler(RobotBlockHandler):
    """获取机器人位置处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """执行获取机器人位置操作"""
        try:
            from services.sync_service import get_amr_info
            
            # 获取关键参数用于验证
            vehicle = input_params.get("vehicle")
            
            # 参数检查
            if not vehicle:
                result = {
                    "success": False,
                    "message": "指定机器人不能为空 "
                }
                await self._record_task_log(block, result, context)
                return result

            # 调用AMR信息接口获取机器人位置
            amr_info_result = await get_amr_info(token=context.token)
            
            # if amr_info_result and amr_info_result.get("success", False):
                # 获取AMR列表
            amr_list = amr_info_result.get("result", [])

            # 根据机器人名称查找对应的AMR信息
            target_amr = None
            for amr in amr_list:
                if amr.get("name") == vehicle:
                    target_amr = amr
                    break

            if target_amr:
                # 获取机器人位置信息
                last_node_id = target_amr.get("lastNodeId", "")

                # 设置上下文变量
                context.set_variable("station", last_node_id)
                context.set_variable("lastStation", last_node_id)
                context.set_block_output(block.get("name"), {
                    "station": last_node_id,
                    "lastStation": last_node_id
                })

                result = {
                    "success": True,
                    "message": f"获取机器人 {vehicle} 位置成功，当前位置: {last_node_id}"
                }
            else:
                result = {
                    "success": False,
                    "message": f"未找到名称为 {vehicle} 的机器人"
                }
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"获取机器人位置执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

# 获取机器人电量处理器
@register_handler(RobotBlockName.GET_BATTERY_LEVEL)
class GetBatteryLevelBlockHandler(RobotBlockHandler):
    """获取机器人电量处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """执行获取机器人电量操作"""
        try:
            from services.sync_service import get_amr_info
            
            # 获取关键参数用于验证
            vehicle = str(input_params.get("vehicle")).strip()
            
            # 参数检查
            if not vehicle:
                result = {
                    "success": False,
                    "message": "机器人名称不能为空"
                }
                await self._record_task_log(block, result, context)
                return result

            # 调用AMR信息接口获取机器人电量
            amr_info_result = await get_amr_info(token=context.token)
            
            # if amr_info_result and amr_info_result.get("success", False):
            #     # 获取AMR列表
            amr_list = amr_info_result.get("result", [])
            # print(amr_list, "==")
            # print(vehicle, "====")
            # 根据机器人名称查找对应的AMR信息
            target_amr = None
            for amr in amr_list:
                if amr.get("name") == vehicle:
                    target_amr = amr
                    break

            if target_amr:
                # 获取机器人电量信息
                battery_level = target_amr.get("batteryLevel", 0.0)

                # 设置上下文变量
                context.set_variable("batteryLevel", battery_level)
                context.set_block_output(block.get("name"), {"batteryLevel": battery_level})

                # 格式化电量为百分比
                battery_percent = f"{battery_level}"
                result = {
                    "success": True,
                    "message": f"获取机器人 {vehicle} 电量成功，当前电量: {battery_percent}"
                }
            else:
                result = {
                    "success": False,
                    "message": f"未找到名称为 {vehicle} 的机器人"
                }
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"获取机器人电量执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

# 获取机器人PGV码处理器
@register_handler(RobotBlockName.GET_PGV_CODE)
class GetPGVCodeBlockHandler(RobotBlockHandler):
    """获取机器人PGV码处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """执行获取机器人PGV码操作"""
        try:
            # 获取关键参数用于验证
            vehicle = input_params.get("vehicle")
            
            # 参数检查
            if not vehicle:
                result = {
                    "success": False,
                    "message": "机器人ID不能为空"
                }
                await self._record_task_log(block, result, context)
                return result

            # 调用外部API获取机器人PGV码
            result = {}
            if result.get("success", False):
                # 获取PGV码信息
                code_info = result.get("data", {}).get("codeInfo", False)
                
                # 设置上下文变量
                context.set_variable("codeInfo", code_info)
                context.set_block_output(block.get("name"), {"codeInfo": code_info})
                
                code_status = "有效" if code_info else "无效"
                result["message"] = f"获取机器人 {vehicle} PGV码成功，二维码信息: {code_status}"
            else:
                result["message"] = f"获取机器人PGV码失败: {result.get('message', '未知错误')}"
            
            # 记录执行结果
            await self._record_task_log(block, result, context)
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"获取机器人PGV码执行异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result

# 选择执行机器人处理器
@register_handler(RobotBlockName.SELECT_AGV)
class SelectAgvBlockHandler(RobotBlockHandler):
    """选择执行机器人处理器"""
    
    async def execute(
        self, 
        block: Dict[str, Any],
        input_params: Dict[str, Any],
        context: TaskContext
    ) -> Dict[str, Any]:
        """执行选择机器人操作"""
        try:
            # print("block:::::::::::", block)
            # 获取关键参数用于验证
            key_route = input_params.get("keyRoute")
            priority = input_params.get("priority", 1)
            amr_name = input_params.get("vehicle", "")
            amr_group_name = input_params.get("group", "")
            amr_label_group = input_params.get("label_group", "")
            map_id = context.map_id
            # 获取当前块信息
            current_block_id = block.get("id", "unknown")
            current_block_name = block.get("name", f"b{current_block_id}")
            # 确保priority是整数类型，默认为1
            try:
                priority = int(priority) if priority and str(priority).strip() else 1
            except (ValueError, TypeError):
                priority = 1

            # 确保字符串参数不为None，并进行类型校验
            amr_name = amr_name or ""

            # 校验amr_group_name，确保是列表格式
            if amr_group_name:
                if isinstance(amr_group_name, str):
                    # 如果是字符串，尝试解析为JSON列表
                    try:
                        amr_group_name = json.loads(amr_group_name) if amr_group_name.strip() else []
                    except (json.JSONDecodeError, ValueError):
                        # 如果解析失败，按逗号分割
                        amr_group_name = [name.strip() for name in amr_group_name.split(",") if name.strip()]
                elif not isinstance(amr_group_name, list):
                    result = {
                        "success": False,
                        "message": f"指定机器人组参数格式错误，必须是列表类型, 块id：{current_block_name}"
                    }
                    await self._record_task_log(block, result, context)
                    return result
            else:
                amr_group_name = []

            # 校验amr_label_group，确保是列表格式
            if amr_label_group:
                if isinstance(amr_label_group, str):
                    # 如果是字符串，尝试解析为JSON列表
                    try:
                        amr_label_group = json.loads(amr_label_group) if amr_label_group.strip() else []
                    except (json.JSONDecodeError, ValueError):
                        # 如果解析失败，按逗号分割
                        amr_label_group = [label.strip() for label in amr_label_group.split(",") if label.strip()]
                elif not isinstance(amr_label_group, list):
                    result = {
                        "success": False,
                        "message": f"指定机器人标签组参数格式错误，必须是列表类型, 块id：{current_block_name}"
                    }
                    await self._record_task_log(block, result, context)
                    return result
            else:
                amr_label_group = []

            # 参数检查
            if not key_route:
                result = {
                    "success": False,
                    "message": f"关键路径不能为空, 块id：{current_block_name}"
                }
                await self._record_task_log(block, result, context)
                return result

            # 校验并转换keyRoute参数
            is_valid, key_station_name, error_msg, is_type = await self._validate_and_convert_key_route(key_route, map_id, flag=True)
            if not is_valid:
                result = {
                    "success": False,
                    "message": error_msg
                }
                await self._record_task_log(block, result, context)
                return result

            # 调用外部API选择执行机器人
            from services.sync_service import create_choose_amr_task, wait_for_amr_selection
            result = await create_choose_amr_task(
                task_id=context.task_record_id,
                key_station_name=key_station_name,  # 使用校验后的station_name
                amr_name=amr_name,
                amr_group_name=amr_group_name,
                amr_label_group=amr_label_group,
                token=context.token,
                priority=priority
            )
            if result.get("success", False):
                # 获取任务块ID
                task_block_id = result.get("result", {}).get("id", "")
                
                if not task_block_id:
                    result = {
                        "success": False,
                        "message": f"创建选择AMR任务成功，但未返回任务块ID, 块id：{current_block_name}"
                    }
                    await self._record_task_log(block, result, context)
                    return result
                
                logger.debug(f"开始等待任务块 {task_block_id} 的AMR选择结果")
                
                # 等待AMR选择完成
                task_block_result = await wait_for_amr_selection(
                    task_block_id=task_block_id,
                    token=context.token,
                    context=context
                )

                if task_block_result.get("is_canceled", False):
                    return {"success": True, "message": f"选择执行机器人取消, 块id：{current_block_name}", "is_canceled": True}
                if not task_block_result or not task_block_result.get("success", False):
                    result = {
                        "success": False,
                        "message": task_block_result.get("message", "")
                    }
                    await self._record_task_log(block, result, context)
                    return result
                
                # 获取选出的机器人ID
                agv_id = task_block_result.get("result", {}).get("amrId", "")
                amr_name = task_block_result.get("result", {}).get("amrName", "")
                if not agv_id:
                    result = {
                        "success": False,
                        "message": f"未能获取到选择的AMR ID，任务块ID: {task_block_id}, 块id：{current_block_name}"
                    }
                    await self._record_task_log(block, result, context)
                    return result
                results = {
                    "success": True,
                    "message": f"选择机器人块成功, 块id：{current_block_name}",
                    "output": {
                        "selectedAgvId": amr_name,
                    }
                }
                await self._record_task_log(block, results, context)
                # 更新块记录状态为成功
                await self.update_block_record(context.block_record_id, amr_name)
                
                # 获取当前块ID和名称
                current_block_id = block.get("id", "unknown")
                current_block_name = block.get("name", f"b{current_block_id}")
                # 更新任务记录中的agv_id字段
                await self._update_task_record_agv_id(context.task_record_id, amr_name)

                logger.debug(f"选择机器人块 {current_block_name}(ID:{current_block_id}) 选择的机器人: {amr_name}")
                
                # 分析块的层级结构并记录关联关系
                affected_blocks = self._analyze_affected_blocks(block, current_block_id, current_block_name)
                
                # 将分析结果记录到日志
                logger.debug(f"选择机器人块 {current_block_name} 影响的块ID: {[b['id'] for b in affected_blocks]}")
                context.set_block_output(current_block_name, {"selectedAgvId": amr_name})

                # 为每个受影响的块设置变量，记录它应该使用的机器人ID
                for affected_block in affected_blocks:
                    affected_id = affected_block["id"]
                    affected_name = affected_block["name"]
                    context.set_variable(f"agv_for_block_{affected_id}", agv_id)
                    context.set_variable(f"agv_for_{affected_name}", agv_id)
                    context.set_variable(f"agv_task_id_{affected_id}", task_block_id)
                    context.set_block_output(affected_name, {"selectedAgvId": amr_name})
                                
                # 构造成功消息
                vehicle = input_params.get("vehicle", "")
                group = input_params.get("group", "")
                tag = input_params.get("tag", "")
                
                if vehicle:
                    result["message"] = f"指定机器人 {vehicle} 选择成功, 块id：{current_block_name}"
                elif group:
                    result["message"] = f"从机器人组 {group} 选择机器人成功: {amr_name}, 块id：{current_block_name}"
                elif tag:
                    result["message"] = f"根据标签 {tag} 选择机器人成功: {amr_name}, 块id：{current_block_name}"
                else:
                    result["message"] = f"选择执行机器人成功: {amr_name}, 块id：{current_block_name}"
                
                # 打印选择结果和影响的块
                logger.debug(f"选择机器人块 {current_block_name}(ID:{current_block_id}) 选择的机器人: {amr_name}")
                logger.debug(f"影响的块: {len(affected_blocks)} 个")
                for i, b in enumerate(affected_blocks):
                    logger.debug(f"{i+1}. {b['name']}(ID:{b['id']}, 类型:{b['type']}, 关系:{b['relation']})")
                
                from services.execution.block_executor import BlockExecutor
                executor = BlockExecutor(context)
                
                # 检查是否有子块需要执行
                has_children = "children" in block and "default" in block.get("children", {}) and len(block.get("children", {}).get("default", [])) > 0
                
                if has_children:
                    # 执行子块
                    logger.debug(f"开始执行选择机器人块 {current_block_name} 的子块")
                    loop_result = await executor.execute_children(block, "default")
                    
                    # 处理子块执行结果
                    if loop_result.get("success", False):
                        # 子块执行成功，合并结果
                        logger.debug(f"选择机器人块 {current_block_name} 的子块执行成功")
                        
                        # 如果有需要合并的输出数据
                        child_results = loop_result.get("output", {}).get("results", [])
                        result["childBlockResults"] = child_results
                        
                        # 保持成功状态
                        result["success"] = True
                        result["output"] = {
                            "selectedAgvId": amr_name,
                            "childrenExecuted": True,
                        }
                        
                        # 如果原始消息中没有包含子块执行信息，添加这部分信息
                        if "子块" not in result["message"]:
                            result["message"] = f"{result['message']}，子块执行成功, 块id：{current_block_name}"
                    else:
                        # 子块执行失败，根据失败的子块更新消息
                        logger.error(f"选择机器人块 {current_block_name} 的子块执行失败: {loop_result.get('message')}")
                        
                        # 创建包含子块失败信息的结果
                        error_msg = loop_result.get("message", "未知错误")
                        failed_block_id = loop_result.get("block_id", "unknown")
                        
                        result = {
                            "success": False,
                            "message": f"选择执行机器人成功 选择小车：{amr_name}，但子块执行失败: {error_msg}，失败块ID: {failed_block_id}",
                            "output": {
                                "selectedAgvId": amr_name,
                                "childrenExecuted": False,
                            }
                        }
                # 记录执行结果
                from services.sync_service import closure_task
                closure_result = await closure_task(
                    task_id=task_block_id,
                    token=context.token
                )
            else:
                result["message"] = f"选择执行机器人失败: {result.get('message', '未知错误')}, 块id：{current_block_name}"
            return result
        except Exception as e:
            result = {
                "success": False,
                "message": f"选择执行机器人异常: {str(e)}"
            }
            # 记录异常
            await self._record_task_log(block, result, context)
            return result 