"""Standard syslog logging for basement services (operator 2026-07-19: "Syslog logging" in the common
substrate). `build_logging(service_name)` returns a Django LOGGING dict that ships logs to BOTH stdout
(so docker/journald still capture them) AND syslog, tagged with the service name.

FAIL-SOFT: the syslog handler is only added when its target is actually present (a /dev/log socket
that exists, or a network host:port) — so a container without a syslog socket falls back to stdout
instead of crashing at settings-load (Django's dictConfig constructs handlers eagerly). Everything is
env-tunable: SYSLOG_ADDRESS (default /dev/log), SYSLOG_FACILITY (default local0), LOG_LEVEL, ANDREA_SYSLOG
(set 0 to disable syslog entirely).
"""
import logging.handlers
import os

_FACILITIES = {
    name[4:].lower(): getattr(logging.handlers.SysLogHandler, name)
    for name in dir(logging.handlers.SysLogHandler) if name.startswith("LOG_")
}


def _syslog_target(address: str):
    """Return the SysLogHandler `address` arg if the target is usable, else None (→ syslog skipped).
    A unix path must EXIST; a host:port is returned as a tuple (UDP, so no connect-time failure)."""
    if not address:
        return None
    if address.startswith("/"):
        return address if os.path.exists(address) else None
    if ":" in address:
        host, _, port = address.rpartition(":")
        return (host, int(port)) if host and port.isdigit() else None
    return None


def build_logging(service_name: str) -> dict:
    level = os.environ.get("LOG_LEVEL", "INFO").upper()
    handlers = {"console": {"class": "logging.StreamHandler", "formatter": "plain"}}
    root_handlers = ["console"]

    syslog_on = os.environ.get("ANDREA_SYSLOG", "1").lower() not in ("0", "false", "no", "off")
    target = _syslog_target(os.environ.get("SYSLOG_ADDRESS", "/dev/log")) if syslog_on else None
    if target is not None:
        facility = _FACILITIES.get(os.environ.get("SYSLOG_FACILITY", "local0").lower(),
                                   logging.handlers.SysLogHandler.LOG_LOCAL0)
        handlers["syslog"] = {
            "class": "logging.handlers.SysLogHandler",
            "address": target,
            "facility": facility,
            "formatter": "syslog",
        }
        root_handlers.append("syslog")

    return {
        "version": 1,
        "disable_existing_loggers": False,
        "formatters": {
            "plain": {"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"},
            # syslog already stamps time/host; the tag is the service name so lines are greppable per-service.
            "syslog": {"format": f"{service_name}[%(process)d] %(name)s %(levelname)s %(message)s"},
        },
        "handlers": handlers,
        "root": {"handlers": root_handlers, "level": level},
    }


def configure(logging_settings):
    """Django LOGGING_CONFIG hook. Runs at startup AFTER the settings module is fully loaded, so it
    rebuilds LOGGING from the FINAL settings.SERVICE_NAME — correcting the syslog tag even when a service
    overrides SERVICE_NAME after `from andrea_svc_web.settings import *` (the base's own LOGGING dict was
    built with the base default first). Wired via LOGGING_CONFIG in andrea_svc_web.settings, so every
    service is tagged correctly with ZERO per-service code — which is what the unified-syslog→Loki→ganglia
    attribution needs. `logging_settings` (the pre-built dict) is ignored on purpose."""
    import logging.config

    from django.conf import settings as _settings
    logging.config.dictConfig(build_logging(getattr(_settings, "SERVICE_NAME", "andrea-service")))
