"""
Taint-aware logging filter.

Installs a ``logging.Filter`` that scrubs :class:`~llm_taint.TaintedStr`
values from all log records before they reach any handler
(file, console, remote logging service).

Usage::

    from llm_taint.logger import install_taint_filter
    install_taint_filter()   # Call once at startup, before any logging occurs
"""
from __future__ import annotations

import logging

from .taint import is_tainted, scrub


class TaintScrubFilter(logging.Filter):
    """
    Logging filter that scrubs tainted values from log records.

    Iterates over ``record.args`` (tuple or dict) and replaces any
    :class:`~llm_taint.TaintedStr` with its scrubbed representation.
    Also scrubs ``record.msg`` if it is itself tainted.

    The record is always allowed through — this filter scrubs, it does not drop.

    Example::

        import logging
        from llm_taint import taint
        from llm_taint.logger import TaintScrubFilter

        handler = logging.StreamHandler()
        handler.addFilter(TaintScrubFilter())

        logger = logging.getLogger("myapp")
        logger.addHandler(handler)

        key = taint("sk-abc123", label="openai_key")
        logger.info("Using key: %s", key)
        # Output: "Using key: [REDACTED:openai_key]"
    """

    def filter(self, record: logging.LogRecord) -> bool:
        if record.args:
            if isinstance(record.args, dict):
                record.args = {
                    k: scrub(v) if is_tainted(v) else v
                    for k, v in record.args.items()
                }
            elif isinstance(record.args, tuple):
                record.args = tuple(
                    scrub(a) if is_tainted(a) else a for a in record.args
                )

        if is_tainted(record.msg):
            record.msg = scrub(record.msg)

        return True


_installed = False


def install_taint_filter(logger_name: str = "") -> None:
    """
    Install :class:`TaintScrubFilter` on the root logger (or a named logger).

    Safe to call multiple times — only installs once.

    Args:
        logger_name: Logger name to install on. Empty string = root logger.

    Example::

        # At application startup, before any logging:
        from llm_taint.logger import install_taint_filter
        install_taint_filter()

        # From this point on, tainted values are automatically scrubbed
        # in all log records regardless of which logger emits them.
    """
    global _installed
    if _installed:
        return
    target = logging.getLogger(logger_name)
    target.addFilter(TaintScrubFilter())
    _installed = True
    logging.getLogger(__name__).debug(
        "Taint scrub filter installed on logger '%s'", logger_name or "root"
    )
