"""Structured logging (spec §59). Never logs secrets — the redaction list below is applied to
every bound key before a log line is emitted."""
from __future__ import annotations

import logging
import sys

import structlog

# AUDIT FIX (StockLab overhaul, security audit, docs/AUDIT_SECURITY.md finding #16): this was an
# exact-match set that did not include "refresh_token"/"access_token"/"client_secret"/"secret" --
# a log call binding any of those field names (all of which this codebase actually uses, e.g.
# TokenResponse.refresh_token) would NOT have been redacted before this fix. Deliberately still
# exact-match rather than substring-match: a substring check would also redact harmless fields
# like "token_type" ("bearer"), which is never sensitive and is useful to see in logs.
_REDACT_KEYS = {
    "password", "api_key", "apikey", "token", "authorization", "jwt_secret_key",
    "hashed_password", "refresh_token", "access_token", "client_secret", "secret",
}


def _redact_processor(logger, method_name, event_dict):
    for key in list(event_dict.keys()):
        if key.lower() in _REDACT_KEYS:
            event_dict[key] = "***REDACTED***"
    return event_dict


def configure_logging(json_logs: bool = True) -> None:
    logging.basicConfig(format="%(message)s", stream=sys.stdout, level=logging.INFO)
    processors = [
        structlog.contextvars.merge_contextvars,
        structlog.processors.add_log_level,
        structlog.processors.TimeStamper(fmt="iso"),
        _redact_processor,
        structlog.processors.StackInfoRenderer(),
    ]
    processors.append(structlog.processors.JSONRenderer() if json_logs else structlog.dev.ConsoleRenderer())
    structlog.configure(
        processors=processors,
        logger_factory=structlog.stdlib.LoggerFactory(),
        wrapper_class=structlog.stdlib.BoundLogger,
        cache_logger_on_first_use=True,
    )


def get_logger(name: str):
    return structlog.get_logger(name)
