"""``mgf.django`` — Django integration adapters for ``mgf-common``.

Sibling of :mod:`mgf.common` under the ``mgf.*`` namespace. Houses
every Django-specific adapter that previously lived under
``mgf.common.django.*`` — extracted at mgf-common v0.31 /
mgf-django v0.1 per the federation split plan.

Five surfaces close the Django consumer's adoption gap (the
finding from the v0.5 strategic review: every Django shop rebuilds
equivalent infrastructure because the cost of adoption is greater
than the value):

  - :class:`MgfCommonConfig` — Django ``AppConfig`` that calls
    :func:`mgf.common.bootstrap` idempotently in ``ready()``.
  - :class:`MgfRequestIdMiddleware` — per-request ``X-Request-Id``
    generation/forwarding via the same contextvar
    :class:`mgf.fastapi.RequestIdMiddleware` uses (so
    cross-framework processes can correlate end-to-end).
  - :class:`MgfContextMiddleware` — exposes the active
    :class:`AppContext` on ``request.mgf_context`` for views and
    other middleware.
  - :class:`JsonFormatter` — Django ``LOGGING['formatters']``-
    compatible wrapper around :class:`mgf.common.observability.JsonFormatter`.
    No required args, so the Django ``'()'`` factory syntax works.
  - :class:`DjangoSettingsBridge` — read-only bridge that exposes a
    pydantic-validated subset of ``django.conf.settings`` as a
    :class:`BaseAppSettings`-compatible object. Lets ``mgf-common
    explain settings.X`` work in Django apps.

Install: ``pip install mgf-django`` (pulls ``mgf-common`` +
``django>=4.2``).

The adapter is **callable-from-Django**, not framework-shaped. Your
``manage.py`` is unchanged; your ``settings.py`` is unchanged; your
``INSTALLED_APPS`` adds one entry, your ``MIDDLEWARE`` adds two.

Drop-in shape (the typical Django ``settings.py`` addition):

.. code-block:: python

    INSTALLED_APPS = [
        # ... your apps ...
        "mgf.django",
    ]

    MIDDLEWARE = [
        "mgf.django.MgfRequestIdMiddleware",  # earliest
        "mgf.django.MgfContextMiddleware",
        # ... your other middleware ...
    ]

    # `disable_existing_loggers: False` is load-bearing: Django
    # defaults it to True when the key is omitted, silencing every
    # logger Django ships (django.request, django.security, ...).
    _use_json = os.environ.get("LOG_FORMAT", "dev" if DEBUG else "json") == "json"

    LOGGING = {
        "version": 1,
        "disable_existing_loggers": False,  # KEEP Django's own loggers
        "formatters": {
            "json": {"()": "mgf.django.JsonFormatter"},  # prod: aggregator-parseable
            "dev": {"format": "[%(asctime)s] %(levelname)-7s %(name)s %(message)s"},
        },
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "formatter": "json" if _use_json else "dev",
            },
        },
        "root": {"handlers": ["console"], "level": "INFO"},
        "loggers": {
            "django.request": {"handlers": ["console"], "level": "WARNING", "propagate": False},
            "django.security": {"handlers": ["console"], "level": "INFO", "propagate": False},
            "django.db.backends": {"handlers": ["console"], "level": "WARNING", "propagate": False},
        },
    }

    MGF_COMMON_APP_NAME = "myapp"
    MGF_COMMON_APP_VERSION = "1.0.0"

Example emitted JSON record (one line on the wire)::

    {"ts": "2026-07-10T12:00:00.123Z", "level": "INFO", "level_no": 20,
     "logger": "myapp.views", "msg": "request handled", "app": "myapp",
     "app_version": "1.0.0", "lang": "python", "host": "web-1",
     "module": "views", "func": "my_view", "line": 42,
     "thread": "MainThread", "process": 4711, "schema_version": "1.0.0"}

That's the entire integration. The :class:`AppConfig` calls
:func:`bootstrap` once when Django boots; the middlewares carry the
per-request state; the formatter routes through the standard
mgf-common redaction + OTel correlation pipeline. (Request-id /
OTel trace fields join the record when the middlewares + OTel
wiring are active; full field reference:
:class:`mgf.common.observability.JsonFormatter`.)

Closed-box invariant: ``mgf-django`` depends on ``mgf-common`` +
``django`` only. Consumers MUST import from ``mgf.django``,
never reach into ``mgf.django._apps`` / ``mgf.django._middleware``
/ etc.
"""

from __future__ import annotations

from mgf.django._apps import MgfCommonConfig
from mgf.django._logging import JsonFormatter
from mgf.django._middleware import (
    MgfContextMiddleware,
    MgfRequestIdMiddleware,
)
from mgf.django._settings import DjangoSettingsBridge
from mgf.django._throttle import (
    SENSITIVE_PATHS_DEFAULT,
    ThrottleMiddleware,
    TokenBucket,
)

__all__ = [
    "SENSITIVE_PATHS_DEFAULT",
    "DjangoSettingsBridge",
    "JsonFormatter",
    "MgfCommonConfig",
    "MgfContextMiddleware",
    "MgfRequestIdMiddleware",
    "ThrottleMiddleware",
    "TokenBucket",
    "__version__",
]

__version__ = "0.4.10"
