"""Local audit logging for StyloBridge conversions.

Writes structured JSON-lines to a rotating log file, providing
the paper trail that enterprise IT departments require.
"""

import json
import logging
import os
import stat
import unicodedata
from datetime import datetime, timezone
from logging.handlers import RotatingFileHandler

_audit_logger: logging.Logger | None = None

LOG_FILE = "stylobridge_audit.log"
MAX_BYTES = 10 * 1024 * 1024  # 10 MB
BACKUP_COUNT = 5


def get_audit_logger() -> logging.Logger:
    """Return the singleton audit logger, creating it on first call."""
    global _audit_logger
    if _audit_logger is not None:
        return _audit_logger

    logger = logging.getLogger("stylobridge.audit")
    level = os.getenv("LOG_LEVEL", "INFO").upper()
    logger.setLevel(getattr(logging, level, logging.INFO))

    handler = RotatingFileHandler(
        LOG_FILE, maxBytes=MAX_BYTES, backupCount=BACKUP_COUNT
    )
    handler.setFormatter(logging.Formatter("%(message)s"))
    logger.addHandler(handler)

    # Restrict audit log to owner-only (0o600)
    if os.path.exists(LOG_FILE):
        os.chmod(LOG_FILE, stat.S_IRUSR | stat.S_IWUSR)

    _audit_logger = logger
    return logger


def _sanitize_log_field(value: str | None, max_len: int = 500) -> str | None:
    """Strip control characters, line/paragraph separators, and enforce length bounds."""
    if value is None:
        return None
    # Strip C* (control), Zl (line separator U+2028), Zp (paragraph separator U+2029)
    unsafe = {"C", "Zl", "Zp"}
    cleaned = "".join(
        c for c in value
        if unicodedata.category(c) not in unsafe and unicodedata.category(c)[0] != "C"
    )
    return cleaned[:max_len]


def log_conversion(
    employee: str,
    input_path: str,
    output_format: str,
    success: bool,
    error: str | None = None,
    action: str = "convert",
    output_path: str | None = None,
) -> None:
    """Write a structured JSON-lines audit entry."""
    entry = {
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "employee": _sanitize_log_field(employee, max_len=200),
        "action": _sanitize_log_field(action, max_len=50),
        "input": _sanitize_log_field(input_path),
        "format": _sanitize_log_field(output_format, max_len=20),
        "output": _sanitize_log_field(output_path),
        "success": success,
        "error": _sanitize_log_field(error),
    }
    get_audit_logger().info(json.dumps(entry))
