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

"""
动作点管理服务
处理动作点和库位的管理操作
"""

import math
from typing import List, Dict, Any, Optional, Tuple
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_, func
from data.models import OperatePoint, OperatePointLayer, StorageArea, StorageAreaType, ExtendedProperty, ExtendedPropertyTypeEnum, StorageLocationLog
from routes.model.operate_point_model import (
    OperatePointLayerInfo,
    StorageLocationListRequest, StorageLocationListResponse,
    StorageLocationInfo, StorageLocationStatistics,
    StorageLocationStatusUpdateRequest, StorageLocationStatusUpdateResponse,
    BatchStorageLocationStatusUpdateRequest, BatchStorageLocationStatusUpdateResponse,
    StorageLocationActionEnum,
    ExtendedPropertyCreateRequest, ExtendedPropertyCreateResponse,
    ExtendedPropertyListRequest, ExtendedPropertyListResponse,
    ExtendedPropertyInfo, ExtendedPropertyDeleteResponse,
    StorageLocationDetailResponse, StorageLocationEditRequest, StorageLocationEditResponse,
    StorageLocationLogInfo, StorageLocationLogListRequest, StorageLocationLogListResponse,
    LogicalStorageLocationCreateRequest, LogicalStorageLocationCreateResponse,
    LogicalStorageLocationDeleteResponse,
)
from utils.logger import get_logger
import datetime

logger = get_logger("services.operate_point_service")


class OperatePointService:
    """库位管理服务"""

    @staticmethod
    def get_storage_location_list(db: Session, request: StorageLocationListRequest) -> StorageLocationListResponse:
        """
        获取库位列表
        
        Args:
            db: 数据库会话
            request: 库位列表查询请求
            
        Returns:
            StorageLocationListResponse: 库位列表响应
        """
        try:
            # 构建查询条件 - 主要查询 OperatePointLayer 表
            query = db.query(OperatePointLayer).filter(OperatePointLayer.is_deleted == False)
            
            # 判断是否需要关联 OperatePoint 表
            need_join_operate_point = request.scene_id or request.storage_area_id
            if need_join_operate_point:
                query = query.join(OperatePoint)
            
            # 添加 OperatePoint 相关的过滤条件
            if request.scene_id:
                query = query.filter(OperatePoint.scene_id == request.scene_id)
            
            if request.storage_area_id:
                query = query.filter(OperatePoint.storage_area_id == request.storage_area_id)
            
            # 站点名称模糊搜索
            if request.station_name:
                query = query.filter(OperatePointLayer.station_name.like(f"%{request.station_name}%"))
            

            # 库位名称模糊搜索
            if request.layer_name:
                query = query.filter(OperatePointLayer.layer_name.like(f"%{request.layer_name}%"))
            
            # 是否禁用过滤
            if request.is_disabled is not None:
                query = query.filter(OperatePointLayer.is_disabled == request.is_disabled)
            
            # 是否占用过滤
            if request.is_occupied is not None:
                query = query.filter(OperatePointLayer.is_occupied == request.is_occupied)
            
            # 是否锁定过滤
            if request.is_locked is not None:
                query = query.filter(OperatePointLayer.is_locked == request.is_locked)
            
            # 是否空托盘过滤
            if request.is_empty_tray is not None:
                query = query.filter(OperatePointLayer.is_empty_tray == request.is_empty_tray)
            
            # 库位类型过滤
            if request.location_type is not None:
                query = query.filter(OperatePointLayer.location_type == request.location_type)
            
            # 获取总数
            total = query.count()
            
            # 排序处理
            storage_locations = query.all()  # 先获取所有数据进行自定义排序
            # print(f"storage_locations: {request.layer_name_sort}, {request.station_name_sort}", "==================")
            # 应用自定义排序
            if request.layer_name_sort is not None or request.station_name_sort is not None:
                storage_locations = OperatePointService._apply_custom_sorting(
                    storage_locations, 
                    request.layer_name_sort, 
                    request.station_name_sort
                )
            # 分页
            offset = (request.page - 1) * request.page_size
            storage_locations = storage_locations[offset:offset + request.page_size]
            # print(len(storage_locations) ,storage_locations)
            # 转换为响应对象
            storage_location_infos = []
            for sl in storage_locations:
                # print(sl, "------------------------------------------")
                storage_location_info = OperatePointService._convert_to_storage_location_info(
                    sl, 
                    request.include_operate_point_info, 
                    request.include_extended_fields
                )
                storage_location_infos.append(storage_location_info)
            
            # 计算总页数
            total_pages = math.ceil(total / request.page_size) if total > 0 else 0
            
            # 获取统计信息
            # statistics = OperatePointService._get_storage_location_statistics(db, request)
            
            return StorageLocationListResponse(
                total=total,
                page=request.page,
                page_size=request.page_size,
                total_pages=total_pages,
                storage_locations=storage_location_infos,
                # statistics=statistics
            )
            
        except Exception as e:
            logger.error(f"获取库位列表失败: {str(e)}")
            raise
    
    @staticmethod
    def _apply_custom_sorting(storage_locations: List[OperatePointLayer], layer_name_sort: Optional[bool], station_name_sort: Optional[bool]) -> List[OperatePointLayer]:
        """
        对库位列表应用自定义排序
        
        排序规则：
        - layer_name：如 GSD_1_1_1，先按数字部分排序，然后按字母部分排序
        - station_name：如 AP1，先按数字部分排序，然后按字母部分排序
        
        Args:
            storage_locations: 库位列表
            layer_name_sort: layer_name排序方式 (True为升序，False为降序，None不排序)
            station_name_sort: station_name排序方式 (True为升序，False为降序，None不排序)
            
        Returns:
            排序后的库位列表
        """
        # print(f"layer_name_sort: {layer_name_sort}, station_name_sort: {station_name_sort}", "==================")
        import re
        from functools import cmp_to_key
        
        def _parse_alphanumeric_name(name: str):
            """解析字母数字混合的名称，返回(字母部分, 数字部分列表)"""
            if not name:
                return ("", [])
            
            # 使用正则表达式分离字母和数字部分
            parts = re.findall(r'([A-Za-z]+)|(\d+)', name)
            letters = ""
            numbers = []
            
            for letter_part, number_part in parts:
                if letter_part:
                    letters += letter_part
                elif number_part:
                    numbers.append(int(number_part))
            
            return (letters.upper(), numbers)
        
        def _compare_names(name1: str, name2: str):
            """比较两个名称，返回 -1、0、1"""
            letters1, numbers1 = _parse_alphanumeric_name(name1)
            letters2, numbers2 = _parse_alphanumeric_name(name2)
            
            # 先比较字母部分
            if letters1 < letters2:
                return -1
            elif letters1 > letters2:
                return 1
            
            # 字母部分相同，比较数字部分
            # 按位比较数字
            min_len = min(len(numbers1), len(numbers2))
            for i in range(min_len):
                if numbers1[i] < numbers2[i]:
                    return -1
                elif numbers1[i] > numbers2[i]:
                    return 1
            
            # 如果前面的数字都相同，数字部分更长的排在后面
            if len(numbers1) < len(numbers2):
                return -1
            elif len(numbers1) > len(numbers2):
                return 1
            
            return 0
        
        def _sort_comparator(a, b):
            """自定义比较器"""
            # 优先按 layer_name 排序（如果指定）
            if layer_name_sort is not None:
                layer_cmp = _compare_names(a.layer_name or "", b.layer_name or "")
                if layer_cmp != 0:
                    return layer_cmp if layer_name_sort else -layer_cmp  # True=升序, False=降序
            
            # 然后按 station_name 排序（如果指定）
            if station_name_sort is not None:
                station_cmp = _compare_names(a.station_name or "", b.station_name or "")
                if station_cmp != 0:
                    return station_cmp if station_name_sort else -station_cmp  # True=升序, False=降序
            
            return 0
        
        # 应用排序
        if layer_name_sort is not None or station_name_sort is not None:
            storage_locations = sorted(storage_locations, key=cmp_to_key(_sort_comparator))
        
        return storage_locations
    
    @staticmethod
    def _convert_to_storage_location_info(layer: OperatePointLayer, include_operate_point_info: bool = True, include_extended_fields: bool = False) -> StorageLocationInfo:
        """
        将数据库模型转换为库位信息响应对象
        
        Args:
            layer: 动作点分层数据库模型
            include_operate_point_info: 是否包含动作点信息
            
        Returns:
            StorageLocationInfo: 库位信息
        """
        # 构建库位信息
        storage_location_info = StorageLocationInfo(
            id=layer.id,
            layer_index=layer.layer_index,
            location_type=layer.location_type,
            layer_name=layer.layer_name,
            is_occupied=layer.is_occupied,
            is_locked=layer.is_locked,
            is_disabled=layer.is_disabled,
            is_empty_tray=layer.is_empty_tray,
            locked_by=layer.locked_by,
            goods_content=layer.goods_content,
            goods_weight=layer.goods_weight,
            goods_volume=layer.goods_volume,
            goods_stored_at=layer.goods_stored_at,
            goods_retrieved_at=layer.goods_retrieved_at,
            last_access_at=layer.last_access_at,
            max_weight=layer.max_weight,
            max_volume=layer.max_volume,
            layer_height=layer.layer_height,
            tags=layer.tags,
            description=layer.description,
            created_at=layer.created_at,
            updated_at=layer.updated_at
        )

        # 如果需要包含动作点信息，则直接平铺到库位信息中
        if include_operate_point_info and layer.operate_point:
            storage_location_info.operate_point_id = layer.operate_point.id
            storage_location_info.station_name = layer.operate_point.station_name
            storage_location_info.scene_id = layer.operate_point.scene_id
            storage_location_info.storage_area_id = layer.operate_point.storage_area_id
            storage_location_info.storage_area_type = layer.operate_point.storage_area_type.value if layer.operate_point.storage_area_type else None
            storage_location_info.area_name = layer.operate_point.area_name
            storage_location_info.max_layers = layer.operate_point.max_layers
            storage_location_info.current_layers = layer.operate_point.current_layers
            storage_location_info.position_x = layer.operate_point.position_x
            storage_location_info.position_y = layer.operate_point.position_y
            storage_location_info.position_z = layer.operate_point.position_z
            storage_location_info.operate_point_description = layer.operate_point.description
        
        # 如果需要包含扩展字段，则从 config_json 中解析
        if include_extended_fields and layer.config_json:
            extended_fields = OperatePointService._parse_extended_fields(layer.config_json)
            # 将扩展字段转换为简单的键值对格式，便于前端处理
            storage_location_info.extended_fields = {
                field_name: field_data["value"]
                for field_name, field_data in extended_fields.items()
            }
        elif include_extended_fields:
            storage_location_info.extended_fields = {}
        
        return storage_location_info

    @staticmethod
    def update_storage_location_status(db: Session, request: StorageLocationStatusUpdateRequest, token: Optional[str] = None) -> StorageLocationStatusUpdateResponse:
        """
        更新库位状态
        
        Args:
            db: 数据库会话
            request: 库位状态更新请求
            token: JWT token用于解析操作人信息
            
        Returns:
            StorageLocationStatusUpdateResponse: 更新响应
        """
        try:
            # 查询库位（使用layer_name进行查询）
            storage_location = db.query(OperatePointLayer).filter(
                OperatePointLayer.layer_name == request.layer_name,
                OperatePointLayer.is_deleted == False
            ).first()
            
            if not storage_location:
                return StorageLocationStatusUpdateResponse(
                    layer_name=request.layer_name,
                    action=request.action,
                    success=False,
                    message="库位不存在",
                    new_status={}
                )
            
            # 执行状态更新
            success, message = OperatePointService._execute_status_update(storage_location, request.action, request.locked_by)
            
            if success:
                db.commit()
                
                # 记录操作日志
                try:
                    operator = OperatePointService._get_operator(request.locked_by, token)
                    OperatePointService.create_storage_location_log(
                        db=db,
                        operator=operator,
                        operation_type=request.action.value,
                        affected_storage_locations=[request.layer_name],
                        description=request.reason
                    )
                except Exception as e:
                    logger.error(f"记录操作日志失败: {str(e)}")
                
                # 获取更新后的状态
                new_status = OperatePointService._get_storage_location_status(storage_location)
                
                return StorageLocationStatusUpdateResponse(
                    layer_name=request.layer_name,
                    action=request.action,
                    success=True,
                    message=message,
                    new_status=new_status
                )
            else:
                db.rollback()
                return StorageLocationStatusUpdateResponse(
                    layer_name=request.layer_name,
                    action=request.action,
                    success=False,
                    message=message,
                    new_status={}
                )
                
        except Exception as e:
            db.rollback()
            logger.error(f"更新库位状态失败: {str(e)}")
            return StorageLocationStatusUpdateResponse(
                layer_name=request.layer_name,
                action=request.action,
                success=False,
                message=f"更新库位状态失败: {str(e)}",
                new_status={}
            )
    
    @staticmethod
    def batch_update_storage_location_status(db: Session, request: BatchStorageLocationStatusUpdateRequest, token: Optional[str] = None) -> BatchStorageLocationStatusUpdateResponse:
        """
        批量更新库位状态
        
        Args:
            db: 数据库会话
            request: 批量库位状态更新请求
            token: JWT token用于解析操作人信息
            
        Returns:
            BatchStorageLocationStatusUpdateResponse: 批量更新响应
        """
        try:
            results = []
            success_count = 0
            failed_count = 0
            
            for layer_name in request.layer_names:
                # 创建单个更新请求
                single_request = StorageLocationStatusUpdateRequest(
                    layer_name=layer_name,
                    action=request.action,
                    locked_by=request.locked_by,
                    reason=request.reason
                )
                
                # 执行单个更新
                result = OperatePointService.update_storage_location_status(db, single_request, token)
                results.append(result)
                
                if result.success:
                    success_count += 1
                else:
                    failed_count += 1
            
            return BatchStorageLocationStatusUpdateResponse(
                total_count=len(request.layer_names),
                success_count=success_count,
                failed_count=failed_count,
                results=results
            )
            
        except Exception as e:
            logger.error(f"批量更新库位状态失败: {str(e)}")
            raise
    
    @staticmethod
    def _execute_status_update(storage_location: OperatePointLayer, action: StorageLocationActionEnum, locked_by: Optional[str] = None) -> Tuple[bool, str]:
        """
        执行状态更新操作
        
        Args:
            storage_location: 库位对象
            action: 操作类型（枚举）
            locked_by: 锁定者
            
        Returns:
            Tuple[bool, str]: (是否成功, 消息)
        """
        try:
            current_time = datetime.datetime.now()
            
            if action == StorageLocationActionEnum.OCCUPY:
                # 占用操作
                if storage_location.is_occupied:
                    return True, "库位已被占用，无需重复操作"
                if storage_location.is_disabled:
                    return False, "库位已禁用，无法占用"
                if storage_location.is_locked:
                    return False, "库位已锁定，无法占用"
                
                storage_location.is_occupied = True
                storage_location.last_access_at = current_time
                storage_location.goods_stored_at = current_time
                storage_location.goods_retrieved_at = None
                return True, "库位占用成功"
                
            elif action == StorageLocationActionEnum.RELEASE:
                # 释放操作
                if not storage_location.is_occupied:
                    return True, "库位未被占用，无需重复操作"
                
                storage_location.is_occupied = False
                storage_location.goods_content = ''
                storage_location.goods_weight = None
                storage_location.goods_volume = None
                storage_location.goods_retrieved_at = current_time
                storage_location.goods_stored_at = None
                storage_location.last_access_at = current_time
                return True, "库位释放成功"
                
            elif action == StorageLocationActionEnum.LOCK:
                # 锁定操作
                if not locked_by:
                    return False, "锁定操作必须提供锁定者"
                if storage_location.is_locked:
                    if storage_location.locked_by == locked_by:
                        return True, "库位已被相同锁定者锁定，无需重复操作"
                    else:
                        return False, f"库位已被其他锁定者锁定，当前锁定者: {storage_location.locked_by}"
                
                storage_location.is_locked = True
                storage_location.locked_by = locked_by
                storage_location.last_access_at = current_time
                return True, "库位锁定成功"
                
            elif action == StorageLocationActionEnum.UNLOCK:
                # 解锁操作
                if not storage_location.is_locked:
                    return True, "库位未被锁定，无需重复操作"
                
                storage_location.is_locked = False
                storage_location.locked_by = None
                storage_location.last_access_at = current_time
                return True, "库位解锁成功"
                
            elif action == StorageLocationActionEnum.ENABLE:
                # 启用操作
                if not storage_location.is_disabled:
                    return True, "库位已启用，无需重复操作"
                
                storage_location.is_disabled = False
                storage_location.last_access_at = current_time
                return True, "库位启用成功"
                
            elif action == StorageLocationActionEnum.DISABLE:
                # 禁用操作
                if storage_location.is_disabled:
                    return True, "库位已禁用，无需重复操作"
                
                storage_location.is_disabled = True
                storage_location.last_access_at = current_time
                return True, "库位禁用成功"
                
            elif action == StorageLocationActionEnum.SET_EMPTY_TRAY:
                # 设置为空托盘
                if storage_location.is_empty_tray:
                    return True, "库位已设置为空托盘，无需重复操作"
                
                storage_location.is_empty_tray = True
                storage_location.is_occupied = True
                storage_location.last_access_at = current_time
                storage_location.goods_stored_at = current_time
                storage_location.goods_retrieved_at = None
                return True, "库位设置为空托盘成功"
                
            elif action == StorageLocationActionEnum.CLEAR_EMPTY_TRAY:
                # 清除空托盘状态
                if not storage_location.is_empty_tray:
                    return True, "库位已非空托盘状态，无需重复操作"
                
                storage_location.is_empty_tray = False
                storage_location.last_access_at = current_time
                storage_location.is_occupied = False
                storage_location.goods_content = ''
                storage_location.goods_weight = None
                storage_location.goods_volume = None
                storage_location.goods_retrieved_at = current_time
                storage_location.goods_stored_at = None

                return True, "库位清除空托盘状态成功"
                
            else:
                return False, f"不支持的操作类型: {action}"
                
        except Exception as e:
            logger.error(f"执行状态更新操作失败: {str(e)}")
            return False, f"执行状态更新操作失败: {str(e)}"
    
    @staticmethod
    def _get_storage_location_status(storage_location: OperatePointLayer) -> Dict[str, Any]:
        """
        获取库位状态信息
        
        Args:
            storage_location: 库位对象
            
        Returns:
            Dict[str, Any]: 状态信息
        """
        return {
            "id": storage_location.id,
            "is_occupied": storage_location.is_occupied,
            "is_locked": storage_location.is_locked,
            "is_disabled": storage_location.is_disabled,
            "is_empty_tray": storage_location.is_empty_tray,
            "locked_by": storage_location.locked_by,
            "goods_content": storage_location.goods_content,
            "last_access_at": storage_location.last_access_at,
            "updated_at": storage_location.updated_at
        } 

    @staticmethod
    def _get_operator(provided_operator: Optional[str] = None, token: Optional[str] = None, fallback_operator: str = "系统") -> str:
        """
        获取操作人信息
        
        Args:
            provided_operator: 提供的操作人（如锁定者）
            token: JWT token用于解析用户信息
            fallback_operator: 默认操作人
            
        Returns:
            str: 操作人名称
        """
        # 如果提供了操作人且不为空，使用提供的操作人
        if provided_operator and provided_operator.strip():
            return provided_operator.strip()
        
        # 从JWT token中获取用户名
        if token and token.strip():
            from utils.crypto_utils import JWTParser
            username = JWTParser.get_username_from_jwt(token.strip())
            if username:
                return username
        
        # 使用默认操作人
        return fallback_operator

    @staticmethod
    def get_operation_result_summary(results: List[StorageLocationStatusUpdateResponse]) -> Dict[str, Any]:
        """
        获取操作结果的汇总统计信息
        
        Args:
            results: 操作结果列表
            
        Returns:
            Dict[str, Any]: 统计信息
        """
        if not results:
            return {
                "total": 0,
                "success": 0,
                "failed": 0,
                "no_change_needed": 0,
                "actual_updates": 0
            }
        
        total = len(results)
        success = sum(1 for r in results if r.success)
        failed = total - success
        
        # 统计无需更改的操作（幂等性操作）
        no_change_messages = [
            "无需重复操作",
            "已被占用，无需重复操作",
            "未被占用，无需重复操作",
            "已被相同锁定者锁定，无需重复操作",
            "未被锁定，无需重复操作",
            "已启用，无需重复操作",
            "已禁用，无需重复操作",
            "已设置为空托盘，无需重复操作",
            "已非空托盘状态，无需重复操作"
        ]
        
        no_change_needed = sum(1 for r in results 
                              if r.success and any(msg in r.message for msg in no_change_messages))
        actual_updates = success - no_change_needed
        
        return {
            "total": total,
            "success": success,
            "failed": failed,
            "no_change_needed": no_change_needed,
            "actual_updates": actual_updates
        } 

    
    @staticmethod
    def _parse_extended_fields(config_json: str) -> Dict[str, Any]:
        """
        解析扩展字段JSON
        
        Args:
            config_json: JSON字符串
            
        Returns:
            Dict[str, Any]: 扩展字段字典
        """
        try:
            if not config_json:
                return {}
            
            import json
            config = json.loads(config_json)
            return config.get("extended_fields", {})
            
        except Exception as e:
            logger.error(f"解析扩展字段JSON失败: {str(e)}")
            return {}
    
    @staticmethod
    def _serialize_extended_fields(extended_fields: Dict[str, Any]) -> str:
        """
        序列化扩展字段为JSON
        
        Args:
            extended_fields: 扩展字段字典
            
        Returns:
            str: JSON字符串
        """
        try:
            import json
            config = {"extended_fields": extended_fields}
            return json.dumps(config, ensure_ascii=False, indent=2)
            
        except Exception as e:
            logger.error(f"序列化扩展字段JSON失败: {str(e)}")
            return "{}"
    
    @staticmethod
    def _infer_field_type(value: Any) -> str:
        """
        推断字段类型
        
        Args:
            value: 字段值
            
        Returns:
            str: 字段类型
        """
        if isinstance(value, bool):
            return "boolean"
        elif isinstance(value, int):
            return "integer"
        elif isinstance(value, float):
            return "number"
        elif isinstance(value, str):
            # 尝试判断是否为日期
            try:
                datetime.datetime.fromisoformat(value)
                return "date"
            except:
                return "string"
        elif isinstance(value, list):
            return "array"
        elif isinstance(value, dict):
            return "object"
        else:
            return "string" 

    # 扩展属性管理相关方法
    @staticmethod
    def create_extended_property(db: Session, request: ExtendedPropertyCreateRequest, token: Optional[str] = None) -> ExtendedPropertyCreateResponse:
        """
        创建扩展属性
        
        Args:
            db: 数据库会话
            request: 扩展属性创建请求
            token: JWT token用于解析操作人信息
            
        Returns:
            ExtendedPropertyCreateResponse: 创建响应
        """
        try:
            # 检查属性名称是否已存在
            existing_property = db.query(ExtendedProperty).filter(
                ExtendedProperty.property_name == request.property_name,
                ExtendedProperty.is_deleted == False
            ).first()
            
            if existing_property:
                raise ValueError(f"属性名称 '{request.property_name}' 已存在")
            
            # 创建扩展属性
            extended_property = ExtendedProperty(
                property_key=request.property_name,  # 使用 property_name 作为 property_key
                property_name=request.property_name,
                property_type=request.property_type,
                is_required=request.is_required,
                is_enabled=request.is_enabled,
                description=request.description,
                placeholder=request.placeholder,
                default_value=request.default_value,
                options=OperatePointService._serialize_options(request.options),
                validation_rules=OperatePointService._serialize_validation_rules(request.validation_rules),
                category=request.category,
                sort_order=request.sort_order,
                display_width=request.display_width,
                display_format=request.display_format
            )
            
            db.add(extended_property)
            db.commit()
            db.refresh(extended_property)
            
            # 成功创建扩展属性后，更新所有 OperatePointLayer 的 config_json
            try:
                OperatePointService._add_extended_property_to_layers(
                    db=db,
                    property_name=extended_property.property_name,
                    property_type=extended_property.property_type,
                    default_value=extended_property.default_value,
                    is_required=extended_property.is_required
                )
                db.commit()
                logger.info(f"成功为所有库位层添加扩展属性: {extended_property.property_name}")
            except Exception as e:
                logger.error(f"添加扩展属性到库位层失败: {str(e)}")
                # 这里不抛出异常，因为扩展属性已经创建成功
            
            # 记录操作日志
            try:
                operator = OperatePointService._get_operator(token=token)
                OperatePointService.create_storage_location_log(
                    db=db,
                    operator=operator,
                    operation_type="创建扩展属性",
                    affected_storage_locations=[],  # 扩展属性影响所有库位，这里传空列表
                    description=f"创建扩展属性 '{extended_property.property_name}'，类型: {extended_property.property_type.value}，已应用到所有库位层"
                )
            except Exception as e:
                logger.error(f"记录操作日志失败: {str(e)}")
            
            return ExtendedPropertyCreateResponse(
                id=str(extended_property.id),
                property_name=extended_property.property_name,
                message="扩展属性创建成功，已应用到所有库位层"
            )
            
        except Exception as e:
            db.rollback()
            logger.error(f"创建扩展属性失败: {str(e)}")
            raise
    
    @staticmethod
    def get_extended_property_list(db: Session, request: ExtendedPropertyListRequest) -> ExtendedPropertyListResponse:
        """
        获取扩展属性列表
        
        Args:
            db: 数据库会话
            request: 扩展属性列表查询请求
            
        Returns:
            ExtendedPropertyListResponse: 属性列表响应
        """
        try:
            # 构建查询条件
            query = db.query(ExtendedProperty).filter(ExtendedProperty.is_deleted == False)
            
            # 属性名称模糊搜索
            if request.property_name:
                query = query.filter(ExtendedProperty.property_name.like(f"%{request.property_name}%"))
            
            # 属性类型过滤
            if request.property_type:
                query = query.filter(ExtendedProperty.property_type == request.property_type)
            
            # 分类过滤
            if request.category:
                query = query.filter(ExtendedProperty.category == request.category)
            
            # 是否启用过滤
            if request.is_enabled is not None:
                query = query.filter(ExtendedProperty.is_enabled == request.is_enabled)
            
            # 排序
            query = query.order_by(ExtendedProperty.sort_order.asc(), ExtendedProperty.created_at.desc())
            
            # 获取总数
            total = query.count()
            
            # 分页
            offset = (request.page - 1) * request.page_size
            properties = query.offset(offset).limit(request.page_size).all()
            
            # 转换为响应对象
            property_infos = []
            for prop in properties:
                property_info = OperatePointService._convert_to_extended_property_info(prop)
                property_infos.append(property_info)
            
            # 计算总页数
            total_pages = math.ceil(total / request.page_size) if total > 0 else 0
            
            return ExtendedPropertyListResponse(
                total=total,
                page=request.page,
                page_size=request.page_size,
                total_pages=total_pages,
                properties=property_infos
            )
            
        except Exception as e:
            logger.error(f"获取扩展属性列表失败: {str(e)}")
            raise
    
    @staticmethod
    def delete_extended_property(db: Session, property_id: str, token: Optional[str] = None) -> ExtendedPropertyDeleteResponse:
        """
        删除扩展属性
        
        Args:
            db: 数据库会话
            property_id: 属性ID
            token: JWT token用于解析操作人信息
            
        Returns:
            ExtendedPropertyDeleteResponse: 删除响应
        """
        try:
            # 查询扩展属性
            extended_property = db.query(ExtendedProperty).filter(
                ExtendedProperty.id == property_id,
                ExtendedProperty.is_deleted == False
            ).first()
            
            if not extended_property:
                raise ValueError("扩展属性不存在")
            
            # 软删除
            extended_property.is_deleted = True
            extended_property.updated_at = datetime.datetime.now()
            
            # 记录属性名称，用于后续清理
            property_name = extended_property.property_name
            
            db.commit()
            
            # 成功删除扩展属性后，从所有 OperatePointLayer 的 config_json 中移除该属性
            try:
                OperatePointService._remove_extended_property_from_layers(
                    db=db,
                    property_name=property_name
                )
                db.commit()
                logger.info(f"成功从所有库位层移除扩展属性: {property_name}")
            except Exception as e:
                logger.error(f"从库位层移除扩展属性失败: {str(e)}")
                # 这里不抛出异常，因为扩展属性已经删除成功
            
            # 记录操作日志
            try:
                operator = OperatePointService._get_operator(token=token)
                OperatePointService.create_storage_location_log(
                    db=db,
                    operator=operator,
                    operation_type="删除扩展属性",
                    affected_storage_locations=[],  # 扩展属性影响所有库位，这里传空列表
                    description=f"删除扩展属性 '{property_name}'，已从所有库位层移除"
                )
            except Exception as e:
                logger.error(f"记录操作日志失败: {str(e)}")
            
            return ExtendedPropertyDeleteResponse(
                property_id=str(extended_property.id),
                property_name=extended_property.property_name,
                message="扩展属性删除成功，已从所有库位层移除"
            )
            
        except Exception as e:
            db.rollback()
            logger.error(f"删除扩展属性失败: {str(e)}")
            raise
    
    @staticmethod
    def _convert_to_extended_property_info(prop: ExtendedProperty) -> ExtendedPropertyInfo:
        """
        将数据库模型转换为扩展属性信息响应对象
        
        Args:
            prop: 扩展属性数据库模型
            
        Returns:
            ExtendedPropertyInfo: 扩展属性信息
        """
        return ExtendedPropertyInfo(
            id=str(prop.id),
            property_name=prop.property_name,
            property_type=prop.property_type,
            is_required=prop.is_required,
            is_enabled=prop.is_enabled,
            description=prop.description,
            placeholder=prop.placeholder,
            default_value=prop.default_value,
            options=OperatePointService._parse_options(prop.options),
            validation_rules=OperatePointService._parse_validation_rules(prop.validation_rules),
            category=prop.category,
            sort_order=prop.sort_order,
            display_width=prop.display_width,
            display_format=prop.display_format,
            created_at=prop.created_at,
            updated_at=prop.updated_at
        )
    
    @staticmethod
    def _serialize_options(options: Optional[List[Dict[str, Any]]]) -> Optional[str]:
        """
        序列化选项为JSON字符串
        
        Args:
            options: 选项列表
            
        Returns:
            str: JSON字符串
        """
        if not options:
            return None
        
        try:
            import json
            return json.dumps(options, ensure_ascii=False)
        except Exception as e:
            logger.error(f"序列化选项失败: {str(e)}")
            return None
    
    @staticmethod
    def _parse_options(options_json: Optional[str]) -> Optional[List[Dict[str, Any]]]:
        """
        解析选项JSON字符串
        
        Args:
            options_json: JSON字符串
            
        Returns:
            List[Dict[str, Any]]: 选项列表
        """
        if not options_json:
            return None
        
        try:
            import json
            return json.loads(options_json)
        except Exception as e:
            logger.error(f"解析选项JSON失败: {str(e)}")
            return None
    
    @staticmethod
    def _serialize_validation_rules(rules: Optional[Dict[str, Any]]) -> Optional[str]:
        """
        序列化验证规则为JSON字符串
        
        Args:
            rules: 验证规则字典
            
        Returns:
            str: JSON字符串
        """
        if not rules:
            return None
        
        try:
            import json
            return json.dumps(rules, ensure_ascii=False)
        except Exception as e:
            logger.error(f"序列化验证规则失败: {str(e)}")
            return None
    
    @staticmethod
    def _parse_validation_rules(rules_json: Optional[str]) -> Optional[Dict[str, Any]]:
        """
        解析验证规则JSON字符串
        
        Args:
            rules_json: JSON字符串
            
        Returns:
            Dict[str, Any]: 验证规则字典
        """
        if not rules_json:
            return None
        
        try:
            import json
            return json.loads(rules_json)
        except Exception as e:
            logger.error(f"解析验证规则JSON失败: {str(e)}")
            return None

    @staticmethod
    def _add_extended_property_to_layers(
        db: Session,
        property_name: str,
        property_type: ExtendedPropertyTypeEnum,
        default_value: Optional[str] = None,
        is_required: bool = False
    ):
        """
        将扩展属性添加到所有库位层的config_json中
        
        Args:
            db: 数据库会话
            property_name: 属性名称
            property_type: 属性类型
            default_value: 默认值
            is_required: 是否必填
        """
        try:
            # 获取所有未删除的库位层
            layers = db.query(OperatePointLayer).filter(
                OperatePointLayer.is_deleted == False
            ).all()
            
            for layer in layers:
                # 解析现有的config_json
                config = {}
                if layer.config_json:
                    try:
                        import json
                        config = json.loads(layer.config_json)
                    except Exception as e:
                        logger.error(f"解析库位层 {layer.id} 的config_json失败: {str(e)}")
                        config = {}
                
                # 确保extended_fields字段存在
                if 'extended_fields' not in config:
                    config['extended_fields'] = {}
                
                # 添加新的扩展属性
                config['extended_fields'][property_name] = {
                    'value': default_value,
                    'type': property_type.value,
                    'is_required': is_required,
                    'updated_at': datetime.datetime.now().isoformat()
                }
                
                # 更新config_json
                try:
                    import json
                    layer.config_json = json.dumps(config, ensure_ascii=False, indent=2)
                    logger.debug(f"为库位层 {layer.id} 添加扩展属性: {property_name}")
                except Exception as e:
                    logger.error(f"序列化库位层 {layer.id} 的config_json失败: {str(e)}")
                    
        except Exception as e:
            logger.error(f"添加扩展属性到库位层失败: {str(e)}")
            raise

    @staticmethod
    def _remove_extended_property_from_layers(db: Session, property_name: str):
        """
        从所有库位层的config_json中移除扩展属性
        
        Args:
            db: 数据库会话
            property_name: 属性名称
        """
        try:
            # 获取所有未删除的库位层
            layers = db.query(OperatePointLayer).filter(
                OperatePointLayer.is_deleted == False
            ).all()
            
            for layer in layers:
                # 解析现有的config_json
                config = {}
                if layer.config_json:
                    try:
                        import json
                        config = json.loads(layer.config_json)
                    except Exception as e:
                        logger.error(f"解析库位层 {layer.id} 的config_json失败: {str(e)}")
                        continue
                
                # 检查是否存在extended_fields
                if 'extended_fields' in config and property_name in config['extended_fields']:
                    # 移除指定的扩展属性
                    del config['extended_fields'][property_name]
                    
                    # 更新config_json
                    try:
                        import json
                        layer.config_json = json.dumps(config, ensure_ascii=False, indent=2)
                        logger.debug(f"从库位层 {layer.id} 移除扩展属性: {property_name}")
                    except Exception as e:
                        logger.error(f"序列化库位层 {layer.id} 的config_json失败: {str(e)}")
                        
        except Exception as e:
            logger.error(f"从库位层移除扩展属性失败: {str(e)}")
            raise

    @staticmethod
    def get_storage_location_detail(db: Session, layer_name: str) -> Dict[str, Any]:
        """
        获取库位详情
        
        Args:
            db: 数据库会话
            layer_name: 库位名称
            
        Returns:
            Dict[str, Any]: 库位详情信息
        """
        try:
            # 查询库位
            layer = db.query(OperatePointLayer).filter(
                OperatePointLayer.layer_name == layer_name,
                OperatePointLayer.is_deleted == False
            ).first()
            
            if not layer:
                raise ValueError(f"库位 {layer_name} 不存在")
            
            # 获取库位详细信息
            storage_location_info = OperatePointService._convert_to_storage_location_info(
                layer, include_operate_point_info=True, include_extended_fields=True
            )
            
            # 获取动作点详细信息
            operate_point_info = None
            if layer.operate_point:
                operate_point_info = {
                    "id": layer.operate_point.id,
                    "station_name": layer.operate_point.station_name,
                    "scene_id": layer.operate_point.scene_id,
                    "storage_area_id": layer.operate_point.storage_area_id,
                    "storage_area_type": layer.operate_point.storage_area_type.value if layer.operate_point.storage_area_type else None,
                    "area_name": layer.operate_point.area_name,
                    "max_layers": layer.operate_point.max_layers,
                    "current_layers": layer.operate_point.current_layers,
                    "position_x": layer.operate_point.position_x,
                    "position_y": layer.operate_point.position_y,
                    "position_z": layer.operate_point.position_z,
                    "description": layer.operate_point.description,
                    "created_at": layer.operate_point.created_at,
                    "updated_at": layer.operate_point.updated_at,
                    "is_deleted": layer.operate_point.is_deleted
                }
            
            # 获取扩展字段定义
            extended_fields_definitions = []
            if layer.config_json:
                try:
                    import json
                    config = json.loads(layer.config_json)
                    if 'extended_fields' in config:
                        # 获取所有扩展属性定义
                        extended_properties = db.query(ExtendedProperty).filter(
                            ExtendedProperty.is_deleted == False,
                            ExtendedProperty.is_enabled == True
                        ).all()
                        
                        for prop in extended_properties:
                            extended_fields_definitions.append(
                                OperatePointService._convert_to_extended_property_info(prop)
                            )
                except Exception as e:
                    logger.error(f"解析扩展字段定义失败: {str(e)}")
            
            # 构建状态变更历史（暂时为空，后续可以扩展）
            status_history = []
            
            return {
                "storage_location": storage_location_info,
                "operate_point_info": operate_point_info,
                "extended_fields_definitions": extended_fields_definitions,
                "status_history": status_history
            }
            
        except Exception as e:
            logger.error(f"获取库位详情失败: {str(e)}")
            raise

    @staticmethod
    def edit_storage_location(db: Session, layer_name: str, request: Any, token: Optional[str] = None) -> Dict[str, Any]:
        """
        编辑库位信息
        
        Args:
            db: 数据库会话
            layer_name: 库位名称
            request: 库位编辑请求
            token: JWT token用于解析操作人信息
            
        Returns:
            Dict[str, Any]: 编辑响应
        """
        try:
            # 查询库位
            layer = db.query(OperatePointLayer).filter(
                OperatePointLayer.layer_name == layer_name,
                OperatePointLayer.is_deleted == False
            ).first()
            
            if not layer:
                raise ValueError(f"库位 {layer_name} 不存在")
            
            # 跟踪更新的字段
            updated_fields = []
            
            # 更新基本字段
            if request.goods_content is not None and request.goods_content != layer.goods_content:
                layer.goods_content = request.goods_content
                updated_fields.append("goods_content")
            
            if request.goods_weight is not None and request.goods_weight != layer.goods_weight:
                layer.goods_weight = request.goods_weight
                updated_fields.append("goods_weight")
            
            if request.goods_volume is not None and request.goods_volume != layer.goods_volume:
                layer.goods_volume = request.goods_volume
                updated_fields.append("goods_volume")
            
            if request.max_weight is not None and request.max_weight != layer.max_weight:
                layer.max_weight = request.max_weight
                updated_fields.append("max_weight")
            
            if request.max_volume is not None and request.max_volume != layer.max_volume:
                layer.max_volume = request.max_volume
                updated_fields.append("max_volume")
            
            if request.layer_height is not None and request.layer_height != layer.layer_height:
                layer.layer_height = request.layer_height
                updated_fields.append("layer_height")
            
            # 更新状态字段
            if request.is_locked is not None and request.is_locked != layer.is_locked:
                layer.is_locked = request.is_locked
                updated_fields.append("is_locked")
            
            if request.is_disabled is not None and request.is_disabled != layer.is_disabled:
                layer.is_disabled = request.is_disabled
                updated_fields.append("is_disabled")
            
            if request.is_empty_tray is not None and request.is_empty_tray != layer.is_empty_tray:
                layer.is_empty_tray = request.is_empty_tray
                updated_fields.append("is_empty_tray")
            
            if request.tags is not None and request.tags != layer.tags:
                layer.tags = request.tags
                updated_fields.append("tags")
            
            if request.description is not None and request.description != layer.description:
                layer.description = request.description
                updated_fields.append("description")
            
            # 更新扩展字段
            if request.extended_fields is not None:
                # 解析现有的config_json
                config = {}
                if layer.config_json:
                    try:
                        import json
                        config = json.loads(layer.config_json)
                    except Exception as e:
                        logger.error(f"解析库位层 {layer.id} 的config_json失败: {str(e)}")
                        config = {}
                
                # 确保extended_fields字段存在
                if 'extended_fields' not in config:
                    config['extended_fields'] = {}
                
                # 更新扩展字段
                for field_name, field_value in request.extended_fields.items():
                    if field_name in config['extended_fields']:
                        # 检查值是否真正发生了变化
                        current_value = config['extended_fields'][field_name].get('value')
                        if current_value != field_value:
                            config['extended_fields'][field_name]['value'] = field_value
                            config['extended_fields'][field_name]['updated_at'] = datetime.datetime.now().isoformat()
                            updated_fields.append(f"extended_fields.{field_name}")
                    else:
                        # 新增扩展字段（需要验证是否存在定义）
                        extended_property = db.query(ExtendedProperty).filter(
                            ExtendedProperty.property_name == field_name,
                            ExtendedProperty.is_deleted == False,
                            ExtendedProperty.is_enabled == True
                        ).first()
                        
                        if extended_property:
                            config['extended_fields'][field_name] = {
                                'value': field_value,
                                'type': extended_property.property_type.value,
                                'is_required': extended_property.is_required,
                                'updated_at': datetime.datetime.now().isoformat()
                            }
                            updated_fields.append(f"extended_fields.{field_name}")
                        else:
                            logger.warning(f"扩展字段 {field_name} 不存在或已禁用，跳过更新")
                
                # 只有当扩展字段确实发生了变化时才更新config_json
                if any(field.startswith("extended_fields.") for field in updated_fields):
                    try:
                        import json
                        layer.config_json = json.dumps(config, ensure_ascii=False, indent=2)
                    except Exception as e:
                        logger.error(f"序列化库位层 {layer.id} 的config_json失败: {str(e)}")
                        raise ValueError(f"更新扩展字段失败: {str(e)}")
            
            # 检查是否有实际的字段变更
            if not updated_fields:
                return {
                    "layer_name": layer_name,
                    "success": True,
                    "message": "没有字段发生变化，数据保持不变",
                    "updated_fields": [],
                    "updated_storage_location": OperatePointService._convert_to_storage_location_info(
                        layer, include_operate_point_info=True, include_extended_fields=True
                    )
                }
            
            # 更新最后修改时间
            layer.updated_at = datetime.datetime.now()
            updated_fields.append("updated_at")
            
            # 提交更改
            db.commit()
            
            # 记录操作日志
            try:
                operator = OperatePointService._get_operator(token=token)
                OperatePointService.create_storage_location_log(
                    db=db,
                    operator=operator,
                    operation_type="编辑库位",
                    affected_storage_locations=[layer_name],
                    description=f"编辑库位信息，更新字段: {', '.join(updated_fields)}"
                )
            except Exception as e:
                logger.error(f"记录操作日志失败: {str(e)}")
            
            # 获取更新后的库位信息
            updated_storage_location = OperatePointService._convert_to_storage_location_info(
                layer, include_operate_point_info=True, include_extended_fields=True
            )
            
            return {
                "layer_name": layer_name,
                "success": True,
                "message": f"库位信息更新成功，共更新 {len(updated_fields)} 个字段",
                "updated_fields": updated_fields,
                "updated_storage_location": updated_storage_location
            }
            
        except Exception as e:
            logger.error(f"编辑库位信息失败: {str(e)}")
            db.rollback()
            raise 

    @staticmethod
    def create_storage_location_log(
        db: Session,
        operator: str,
        operation_type: str,
        affected_storage_locations: List[str],
        description: Optional[str] = None
    ) -> StorageLocationLog:
        """
        创建库位操作记录
        
        Args:
            db: 数据库会话
            operator: 操作人
            operation_type: 操作类型
            affected_storage_locations: 影响的库位ID列表
            description: 操作描述
            
        Returns:
            StorageLocationLog: 创建的操作记录
        """
        try:
            import json
            
            # 创建操作记录
            log = StorageLocationLog(
                operator=operator,
                operation_type=operation_type,
                affected_storage_locations=json.dumps(affected_storage_locations, ensure_ascii=False),
                description=description
            )
            
            db.add(log)
            db.commit()
            
            return log
            
        except Exception as e:
            logger.error(f"创建库位操作记录失败: {str(e)}")
            db.rollback()
            raise

    @staticmethod
    def get_storage_location_logs(db: Session, request: StorageLocationLogListRequest) -> StorageLocationLogListResponse:
        """
        获取库位操作记录列表
        
        Args:
            db: 数据库会话
            request: 操作记录查询请求
            
        Returns:
            StorageLocationLogListResponse: 操作记录列表响应
        """
        try:
            # 构建查询条件
            query = db.query(StorageLocationLog).filter(StorageLocationLog.is_deleted == False)
            
            # 根据库位名称筛选
            if request.layer_name:
                # 先查找对应的库位ID
                location = db.query(OperatePointLayer).filter(
                    OperatePointLayer.layer_name == request.layer_name,
                    OperatePointLayer.is_deleted == False
                ).first()
                if location:
                    query = query.filter(StorageLocationLog.affected_storage_locations.like(f'%"{location.id}"%'))
                else:
                    # 如果找不到库位，返回空结果
                    query = query.filter(False)
            
            # 根据操作人筛选（模糊搜索）
            if request.operator:
                query = query.filter(StorageLocationLog.operator.like(f"%{request.operator}%"))
            
            # 根据操作类型筛选
            if request.operation_type:
                query = query.filter(StorageLocationLog.operation_type == request.operation_type)
            
            # 根据时间范围筛选
            if request.start_time:
                query = query.filter(StorageLocationLog.operation_time >= request.start_time)
            
            if request.end_time:
                query = query.filter(StorageLocationLog.operation_time <= request.end_time)
            
            # 按操作时间倒序排列
            query = query.order_by(StorageLocationLog.operation_time.desc())
            
            # 获取总数
            total = query.count()
            
            # 分页
            offset = (request.page - 1) * request.page_size
            logs = query.offset(offset).limit(request.page_size).all()
            
            # 转换为响应对象
            log_infos = []
            for log in logs:
                log_info = OperatePointService._convert_to_storage_location_log_info(log)
                log_infos.append(log_info)
            
            # 计算总页数
            total_pages = math.ceil(total / request.page_size) if total > 0 else 0
            
            return StorageLocationLogListResponse(
                total=total,
                page=request.page,
                page_size=request.page_size,
                total_pages=total_pages,
                logs=log_infos
            )
            
        except Exception as e:
            logger.error(f"获取库位操作记录列表失败: {str(e)}")
            raise

    @staticmethod
    def _convert_to_storage_location_log_info(log: StorageLocationLog) -> StorageLocationLogInfo:
        """
        将数据库模型转换为库位操作记录信息响应对象
        
        Args:
            log: 库位操作记录数据库模型
            
        Returns:
            StorageLocationLogInfo: 操作记录信息
        """
        try:
            import json
            
            # 解析影响的库位ID列表
            affected_storage_locations = []
            if log.affected_storage_locations:
                try:
                    affected_storage_locations = json.loads(log.affected_storage_locations)
                except Exception as e:
                    logger.error(f"解析影响库位列表失败: {str(e)}")
                    affected_storage_locations = []
            
            return StorageLocationLogInfo(
                id=str(log.id),
                operation_time=log.operation_time,
                operator=log.operator,
                operation_type=log.operation_type,
                affected_storage_locations=affected_storage_locations,
                description=log.description,
                created_at=log.created_at
            )
            
        except Exception as e:
            logger.error(f"转换库位操作记录信息失败: {str(e)}")
            raise

    @staticmethod
    def create_logical_storage_location(db: Session, request: LogicalStorageLocationCreateRequest) -> LogicalStorageLocationCreateResponse:
        """
        创建逻辑库位
        
        Args:
            db: 数据库会话
            request: 逻辑库位创建请求
            
        Returns:
            LogicalStorageLocationCreateResponse: 创建响应
        """
        try:
            # 检查库位名称是否已存在
            existing_location = db.query(OperatePointLayer).filter(
                OperatePointLayer.layer_name == request.layer_name,
                OperatePointLayer.is_deleted == False
            ).first()
            
            if existing_location:
                raise ValueError(f"库位名称 '{request.layer_name}' 已存在")
            
            # 检查场景ID是否存在
            scene_exists = db.query(OperatePoint).filter(
                OperatePoint.scene_id == request.scene_id,
                OperatePoint.is_deleted == False
            ).first()
            
            if not scene_exists:
                raise ValueError(f"场景ID '{request.scene_id}' 不存在")
            
            # 生成唯一的layer_index
            max_layer_index = db.query(func.max(OperatePointLayer.layer_index)).scalar() or 0
            new_layer_index = max_layer_index + 1
            
            # 创建逻辑库位
            # from utils.helpers import generate_unique_id
            import uuid
            o_id = str(uuid.uuid4())
            
            # 首先创建对应的虚拟OperatePoint记录（用于逻辑库位）
            virtual_operate_point = OperatePoint(
                id=o_id,
                station_name=request.station_name,
                scene_id=request.scene_id,
                storage_area_id=None,  # 逻辑库位可以不属于任何库区
                storage_area_type=None,
                area_name=request.area_name,
                max_layers=1,  # 逻辑库位只有一层
                current_layers=0,
                description=f"逻辑库位 {request.layer_name} 的虚拟动作点"
            )
            
            # 然后创建OperatePointLayer记录
            logical_location = OperatePointLayer(
                id=o_id,
                operate_point_id=o_id,  # 引用上面创建的虚拟动作点
                station_name=request.station_name,
                area_name=request.area_name,
                scene_id=request.scene_id,
                layer_index=new_layer_index,
                layer_name=request.layer_name,
                location_type=2,  # 逻辑库位
                max_weight=request.max_weight,
                max_volume=request.max_volume,
                layer_height=request.layer_height,
                tags=request.tags or '',
                description=request.description
            )
            
            db.add(virtual_operate_point)
            db.add(logical_location)
            db.commit()
            
            logger.info(f"成功创建逻辑库位: {request.layer_name}")
            
            return LogicalStorageLocationCreateResponse(
                id=logical_location.id,
                layer_name=logical_location.layer_name,
                location_type=2,
                message=f"逻辑库位 '{request.layer_name}' 创建成功"
            )
            
        except ValueError as e:
            logger.warning(f"创建逻辑库位参数错误: {str(e)}")
            raise
        except Exception as e:
            logger.error(f"创建逻辑库位失败: {str(e)}")
            db.rollback()
            raise

    @staticmethod
    def delete_logical_storage_location(db: Session, layer_name: str) -> LogicalStorageLocationDeleteResponse:
        """
        删除逻辑库位
        
        Args:
            db: 数据库会话
            layer_name: 库位名称
            
        Returns:
            LogicalStorageLocationDeleteResponse: 删除响应
        """
        try:
            # 查找库位
            storage_location = db.query(OperatePointLayer).filter(
                OperatePointLayer.layer_name == layer_name,
                OperatePointLayer.is_deleted == False
            ).first()
            
            if not storage_location:
                raise ValueError(f"库位 '{layer_name}' 不存在")
            
            # 检查是否为逻辑库位
            if storage_location.location_type != 2:
                raise ValueError(f"库位 '{layer_name}' 不是逻辑库位，物理库位不能删除")
            
            # 检查库位是否正在被占用
            if storage_location.is_occupied:
                raise ValueError(f"库位 '{layer_name}' 正在被占用，无法删除")
            
            # 检查库位是否被锁定
            if storage_location.is_locked:
                raise ValueError(f"库位 '{layer_name}' 已被锁定，无法删除")
            
            # 软删除库位
            storage_location.is_deleted = True
            storage_location.deleted_at = datetime.datetime.now()
            
            # 对于逻辑库位，还需要删除对应的虚拟动作点
            if storage_location.operate_point_id:
                virtual_operate_point = db.query(OperatePoint).filter(
                    OperatePoint.id == storage_location.operate_point_id
                ).first()
                if virtual_operate_point:
                    virtual_operate_point.is_deleted = True
                    virtual_operate_point.deleted_at = datetime.datetime.now()
            
            db.commit()
            
            logger.info(f"成功删除逻辑库位: {layer_name}")
            
            return LogicalStorageLocationDeleteResponse(
                id=storage_location.id,
                layer_name=storage_location.layer_name,
                location_type=2,
                message=f"逻辑库位 '{layer_name}' 删除成功"
            )
            
        except ValueError as e:
            logger.warning(f"删除逻辑库位参数错误: {str(e)}")
            raise
        except Exception as e:
            logger.error(f"删除逻辑库位失败: {str(e)}")
            db.rollback()
            raise


