"""Layer 2 — Structured fields + redaction + JSON file sink.

Realistic logging shape: structured records with `extra={...}`,
sensitive fields redacted automatically, JSON output written to a
rotating file alongside the human-friendly console output.
"""

from __future__ import annotations

import json
import logging
import os
import tempfile
from pathlib import Path

import mgf.common
from mgf.common.settings import LoggingSettings, MgfSettings


def main() -> None:
    with tempfile.TemporaryDirectory() as tmp:
        os.environ["XDG_STATE_HOME"] = tmp

        log_file = Path(tmp) / "myapp.log"

        # bootstrap() wires identity + logging in one call.
        # fmt="json" forces structured output (rule LG-02). Default
        # "auto" picks text-on-TTY / JSON-otherwise.
        # The rotating file always writes JSON regardless of fmt.
        ctx = mgf.common.bootstrap(
            app_name="example-practical-log",
            app_version="0.1.0",
            settings=MgfSettings(
                logging=LoggingSettings(level="DEBUG", format="json", file=log_file),
            ),
        )

        LOG = logging.getLogger(__name__)

        # Structured fields via extra={...} — promoted to top-level
        # keys in the JSON output (rule LG-09). Lazy %-formatting
        # in the message keeps the template stable for aggregators
        # to group by (rule LG-08).
        LOG.info(
            "user authenticated",
            extra={"user_id": "alice", "session_id": "sess-12345"},
        )

        # Sensitive fields are caught by the default Redactor before
        # any sink sees them (rule LG-04 / SC-09). The 'password'
        # key matches; its value becomes [REDACTED] in every sink.
        LOG.info(
            "connecting to backend",
            extra={"username": "alice", "password": "hunter2"},
        )

        # ERROR-level records carry the traceback via exc_info=True
        # (rule LG-05). LOG.exception is the canonical shape inside
        # an except block; it's equivalent to LOG.error(..., exc_info=True).
        try:
            raise ValueError("bad input from upstream")
        except ValueError:
            LOG.exception(
                "validation failed",
                extra={"input_id": "req-789"},
            )

        # Read back the file to confirm redaction + structure.
        records = [json.loads(line) for line in log_file.read_text().splitlines()]
        print(f"\nWrote {len(records)} JSON records to {log_file.name}:")
        for r in records:
            # Show the structured shape with secrets already redacted.
            print(f"  level={r['level']} msg={r['msg']!r}")
            for key in ("user_id", "session_id", "username", "password", "input_id"):
                if key in r:
                    print(f"    {key} = {r[key]!r}")

        ctx.shutdown()


if __name__ == "__main__":
    main()
