"""Pytola 的日志模块.

本模块提供一个简单的、类似 loguru 的日志系统，具有彩色输出、
文件轮转和易于使用的 API。
"""

from __future__ import annotations

import contextlib
import logging
import logging.handlers
import sys
from pathlib import Path
from typing import ClassVar, Final

__all__ = ["get_logger", "logger"]

# Log file configuration
LOG_DIR: Final[Path] = Path.home() / ".pytola" / "logs"
LOG_FILE: Final[Path] = LOG_DIR / "pytola.log"
MAX_BYTES: Final[int] = 10 * 1024 * 1024  # 10MB
BACKUP_COUNT: Final[int] = 5


class _Logger:
    """一个简单的、类似 loguru 的日志器.

    提供干净、最小化的 API，用于带有自动控制台颜色和文件轮转的日志记录。

    示例
    --------
        >>> from pytola_core.logger import logger
        >>> logger.info("Hello, World!")
        >>> logger.debug("Debug message")  # 仅在启用调试时显示
        >>> logger.error("Error occurred")
    """

    _instance: logging.Logger | None = None

    COLORS: ClassVar[dict[str, str]] = {
        "DEBUG": "\033[36m",  # CYAN
        "INFO": "\033[32m",  # GREEN
        "WARNING": "\033[33m",  # YELLOW
        "ERROR": "\033[31m",  # RED
        "CRITICAL": "\033[41m",  # White on Red Background
        "RESET": "\033[0m",  # RESET COLOR
    }

    @classmethod
    def setup(cls, name: str = "pytola", level: int = logging.INFO) -> logging.Logger:
        """设置带有控制台和文件处理器的日志器.

        此方法应在应用程序启动时调用一次。
        后续调用将返回现有的日志器实例。

        参数
        ----------
        name : str
            日志器名称。默认为 "pytola"
        level : int
            最低日志级别。默认为 INFO
            使用 logger.DEBUG 获取更详细的输出

        返回
        -------
        logging.Logger
            配置好的带有控制台和文件处理器的日志器

        示例
        --------
            >>> from pytola_core.logger import Logger
            >>> logger = Logger.setup(level=Logger.DEBUG)
        """
        if cls._instance is not None:
            return cls._instance

        # Ensure log directory exists
        with contextlib.suppress(OSError):
            LOG_DIR.mkdir(parents=True, exist_ok=True)

        class _ColoredFormatter(logging.Formatter):
            """自定义格式化器，为日志消息添加 ANSI 颜色."""

            def format(self, record: logging.LogRecord) -> str:
                """使用适当的颜色格式化日志记录."""
                # 根据日志级别应用颜色
                log_color = cls.COLORS.get(record.levelname, cls.COLORS["RESET"])

                # 首先格式化消息
                message = super().format(record)

                # 将整个消息包装在级别颜色中
                return f"{log_color}{message}{cls.COLORS['RESET']}"

        # 创建日志器
        logger = logging.getLogger(name)
        logger.setLevel(logging.DEBUG)  # 捕获所有级别，在处理器级别过滤

        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(level)
        console_formatter = _ColoredFormatter("%(asctime)s | %(levelname)-8s | %(message)s", datefmt="%H:%M:%S")
        console_handler.setFormatter(console_formatter)

        # 文件处理器 - 捕获所有 DEBUG+ 日志并带轮转功能
        file_handler = logging.handlers.RotatingFileHandler(
            LOG_FILE,
            maxBytes=MAX_BYTES,
            backupCount=BACKUP_COUNT,
            encoding="utf-8",
        )
        file_handler.setLevel(logging.DEBUG)
        file_formatter = logging.Formatter(
            "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
            datefmt="%Y-%m-%d %H:%M:%S",
        )
        file_handler.setFormatter(file_formatter)

        # 添加处理器
        logger.addHandler(console_handler)
        logger.addHandler(file_handler)

        # 防止多次添加处理器
        logger.propagate = False

        cls._instance = logger
        return logger

    @classmethod
    def get_logger(cls, name: str = "pytola") -> logging.Logger:
        """获取日志器实例.

        如果日志器尚未设置，此方法将使用默认设置进行设置。
        如需自定义配置，请改用 `Logger.setup()`。

        参数:
            name: 日志器名称。默认为 "pytola"

        返回
        -------
            配置好的日志器实例
        """
        if cls._instance is None:
            return cls.setup(name)
        return cls._instance


# 预配置的日志器实例，便于导入
logger: logging.Logger = _Logger.get_logger()

# 为日志器对象添加便利属性（类似 loguru）
# 这些是动态添加的，以便更容易访问日志级别
setattr(logger, "DEBUG", logging.DEBUG)  # noqa: B010
setattr(logger, "INFO", logging.INFO)  # noqa: B010
setattr(logger, "WARNING", logging.WARNING)  # noqa: B010
setattr(logger, "ERROR", logging.ERROR)  # noqa: B010
setattr(logger, "CRITICAL", logging.CRITICAL)  # noqa: B010

get_logger = _Logger.get_logger
