# utils/logger.py
import logging
import os
import traceback
from logging.handlers import RotatingFileHandler
from config.settings import LogConfig

# 延迟导入告警同步服务，避免循环导入
_alert_sync_imported = False
_sync_alert_from_record = None

def _import_alert_sync():
    """延迟导入告警同步服务"""
    global _alert_sync_imported, _sync_alert_from_record
    if not _alert_sync_imported:
        try:
            from utils.alert_sync import sync_alert_from_record
            _sync_alert_from_record = sync_alert_from_record
            _alert_sync_imported = True
        except ImportError as e:
            print(f"告警同步模块导入失败: {e}")
            _alert_sync_imported = True  # 避免重复尝试

class LevelBasedFormatter(logging.Formatter):
    """
    基于日志级别的格式化器
    对不同级别的日志使用不同的格式
    """
    
    def __init__(self):
        # 普通日志格式
        self.normal_format = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        )
        # 详细日志格式（用于警告和错误）
        self.detailed_format = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(funcName)s() - %(message)s"
        )
    
    def format(self, record):
        # 如果是警告或错误级别，使用详细格式
        if record.levelno >= logging.WARNING:
            return self.detailed_format.format(record)
        else:
            return self.normal_format.format(record)


class AlertSyncHandler(logging.Handler):
    """
    告警同步处理器
    拦截WARNING及以上级别的日志，同步到主系统
    """
    
    def __init__(self):
        super().__init__()
        self.setLevel(logging.WARNING)  # 只处理WARNING及以上级别
        
    def emit(self, record):
        """
        处理日志记录，同步告警到主系统
        
        Args:
            record: 日志记录
        """
        try:
            # 延迟导入告警同步服务
            _import_alert_sync()
            
            # 如果告警同步服务可用，同步告警
            if _sync_alert_from_record:
                _sync_alert_from_record(record)
                
        except Exception:
            # 静默处理错误，避免影响正常日志记录
            pass

def setup_logger():
    """设置日志"""
    # 获取日志配置
    LOG_CONFIG = LogConfig.as_dict()
    
    # 创建日志目录
    log_dir = os.path.dirname(LOG_CONFIG["file"])
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    
    # 设置日志级别
    log_level = getattr(logging, LOG_CONFIG["level"].upper(), logging.INFO)
    
    # 设置日志格式 - 增加行号、函数名等信息
    log_format = logging.Formatter(LOG_CONFIG.get("format", "%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
    
    # 为警告和错误级别创建特殊格式
    detailed_format = logging.Formatter(
        "%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(funcName)s() - %(message)s"
    )
    
    # 创建根日志记录器
    root_logger = logging.getLogger()
    root_logger.setLevel(log_level)
    # 清除现有处理器
    for handler in root_logger.handlers[:]:
        root_logger.removeHandler(handler)
    
    # 添加控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(log_format)
    # 为警告及以上级别设置详细格式
    console_handler.setLevel(logging.INFO)
    root_logger.addHandler(console_handler)
    
    # 添加专门的错误控制台处理器，显示更多详细信息
    error_console_handler = logging.StreamHandler()
    error_console_handler.setFormatter(detailed_format)
    error_console_handler.setLevel(logging.WARNING)  # 只处理警告及以上级别
    root_logger.addHandler(error_console_handler)
    
    # 添加统一的文件处理器，使用基于级别的格式化器
    file_handler = RotatingFileHandler(
        LOG_CONFIG["file"],
        maxBytes=10 * 1024 * 1024,  # 10MB
        backupCount=5,
        encoding='utf-8'
    )
    # 使用自定义的格式化器，根据日志级别自动选择格式
    file_handler.setFormatter(LevelBasedFormatter())
    root_logger.addHandler(file_handler)
    
    # 添加告警同步处理器
    alert_sync_handler = AlertSyncHandler()
    root_logger.addHandler(alert_sync_handler)
    
    # 设置第三方库的日志级别
    logging.getLogger("werkzeug").setLevel(logging.WARNING)
    logging.getLogger("urllib3").setLevel(logging.WARNING)
    return root_logger

class Logger:
    """
    日志记录器类
    封装不同级别的日志记录功能
    """
    
    def __init__(self, name):
        """
        初始化日志记录器
        
        Args:
            name (str): 日志记录器名称，通常为模块名称
        """
        # 获取指定名称的日志记录器
        self.logger = logging.getLogger(name)
        self.name = name
        
    def debug(self, message, *args, **kwargs):
        """
        记录调试日志
        
        Args:
            message: 日志消息
            *args: 位置参数
            **kwargs: 关键字参数
        """
        self.logger.debug(message, *args, **kwargs)
    
    def info(self, message, *args, **kwargs):
        """
        记录一般信息日志
        
        Args:
            message: 日志消息
            *args: 位置参数
            **kwargs: 关键字参数
        """
        self.logger.info(message, *args, **kwargs)
    
    def warning(self, message, *args, exc_info=False, stack_info=False, **kwargs):
        """
        记录警告日志
        
        Args:
            message: 日志消息
            *args: 位置参数
            exc_info: 是否包含异常信息，默认False
            stack_info: 是否包含堆栈信息，默认False
            **kwargs: 关键字参数
        """
        # 默认启用堆栈信息以便显示行号
        # 如果不想显示整个堆栈跟踪，可以保持stack_info为False，系统会自动记录行号
        self.logger.warning(message, *args, exc_info=exc_info, stack_info=stack_info, **kwargs)
    
    def error(self, message, *args, exc_info=True, stack_info=True, **kwargs):
        """
        记录错误日志
        
        Args:
            message: 日志消息
            *args: 位置参数
            exc_info: 是否包含异常信息，默认True
            stack_info: 是否包含堆栈信息，默认True
            **kwargs: 关键字参数
        """
        # 由于我们已经在日志格式中添加了行号和文件名，这里不需要特殊处理
        self.logger.error(message, *args, exc_info=exc_info, stack_info=stack_info, **kwargs)
    
    def critical(self, message, *args, exc_info=True, stack_info=True, **kwargs):
        """
        记录严重错误日志
        
        Args:
            message: 日志消息
            *args: 位置参数
            exc_info: 是否包含异常信息，默认True
            stack_info: 是否包含堆栈信息，默认True
            **kwargs: 关键字参数
        """
        self.logger.critical(message, *args, exc_info=exc_info, stack_info=stack_info, **kwargs)
    
    def exception(self, message, *args, **kwargs):
        """
        记录异常日志，自动包含异常堆栈信息
        
        Args:
            message: 日志消息
            *args: 位置参数
            **kwargs: 关键字参数
        """
        self.logger.exception(message, *args, **kwargs)
    
    def log_error_with_trace(self, message, e=None):
        """
        记录带有详细追踪信息的错误日志
        
        Args:
            message: 日志消息
            e: 异常对象，可选
        """
        error_msg = f"{message}"
        if e:
            error_msg += f": {str(e)}"
        
        # 使用traceback模块获取完整的堆栈跟踪
        trace = traceback.format_exc()
        self.logger.error(f"{error_msg}\n{trace}")
    
    def log_startup(self, module_name, version=None):
        """
        记录模块启动日志
        
        Args:
            module_name: 模块名称
            version: 版本号，可选
        """
        version_str = f" v{version}" if version else ""
        self.logger.info(f"=== {module_name}{version_str} 启动完成 ===")
    
    def log_shutdown(self, module_name):
        """
        记录模块关闭日志
        
        Args:
            module_name: 模块名称
        """
        self.logger.info(f"=== {module_name} 已关闭 ===")

def get_logger(name):
    """
    获取指定名称的日志记录器
    
    Args:
        name (str): 日志记录器名称，通常为模块名称
        
    Returns:
        Logger: 日志记录器实例
    """
    # 确保全局日志配置已初始化
    setup_logger()
    
    # 创建并返回Logger实例
    return Logger(name)