"""
测试日志模块
"""

import json
import logging
from collections.abc import Generator
from io import StringIO

import pytest

from databuilder_logic_sdk.utils.log_utils import JsonFormatter, Logger, NormalFormatter, logger


@pytest.fixture(autouse=True)
def reset_logger_level() -> Generator[None, None, None]:
    """在每个测试前后重置 logger 级别"""
    logger.setLevel(logging.DEBUG)  # 重置为 DEBUG
    yield
    logger.setLevel(logging.DEBUG)  # 测试后恢复


def test_logger_info(caplog: pytest.LogCaptureFixture) -> None:
    """测试 logger 的 info 方法"""
    with caplog.at_level(logging.INFO):
        logger.info("This is an info message for testing.")
        logger.debug("This is a debug message for testing.")
        logger.warning("This is a warning message for testing.")
        logger.error("This is an error message for testing.")
        logger.critical("This is a critical message for testing.")

    # 断言日志记录数量
    assert len(caplog.records) == 4  # debug 不会被记录（因为 at_level 设置为 INFO）

    # 断言特定消息存在
    assert "This is an info message for testing." in caplog.text
    assert "This is a warning message for testing." in caplog.text

    # 断言日志级别
    assert caplog.records[0].levelname == "INFO"
    assert caplog.records[2].levelname == "ERROR"


def test_logger_level(caplog: pytest.LogCaptureFixture) -> None:
    """测试 logger 的 set_level 方法"""
    # 测试 DEBUG 级别
    logger.setLevel(10)  # DEBUG
    caplog.clear()
    with caplog.at_level(logging.DEBUG):
        logger.debug("This debug message should appear.")
        assert len(caplog.records) == 1
        assert "This debug message should appear." in caplog.text

    # 测试 WARNING 级别
    logger.setLevel(30)  # WARNING
    caplog.clear()
    with caplog.at_level(logging.DEBUG):
        logger.debug("This debug message should NOT appear.")
        logger.warning("This warning message should appear.")
        assert len(caplog.records) == 1  # 只有 warning 被记录
        assert "This warning message should appear." in caplog.text
        assert "This debug message should NOT appear." not in caplog.text


def test_logger_name(caplog: pytest.LogCaptureFixture) -> None:
    """测试 logger 的名称"""
    with caplog.at_level(logging.INFO):
        logger.info("Testing logger name.")
        assert "LOGIC" in caplog.text
    assert logger.name == "LOGIC"


def test_json_log_format() -> None:
    """测试 JSON 格式的日志输出"""
    # 创建一个 StringIO 来捕获日志输出
    stream = StringIO()

    # 创建 JSON 格式的 logger
    json_logger = Logger(name="json_logger", format="json").get_logger()

    # 添加自定义 handler 来捕获输出
    handler = logging.StreamHandler(stream)

    # 确保使用 JSON formatter
    # 检查 logger 的 handlers 是否已经有 JSON formatter
    json_formatter = None
    for h in json_logger.handlers:
        if hasattr(h.formatter, "__class__") and "JSON" in h.formatter.__class__.__name__:
            json_formatter = h.formatter
            break

    if json_formatter:
        handler.setFormatter(json_formatter)
    else:
        handler.setFormatter(JsonFormatter())

    json_logger.addHandler(handler)

    try:
        # 记录日志
        json_logger.info("This is a JSON formatted log message.")

        # 获取输出
        stream.seek(0)
        log_output = stream.read().strip()

        print(f"\nActual log output: {log_output}\n")

        # 解析 JSON
        log_data = json.loads(log_output)

        # 验证 JSON 内容
        assert log_data["level"] == "INFO"
        assert log_data["msg"] == "This is a JSON formatted log message."
        assert log_data["name"] == "json_logger"
        assert "time" in log_data
    finally:
        json_logger.removeHandler(handler)
        handler.close()


def test_unknown_log_format() -> None:
    """测试未知格式的日志输出，应该回退到普通格式"""
    # 创建未知格式的 logger
    unknown_logger = Logger(name="unknown_logger", format="unknown").get_logger()

    # fallback to normal formatter
    exist = False
    for handler in unknown_logger.handlers:
        if isinstance(handler.formatter, NormalFormatter):
            exist = True

    assert exist


def test_set_formatter() -> None:
    """测试设置日志格式方法"""
    test_logger = Logger(name="test_set_formatter", format="normal")
    logger_instance = test_logger.get_logger()

    # 默认是普通格式
    for handler in logger_instance.handlers:
        assert isinstance(handler.formatter, NormalFormatter)

    # 设置为 JSON 格式
    test_logger.set_json_fmt(all=True)
    for handler in logger_instance.handlers:
        assert isinstance(handler.formatter, JsonFormatter)

    # 设置回普通格式
    test_logger.set_norm_fmt(all=True)
    for handler in logger_instance.handlers:
        assert isinstance(handler.formatter, NormalFormatter)
