import t, c
from stdint import *
import stdio
import stdlib
import memhub
import sys
import w32.win32console as w32cmd
import w32.win32file as w32file
import w32.win32base as win32base


# ============================================================
# VLogger - 原生日志系统（Windows 控制台彩色输出）
#
# 输出格式与 TPC (lib/core/VLogger.py) 对齐：
#   ├ INFO: message
#   ├ INFO[category]: message
#   ├ WARN: message
#   ├ ERROR: message
#   ├ SUCCESS: message
#   ├ DEBUG: message
#   ╠ CRITICAL: message        (红底白字，致命错误)
#   ╠ CRITICAL[category]: message
#
# 分段着色：前缀符号(├/╠) 用级别色，LEVEL 标签用亮色，消息用默认色
# CRITICAL 级别使用 ╠ 前缀和红底白字标签，与 TPC critical 对齐
# ============================================================

# 日志级别
class LogLevel(t.CEnum):
    DEBUG = 0
    INFO = 1
    WARNING = 2
    ERROR = 3
    SUCCESS = 4
    CRITICAL = 5


# Win32 控制台前景色属性
FOREGROUND_BLUE: t.CDefine = 0x0001
FOREGROUND_GREEN: t.CDefine = 0x0002
FOREGROUND_RED: t.CDefine = 0x0004
FOREGROUND_INTENSITY: t.CDefine = 0x0008
FOREGROUND_WHITE: t.CDefine = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
FOREGROUND_CYAN: t.CDefine = FOREGROUND_BLUE | FOREGROUND_GREEN
FOREGROUND_YELLOW: t.CDefine = FOREGROUND_RED | FOREGROUND_GREEN
FOREGROUND_MAGENTA: t.CDefine = FOREGROUND_RED | FOREGROUND_BLUE

# Win32 控制台背景色属性
BACKGROUND_RED: t.CDefine = 0x0040
BACKGROUND_GREEN: t.CDefine = 0x0020
BACKGROUND_BLUE: t.CDefine = 0x0010
BACKGROUND_INTENSITY: t.CDefine = 0x0080
BACKGROUND_WHITE: t.CDefine = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE


@t.NoVTable
class Logger:
    _level: int
    _console_handle: win32base.HANDLE
    _use_color: int
    __mbuddy__: memhub.MemBuddy | t.CPtr

    def __init__(self, level: int = 1):
        self._level = level
        self._console_handle = w32file.GetStdHandle(w32file.STD_OUTPUT_HANDLE)
        self._use_color = 1
        self.__mbuddy__ = _mbuddy

    def _set_color(self, attr: WORD) -> int:
        uc: int = self._use_color
        if uc:
            ch: win32base.HANDLE = self._console_handle
            ret: int = w32cmd.SetConsoleTextAttribute(ch, attr)
            return ret
        return 0

    def _reset_color(self) -> int:
        if self._use_color:
            return w32cmd.SetConsoleTextAttribute(self._console_handle, FOREGROUND_WHITE)
        return 0

    # ============================================================
    # _log - 核心日志输出（分段着色）
    #
    # 格式: ├ LEVEL: msg  或  ├ LEVEL[category]: msg
    # 分三段着色:
    #   1. 前缀符号 ├ (sym_color)
    #   2. LEVEL 标签 (level_color)
    #   3. 消息内容 (默认白色)
    # ============================================================
    def _log(self, level: int, prefix_sym: str, level_str: str, msg: str,
             sym_color: WORD, level_color: WORD,
             category: str = "") -> int:
        # 前缀符号着色
        self._set_color(sym_color)
        stdio.printf("%s ", prefix_sym)
        # LEVEL 标签着色
        self._set_color(level_color)
        stdio.printf("%s", level_str)
        self._reset_color()
        # category 可选
        if category is not None and category[0] != 0:
            stdio.printf(" [%s]", category)
        stdio.printf(": %s\n", msg)
        return 0

    def debug(self, msg: str, category: str = "") -> int:
        return self._log(LogLevel.DEBUG, "├", "DEBUG", msg,
                         FOREGROUND_INTENSITY, FOREGROUND_INTENSITY, category)

    def info(self, msg: str, category: str = "") -> int:
        ret: int = self._log(LogLevel.INFO, "├", "INFO", msg,
                             FOREGROUND_GREEN,
                             FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)
        return ret

    def warning(self, msg: str, category: str = "") -> int:
        return self._log(LogLevel.WARNING, "├", "WARN", msg,
                         FOREGROUND_YELLOW,
                         FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
                         category)

    def error(self, msg: str, category: str = "") -> int:
        ret: int = self._log(LogLevel.ERROR, "├", "ERROR", msg,
                             FOREGROUND_RED,
                             FOREGROUND_RED | FOREGROUND_INTENSITY, category)
        # 错误立即终止进程（避免错误后继续执行导致连锁崩溃）
        sys.exit(1)
        return ret

    def success(self, msg: str, category: str = "") -> int:
        return self._log(LogLevel.SUCCESS, "├", "SUCCESS", msg,
                         FOREGROUND_GREEN,
                         FOREGROUND_GREEN | FOREGROUND_INTENSITY, category)

    def critical(self, msg: str, category: str = "") -> int:
        # CRITICAL 使用 ╠ 前缀（红底白字标签，对齐 TPC critical 风格）
        return self._log(LogLevel.CRITICAL, "╠", "CRITICAL", msg,
                         FOREGROUND_RED,
                         BACKGROUND_RED | FOREGROUND_WHITE | FOREGROUND_INTENSITY,
                         category)

    def set_level(self, level: int) -> int:
        self._level = level
        return 0

    # ============================================================
    # 高级日志方法
    # ============================================================

    def banner(self, msg: str) -> int:
        """输出分节标题（蓝色高亮，与 TPC banner 风格对齐）。"""
        self._set_color(FOREGROUND_BLUE | FOREGROUND_INTENSITY)
        stdio.printf("\n=== %s ===\n\n", msg)
        self._reset_color()
        return 0

    def compile_error(self, msg: str, file: str = "", line: int = 0) -> int:
        """格式化编译错误输出（红底白字标题 + 位置 + 错误信息）。"""
        self._set_color(BACKGROUND_RED | FOREGROUND_WHITE | FOREGROUND_INTENSITY)
        stdio.printf(" 编译错误 ")
        self._set_color(FOREGROUND_RED | FOREGROUND_INTENSITY)
        stdio.printf("\n")
        if file is not None:
            if file[0] != 0 and line > 0:
                stdio.printf("  位置: %s:%d\n", file, line)
            elif file[0] != 0:
                stdio.printf("  文件: %s\n", file)
        stdio.printf("  错误: %s\n", msg)
        self._reset_color()
        return 0

    def compile_warning(self, msg: str, file: str = "", line: int = 0) -> int:
        """格式化编译警告输出（黄底黑字标题 + 位置 + 警告信息）。"""
        self._set_color(BACKGROUND_RED | BACKGROUND_GREEN | FOREGROUND_INTENSITY)
        stdio.printf(" 编译警告 ")
        self._set_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY)
        stdio.printf("\n")
        if file is not None:
            if file[0] != 0 and line > 0:
                stdio.printf("  位置: %s:%d\n", file, line)
            elif file[0] != 0:
                stdio.printf("  文件: %s\n", file)
        stdio.printf("  警告: %s\n", msg)
        self._reset_color()
        return 0


# 全局 mbuddy 指针（由 lib.InitLib 注入）
_mbuddy: memhub.MemBuddy | t.CPtr

# 全局 logger 指针
_g_logger: Logger | t.CPtr

# 全局格式化缓冲区（用于带变量的日志消息，1024 字节）
_fmt_buf: t.CChar | t.CPtr


def fmt_buf() -> t.CChar | t.CPtr:
    """获取全局格式化缓冲区（1024 字节）。

    用法:
        buf: t.CChar | t.CPtr = VLogger.fmt_buf()
        if buf is not None:
            viperlib.snprintf(buf, 1024, "翻译: %s (sha1=%s)", rp, sha1)
            log.info(buf, "Phase1")
    """
    global _fmt_buf
    if _fmt_buf is None:
        _fmt_buf = stdlib.malloc(1024)
    return _fmt_buf


def get_logger() -> Logger | t.CPtr:
    """获取全局 logger 实例。若不存在则通过 _mbuddy 分配并初始化。"""
    global _g_logger
    if _g_logger is None:
        if _mbuddy is None:
            return None
        raw: t.CVoid | t.CPtr = _mbuddy.alloc(Logger.__sizeof__())
        if raw is None:
            return None
        _g_logger = raw
        _g_logger.__before_init__()
        _g_logger.__init__(LogLevel.INFO)
    return _g_logger


def set_logger(logger: Logger | t.CPtr) -> int:
    """设置全局 logger 实例。"""
    global _g_logger
    _g_logger = logger
    return 0


# ============================================================
# 模块级便捷函数（与 TPC 的 lib.core.VLogger 对齐）
#
# 调用方式: VLogger.info("msg", "category")
# 无需先 get_logger()，方便各模块直接使用
# ============================================================

def info(msg: str, category: str = "") -> int:
    """输出 INFO 级别日志。"""
    log: Logger | t.CPtr = get_logger()
    if log is not None:
        return log.info(msg, category)
    return 0


def warning(msg: str, category: str = "") -> int:
    """输出 WARN 级别日志。"""
    log: Logger | t.CPtr = get_logger()
    if log is not None:
        return log.warning(msg, category)
    return 0


def error(msg: str, category: str = "") -> int:
    """输出 ERROR 级别日志并立即终止进程。"""
    log: Logger | t.CPtr = get_logger()
    if log is not None:
        return log.error(msg, category)
    # logger 不可用时也直接退出
    sys.exit(1)
    return 0


def success(msg: str, category: str = "") -> int:
    """输出 SUCCESS 级别日志。"""
    log: Logger | t.CPtr = get_logger()
    if log is not None:
        return log.success(msg, category)
    return 0


def critical(msg: str, category: str = "") -> int:
    """输出 CRITICAL 级别日志（致命错误，红底白字）。"""
    log: Logger | t.CPtr = get_logger()
    if log is not None:
        return log.critical(msg, category)
    return 0


def debug(msg: str, category: str = "") -> int:
    """输出 DEBUG 级别日志。"""
    log: Logger | t.CPtr = get_logger()
    if log is not None:
        return log.debug(msg, category)
    return 0
