import logging
import os
import structlog
import sys


OPENREWARD_USE_STRUCTURED_LOGS = bool(os.getenv("OPENREWARD_USE_STRUCTURED_LOGS", False))

def _rename_for_gcp(_, method, event_dict):
    event_dict["message"] = event_dict.pop("event")
    event_dict["severity"] = event_dict.pop("level", method).upper()
    return event_dict

def setup_logging(level: int = logging.INFO):
    """Configure logging for the current process.

    Uses JSON structured logging when OPENREWARD_USE_STRUCTURED_LOGS is set,
    otherwise uses a human-readable console renderer.
    """
    shared_processors = [
        structlog.contextvars.merge_contextvars,
        structlog.processors.add_log_level,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
    ]

    if OPENREWARD_USE_STRUCTURED_LOGS:
        final_processors = [*shared_processors, _rename_for_gcp, structlog.processors.JSONRenderer()]
    else:
        final_processors = [*shared_processors, structlog.dev.ConsoleRenderer()]

    structlog.configure(
        processors=final_processors,
        wrapper_class=structlog.make_filtering_bound_logger(level),
        context_class=dict,
        logger_factory=structlog.PrintLoggerFactory(),
        cache_logger_on_first_use=False,
    )

    if OPENREWARD_USE_STRUCTURED_LOGS:
        # Production: also configure stdlib root logger so that third-party
        # library messages (uvicorn, aiohttp, etc.) flow through structlog.
        formatter = structlog.stdlib.ProcessorFormatter(
            processors=[
                structlog.stdlib.ProcessorFormatter.remove_processors_meta,
                structlog.processors.JSONRenderer(),
            ],
            foreign_pre_chain=[*shared_processors, structlog.stdlib.ExtraAdder()],
        )

        handler = logging.StreamHandler(sys.stdout)
        handler.setFormatter(formatter)
        root = logging.getLogger()
        root.handlers.clear()
        root.addHandler(handler)
        root.setLevel(level)