# -*- coding: utf-8 -*-

"""
错误代码映射配置
用于为不同类型的错误分配固定的告警代码
"""

from typing import Dict, List, Tuple
import re

class ErrorCodeMapping:
    """错误代码映射管理器"""
    
    # 基础告警代码范围定义
    BASE_RANGES = {
        'system': (5400, 5499),     # 系统相关错误 5400-5499
        'task': (5500, 5699),       # 任务相关错误 5500-5699
        'robot': (5700, 5799),      # 机器人相关错误 5700-5799
        'database': (5800, 5849),   # 数据库相关错误 5800-5849
        'network': (5850, 5899),    # 网络相关错误 5850-5899
        'auth': (5900, 5949),       # 认证相关错误 5900-5949
        'validation': (5950, 5999), # 验证相关错误 5950-5999
    }
    
    # 错误类型和关键词映射
    ERROR_TYPE_PATTERNS = {
        # 任务相关错误
        'task_execution_failed': {
            'patterns': [
                r'任务执行失败',
                r'task execution failed',
                r'execute.*failed',
                r'执行.*失败',
            ],
            'code': 5500,
            'category': 'task'
        },
        'task_execution_timeout': {
            'patterns': [
                r'任务执行超时',
                r'task execution timeout',
                r'execute.*timeout',
                r'执行.*超时',
            ],
            'code': 5501,
            'category': 'task'
        },
        'task_scheduling_failed': {
            'patterns': [
                r'任务调度失败',
                r'task scheduling failed',
                r'调度.*失败',
                r'scheduling.*failed',
            ],
            'code': 5502,
            'category': 'task'
        },
        'task_not_found': {
            'patterns': [
                r'任务.*不存在',
                r'task.*not found',
                r'找不到.*任务',
                r'任务.*未找到',
            ],
            'code': 5503,
            'category': 'task'
        },
        'task_params_invalid': {
            'patterns': [
                r'任务参数.*无效',
                r'task parameters invalid',
                r'参数.*错误',
                r'invalid.*parameters',
            ],
            'code': 5504,
            'category': 'task'
        },
        'task_status_error': {
            'patterns': [
                r'任务状态.*错误',
                r'task status error',
                r'状态.*异常',
                r'status.*error',
            ],
            'code': 5505,
            'category': 'task'
        },
        'task_block_execution_failed': {
            'patterns': [
                r'块.*执行.*失败',
                r'block.*execution.*failed',
                r'任务块.*失败',
                r'block.*failed',
            ],
            'code': 5506,
            'category': 'task'
        },
        'task_template_error': {
            'patterns': [
                r'任务模板.*错误',
                r'task template error',
                r'模板.*异常',
                r'template.*error',
            ],
            'code': 5507,
            'category': 'task'
        },
        'task_sync_failed': {
            'patterns': [
                r'同步任务.*失败',
                r'sync.*task.*failed',
                r'同步任务到.*系统.*失败',
                r'任务同步.*失败',
            ],
            'code': 5508,
            'category': 'task'
        },
        'task_start_failed': {
            'patterns': [
                r'启动任务失败',
                r'start.*task.*failed',
                r'任务启动.*失败',
                r'task.*startup.*failed',
            ],
            'code': 5509,
            'category': 'task'
        },
        'task_run_failed': {
            'patterns': [
                r'运行任务失败',
                r'run.*task.*failed',
                r'任务运行.*失败',
                r'task.*execution.*failed',
            ],
            'code': 5510,
            'category': 'task'
        },
        'task_scene_id_not_exist': {
            'patterns': [
                r'此场景id不存在',
                r'场景.*不存在',
                r'scene.*id.*not.*exist',
                r'scene.*not.*found',
            ],
            'code': 5511,
            'category': 'task'
        },
        'task_child_block_failed': {
            'patterns': [
                r'子块.*执行失败',
                r'child.*block.*failed',
                r'子块.*失败',
                r'child.*execution.*failed',
            ],
            'code': 5512,
            'category': 'task'
        },
        
        # 机器人相关错误
        'robot_connection_failed': {
            'patterns': [
                r'机器人.*连接.*失败',
                r'robot.*connection.*failed',
                r'AGV.*连接.*失败',
                r'vehicle.*connection.*failed',
            ],
            'code': 5700,
            'category': 'robot'
        },
        'robot_battery_low': {
            'patterns': [
                r'机器人.*电池.*低',
                r'robot.*battery.*low',
                r'AGV.*电量.*低',
                r'电池.*不足',
            ],
            'code': 5701,
            'category': 'robot'
        },
        'robot_navigation_failed': {
            'patterns': [
                r'机器人.*导航.*失败',
                r'robot.*navigation.*failed',
                r'AGV.*导航.*失败',
                r'导航.*异常',
            ],
            'code': 5702,
            'category': 'robot'
        },
        'robot_task_failed': {
            'patterns': [
                r'机器人.*任务.*失败',
                r'robot.*task.*failed',
                r'AGV.*任务.*失败',
                r'机器人.*执行.*失败',
            ],
            'code': 5703,
            'category': 'robot'
        },
        'robot_select_amr_failed': {
            'patterns': [
                r'为任务选择AMR失败',
                r'选择.*AMR.*失败',
                r'select.*amr.*failed',
                r'amr.*selection.*failed',
            ],
            'code': 5704,
            'category': 'robot'
        },
        'robot_select_execution_failed': {
            'patterns': [
                r'选择执行机器人失败',
                r'选择.*机器人.*失败',
                r'robot.*selection.*failed',
                r'select.*execution.*robot.*failed',
            ],
            'code': 5705,
            'category': 'robot'
        },
        'robot_tianfeng_task_id_not_exist': {
            'patterns': [
                r'此天风任务id不存在',
                r'天风任务.*不存在',
                r'tianfeng.*task.*id.*not.*exist',
                r'tianfeng.*task.*not.*found',
            ],
            'code': 5706,
            'category': 'robot'
        },
        'robot_block_action_detail_failed': {
            'patterns': [
                r'调用获取任务块动作详情接口失败',
                r'获取任务块动作.*详情.*失败',
                r'task.*block.*action.*detail.*failed',
                r'get.*task.*block.*action.*failed',
            ],
            'code': 5707,
            'category': 'robot'
        },
        'robot_block_detail_failed': {
            'patterns': [
                r'调用获取任务块详情接口失败',
                r'获取任务块.*详情.*失败',
                r'task.*block.*detail.*failed',
                r'get.*task.*block.*failed',
            ],
            'code': 5708,
            'category': 'robot'
        },
        
        # 数据库相关错误
        'database_connection_failed': {
            'patterns': [
                r'数据库.*连接.*失败',
                r'database.*connection.*failed',
                r'DB.*连接.*失败',
                r'连接.*数据库.*失败',
            ],
            'code': 5800,
            'category': 'database'
        },
        'database_query_failed': {
            'patterns': [
                r'数据库.*查询.*失败',
                r'database.*query.*failed',
                r'SQL.*执行.*失败',
                r'查询.*失败',
            ],
            'code': 5801,
            'category': 'database'
        },
        'database_transaction_failed': {
            'patterns': [
                r'数据库.*事务.*失败',
                r'database.*transaction.*failed',
                r'事务.*回滚',
                r'transaction.*rollback',
            ],
            'code': 5802,
            'category': 'database'
        },
        
        # 网络相关错误
        'network_connection_failed': {
            'patterns': [
                r'网络.*连接.*失败',
                r'network.*connection.*failed',
                r'连接.*超时',
                r'connection.*timeout',
            ],
            'code': 5850,
            'category': 'network'
        },
        'network_request_failed': {
            'patterns': [
                r'网络.*请求.*失败',
                r'network.*request.*failed',
                r'HTTP.*请求.*失败',
                r'request.*failed',
            ],
            'code': 5851,
            'category': 'network'
        },
        'network_timeout': {
            'patterns': [
                r'网络.*超时',
                r'network.*timeout',
                r'请求.*超时',
                r'request.*timeout',
                r'TimeoutError',
                r'CancelledError',
            ],
            'code': 5852,
            'category': 'network'
        },
        'network_connect_refused': {
            'patterns': [
                r'ConnectionRefusedError',
                r'Connect call failed',
                r'Cannot connect to host',
                r'连接.*被拒绝',
                r'connection.*refused',
            ],
            'code': 5853,
            'category': 'network'
        },
        'network_api_call_failed': {
            'patterns': [
                r'调用.*接口失败',
                r'调用.*API.*失败',
                r'api.*call.*failed',
                r'interface.*call.*failed',
                r'调用系统任务创建任务接口失败',
            ],
            'code': 5854,
            'category': 'network'
        },
        
        # 系统相关错误
        'system_resource_exhausted': {
            'patterns': [
                r'系统.*资源.*耗尽',
                r'system.*resource.*exhausted',
                r'内存.*不足',
                r'memory.*insufficient',
            ],
            'code': 5400,
            'category': 'system'
        },
        'system_configuration_error': {
            'patterns': [
                r'系统.*配置.*错误',
                r'system.*configuration.*error',
                r'配置.*异常',
                r'configuration.*error',
            ],
            'code': 5401,
            'category': 'system'
        },
        'system_service_unavailable': {
            'patterns': [
                r'系统.*服务.*不可用',
                r'system.*service.*unavailable',
                r'服务.*不可用',
                r'service.*unavailable',
            ],
            'code': 5402,
            'category': 'system'
        },
        
        # 认证相关错误
        'auth_token_invalid': {
            'patterns': [
                r'认证.*令牌.*无效',
                r'auth.*token.*invalid',
                r'token.*过期',
                r'token.*expired',
            ],
            'code': 5900,
            'category': 'auth'
        },
        'auth_permission_denied': {
            'patterns': [
                r'权限.*拒绝',
                r'permission.*denied',
                r'访问.*被拒绝',
                r'access.*denied',
            ],
            'code': 5901,
            'category': 'auth'
        },
        
        # 验证相关错误
        'validation_parameter_invalid': {
            'patterns': [
                r'参数.*验证.*失败',
                r'parameter.*validation.*failed',
                r'参数.*无效',
                r'invalid.*parameter',
            ],
            'code': 5950,
            'category': 'validation'
        },
        'validation_data_format_error': {
            'patterns': [
                r'数据.*格式.*错误',
                r'data.*format.*error',
                r'格式.*不正确',
                r'format.*invalid',
            ],
            'code': 5951,
            'category': 'validation'
        },
        
        # 程序错误相关
        'program_attribute_error': {
            'patterns': [
                r'AttributeError',
                r'\'.*\' object has no attribute \'.*\'',
                r'属性.*错误',
                r'attribute.*error',
                r'\'NoneType\' object has no attribute \'get\'',
            ],
            'code': 5952,
            'category': 'validation'
        },
        'program_type_error': {
            'patterns': [
                r'TypeError',
                r'类型.*错误',
                r'type.*error',
                r'NoneType.*object',
            ],
            'code': 5953,
            'category': 'validation'
        },
        'program_runtime_error': {
            'patterns': [
                r'RuntimeError',
                r'运行时.*错误',
                r'runtime.*error',
                r'执行时.*错误',
            ],
            'code': 5954,
            'category': 'validation'
        },
    }
    
    # 模块特定的错误代码偏移
    MODULE_OFFSETS = {
        'services.task_service': 0,
        'services.task_execution': 5,
        'services.task_scheduler': 10,
        'services.enhanced_scheduler.task_scheduler': 15,
        'services.task_edit_service': 20,
        'services.sync_service': 25,
        'services.robot_scheduler': 30,
        'services.calldevice_service': 35,
        'services.modbus_config_service': 40,
        'services.script_service': 45,
        'services.execution.block_executor': 50,
        'services.execution.task_executor': 55,
        'routes.task_api': 60,
        'routes.task_edit_api': 65,
        'routes.calldevice_api': 70,
        'routes.modbus_config_api': 75,
        'app.task_edit_api': 80,
        'middlewares.error_handlers': 85,
        'middleware.request_logger': 90,
        'utils.alert_sync': 95,
        'data.models': 100,
        'data.session': 105,
        'core.intelligence': 110,
    }
    
    @classmethod
    def get_error_code(cls, logger_name: str, message: str) -> int:
        """
        根据logger名称和消息内容获取错误代码
        
        Args:
            logger_name: logger名称
            message: 错误消息
            
        Returns:
            错误代码
        """
        # 首先尝试匹配错误类型
        error_type = cls._match_error_type(message)
        
        if error_type:
            # 获取基础代码
            base_code = cls.ERROR_TYPE_PATTERNS[error_type]['code']
            
            # 根据模块添加偏移量
            module_offset = cls._get_module_offset(logger_name)
            
            # 确保代码在合理范围内
            final_code = base_code + module_offset
            
            # 确保不超过最大值
            if final_code > 9999:
                final_code = base_code
                
            return final_code
        
        # 如果没有匹配的错误类型，使用通用代码生成
        return cls._generate_fallback_code(logger_name, message)
    
    @classmethod
    def _match_error_type(cls, message: str) -> str:
        """
        匹配错误类型
        
        Args:
            message: 错误消息
            
        Returns:
            错误类型名称，如果没有匹配则返回None
        """
        message_lower = message.lower()
        
        for error_type, config in cls.ERROR_TYPE_PATTERNS.items():
            for pattern in config['patterns']:
                if re.search(pattern, message_lower, re.IGNORECASE):
                    return error_type
        
        return None
    
    @classmethod
    def _get_module_offset(cls, logger_name: str) -> int:
        """
        获取模块的偏移量
        
        Args:
            logger_name: logger名称
            
        Returns:
            偏移量
        """
        # 尝试精确匹配
        if logger_name in cls.MODULE_OFFSETS:
            return cls.MODULE_OFFSETS[logger_name]
        
        # 尝试部分匹配
        for module, offset in cls.MODULE_OFFSETS.items():
            if logger_name.startswith(module):
                return offset
        
        return 0
    
    @classmethod
    def _generate_fallback_code(cls, logger_name: str, message: str) -> int:
        """
        生成备用错误代码（用于无法匹配的错误）
        
        Args:
            logger_name: logger名称
            message: 错误消息
            
        Returns:
            错误代码
        """
        import hashlib
        
        # 使用简化的消息内容生成代码
        simplified_message = cls._simplify_message(message)
        hash_input = f"{logger_name}:{simplified_message}"
        hash_value = hashlib.md5(hash_input.encode()).hexdigest()
        
        # 生成在6000-6999范围内的代码（未分类错误）
        code = int(hash_value[:4], 16) % 1000 + 6000
        return code
    
    @classmethod
    def _simplify_message(cls, message: str) -> str:
        """
        简化错误消息，去除变量部分
        
        Args:
            message: 原始错误消息
            
        Returns:
            简化后的消息
        """
        # 移除常见的变量部分
        simplified = re.sub(r'\d+', '[NUMBER]', message)  # 替换数字
        simplified = re.sub(r'[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}', '[UUID]', simplified)  # 替换UUID
        simplified = re.sub(r'/[^/\s]+', '[PATH]', simplified)  # 替换路径
        simplified = re.sub(r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}', '[IP]', simplified)  # 替换IP地址
        simplified = re.sub(r'\s+', ' ', simplified).strip()  # 清理空白字符
        
        return simplified
    
    @classmethod
    def get_error_info(cls, error_code: int) -> Dict:
        """
        根据错误代码获取错误信息
        
        Args:
            error_code: 错误代码
            
        Returns:
            错误信息字典
        """
        # 查找匹配的错误类型
        for error_type, config in cls.ERROR_TYPE_PATTERNS.items():
            if config['code'] <= error_code < config['code'] + 200:  # 允许偏移量
                return {
                    'error_type': error_type,
                    'category': config['category'],
                    'base_code': config['code'],
                    'description': f"{config['category']}相关错误: {error_type}"
                }
        
        # 根据代码范围确定类别
        for category, (start, end) in cls.BASE_RANGES.items():
            if start <= error_code <= end:
                return {
                    'error_type': 'unknown',
                    'category': category,
                    'base_code': start,
                    'description': f"{category}相关错误"
                }
        
        return {
            'error_type': 'unknown',
            'category': 'unknown',
            'base_code': error_code,
            'description': '未知错误'
        } 