""":class:`JsonFormatter` — Django ``LOGGING``-compatible JSON formatter.

Wraps :class:`mgf.common.observability.JsonFormatter` so the
``'()': '...'`` factory syntax in Django's ``LOGGING['formatters']``
dict works without the consumer having to construct a
:class:`Redactor` first.

The wrapper subclasses the underlying formatter; instances behave
identically (same OTel correlation, same redaction, same JSON
schema). The only difference is the no-arg constructor — it pulls
the default :class:`Redactor` automatically.
"""

from __future__ import annotations

import os

from mgf.common.observability.json_formatter import JsonFormatter as _BaseJsonFormatter
from mgf.common.observability.redaction import Redactor

# SH-05 / RA-06: env var consumers can set to add project-specific
# secret-bearing key names to the default redaction set without
# subclassing. Comma-separated (whitespace ignored). Empty / unset
# means "no extras" (the default behaviour).
_EXTRA_KEYS_ENV_VAR = "MGF_DJANGO_REDACT_EXTRA_KEYS"


def _read_extra_keys() -> frozenset[str]:
    """Parse ``MGF_DJANGO_REDACT_EXTRA_KEYS`` into a frozenset.

    Returns the empty set when the env var is unset or empty. Names
    are stripped of surrounding whitespace; case is preserved
    (mgf-common's Redactor lowercases internally).
    """
    raw = os.environ.get(_EXTRA_KEYS_ENV_VAR, "")
    if not raw.strip():
        return frozenset()
    return frozenset(part.strip() for part in raw.split(",") if part.strip())


class JsonFormatter(_BaseJsonFormatter):
    """No-arg JSON formatter for ``LOGGING['formatters']``.

    Use in Django's logging config::

        LOGGING = {
            "version": 1,
            "formatters": {
                "json": {"()": "mgf.django.JsonFormatter"},
            },
            "handlers": {
                "console": {
                    "class": "logging.StreamHandler",
                    "formatter": "json",
                },
            },
            "root": {"handlers": ["console"], "level": "INFO"},
        }

    The ``()`` syntax is Django's "callable factory" indicator —
    Django constructs the formatter as ``mgf.django.JsonFormatter()``,
    no kwargs. The default :class:`Redactor` (built-in pattern groups)
    is wired automatically.

    **Customising redaction (SH-05 / RA-06):** two options.

    1. **Env-var-driven** — set ``MGF_DJANGO_REDACT_EXTRA_KEYS`` to a
       comma-separated list of project-specific secret-bearing key
       names. The formatter picks them up at construction time and
       adds them to the default redaction set::

           MGF_DJANGO_REDACT_EXTRA_KEYS="project_secret,oauth_nonce"

       Zero code change; works with Django's ``LOGGING`` config as-is.

    2. **Subclass** — for redactor customisation beyond the extra-keys
       set (e.g., a custom pattern group), construct your own
       :class:`Redactor` and pass it via ``super().__init__()``::

           from mgf.common.observability import Redactor
           from mgf.django import JsonFormatter as BaseJsonFormatter

           class MyJsonFormatter(BaseJsonFormatter):
               def __init__(self) -> None:
                   redactor = Redactor(extra_keys=frozenset({"foo"}))
                   _BaseJsonFormatter.__init__(self, redactor=redactor)
    """

    def __init__(self) -> None:
        extra_keys = _read_extra_keys()
        if extra_keys:
            redactor = Redactor(extra_keys=extra_keys)
        else:
            redactor = Redactor.default()
        super().__init__(redactor=redactor)
