"""Structured logging configuration using *structlog*.

Usage::

    from app.utils.logger import get_logger

    logger = get_logger(__name__)
    logger.info("event_happened", user_id="abc", count=42)

结构化日志配置模块。
基于 structlog 提供统一的日志初始化和 logger 获取接口。
开发环境使用彩色控制台输出，生产环境输出 JSON Lines 格式（适配 ELK）。
支持 contextvars 自动注入 trace_id / doc_id 等链路上下文。
"""

from __future__ import annotations

import logging
import sys

import structlog


def configure_logging(*, debug: bool = False) -> None:
    """Configure structlog and the stdlib root logger.

    Call once during application startup (e.g. in the lifespan handler).

    初始化日志系统，应在应用启动时调用一次。
    debug=True 时使用彩色控制台渲染器，否则使用 JSON 渲染器。
    """
    log_level = logging.DEBUG if debug else logging.INFO

    # Shared processors used by both structlog and stdlib integration.
    shared_processors: list[structlog.types.Processor] = [
        structlog.contextvars.merge_contextvars,
        structlog.stdlib.add_log_level,
        structlog.stdlib.add_logger_name,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.UnicodeDecoder(),
    ]

    if debug:
        # Pretty console output for development.
        renderer: structlog.types.Processor = structlog.dev.ConsoleRenderer()
    else:
        # JSON lines for production / ELK.
        renderer = structlog.processors.JSONRenderer(ensure_ascii=False)

    structlog.configure(
        processors=[
            *shared_processors,
            structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
        ],
        logger_factory=structlog.stdlib.LoggerFactory(),
        wrapper_class=structlog.stdlib.BoundLogger,
        cache_logger_on_first_use=True,
    )

    formatter = structlog.stdlib.ProcessorFormatter(
        processors=[
            structlog.stdlib.ProcessorFormatter.remove_processors_meta,
            renderer,
        ],
        foreign_pre_chain=shared_processors,
    )

    handler = logging.StreamHandler(sys.stdout)
    handler.setFormatter(formatter)

    root_logger = logging.getLogger()
    root_logger.handlers.clear()
    root_logger.addHandler(handler)
    root_logger.setLevel(log_level)

    # Silence noisy third-party loggers.
    for name in ("elasticsearch", "neo4j", "httpx", "httpcore", "uvicorn.access"):
        logging.getLogger(name).setLevel(logging.WARNING)


def get_logger(name: str | None = None) -> structlog.stdlib.BoundLogger:
    """Return a bound structlog logger."""
    return structlog.get_logger(name)
