from __future__ import annotations

import logging
import os
import threading
from datetime import datetime
from typing import Optional


# stdlib 级别 → PQLogGUI 标签
_LEVEL_TO_GUI = {
    logging.DEBUG: "debug",
    logging.INFO: "info",
    logging.WARNING: "warning",
    logging.ERROR: "error",
    logging.CRITICAL: "error",
}

# PQLogGUI 标签 → stdlib 级别
GUI_LEVEL_TO_LOG = {
    "debug": logging.DEBUG,
    "info": logging.INFO,
    "success": logging.INFO,
    "warning": logging.WARNING,
    "error": logging.ERROR,
    "separator": logging.INFO,
    "blank": logging.DEBUG,
}

# 用于在 LogRecord 上做 GUI 来源标记，避免回环
_FROM_GUI_FLAG = "_from_gui"

# 文件日志：头一行元信息，第二行正文，记录之间空行隔开，方便阅读
_FILE_LOG_FORMAT = "%(asctime)s [%(levelname)s] %(name)s\n%(message)s\n"
_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"

_initialized = False


def _resolve_log_dir(log_dir: Optional[str]) -> str:
    if log_dir:
        return log_dir
    # 默认放在工作目录下的 log/，方便用户直接打开查看
    return os.path.join(os.getcwd(), "log")


def setup_logging(
    level: int = logging.INFO,
    log_dir: Optional[str] = None,
) -> str:
    """配置全局 logging，返回日志目录。可重复调用，第二次起为空操作。

    - 不再向终端输出，避免污染控制台。
    - 日志文件按日期命名：``log/YYYY-MM-DD.log``。
    """
    global _initialized
    root = logging.getLogger()
    if _initialized:
        return _resolve_log_dir(log_dir)

    resolved = _resolve_log_dir(log_dir)
    os.makedirs(resolved, exist_ok=True)

    file_formatter = logging.Formatter(_FILE_LOG_FORMAT, datefmt=_DATE_FORMAT)

    root.setLevel(level)

    # 移除既有 handler，避免重复 / basicConfig 默认控制台输出
    for handler in list(root.handlers):
        root.removeHandler(handler)

    today = datetime.now().strftime("%Y-%m-%d")
    log_file = os.path.join(resolved, f"{today}.log")
    file_handler = logging.FileHandler(log_file, encoding="utf-8", delay=True)
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(file_formatter)
    root.addHandler(file_handler)

    _initialized = True
    logging.getLogger(__name__).info("日志系统初始化完成 dir=%s", resolved)
    return resolved


class TkLogHandler(logging.Handler):
    """把 stdlib logging 的记录转发到 ``PQLogGUI`` 面板。

    带 ``_from_gui`` 标记的记录会被忽略，避免 GUI → file → GUI 回环。
    """

    def __init__(self, log_gui):
        super().__init__()
        self._log_gui = log_gui

    def emit(self, record: logging.LogRecord) -> None:  # noqa: D401
        if getattr(record, _FROM_GUI_FLAG, False):
            return
        # Tkinter widgets are not thread-safe. Forwarding background-thread logs
        # into GUI controls may block/hang the worker thread. Keep those logs in
        # file handlers only, and only mirror main-thread logs to GUI.
        if threading.current_thread() is not threading.main_thread():
            return
        try:
            message = self.format(record)
        except Exception:
            try:
                message = record.getMessage()
            except Exception:
                return
        gui_level = _LEVEL_TO_GUI.get(record.levelno, "info")
        try:
            # PQLogGUI.log 内部已处理跨线程
            self._log_gui.log(message, level=gui_level, _from_logging=True)
        except Exception:
            self.handleError(record)


def attach_gui_handler(log_gui) -> TkLogHandler:
    """把 ``PQLogGUI`` 注册为 root logger 的 handler。已存在则替换。"""
    root = logging.getLogger()
    # 移除旧的 TkLogHandler，保证只挂一个
    for h in list(root.handlers):
        if isinstance(h, TkLogHandler):
            root.removeHandler(h)
    handler = TkLogHandler(log_gui)
    handler.setLevel(logging.INFO)
    handler.setFormatter(logging.Formatter("%(name)s: %(message)s"))
    root.addHandler(handler)
    return handler
