"""Structured audit event logger.

Writes JSON-line audit events to a dedicated file with rotation.
Also emits events via the standard ``logging`` infrastructure so they
can be picked up by the middleware and TUI.
"""

from __future__ import annotations

import json
import logging
import os
from logging.handlers import RotatingFileHandler
from typing import Optional

from argus_mcp.audit.models import AuditEvent

logger = logging.getLogger(__name__)

# Custom log level — always enabled (NIST requirement: audit cannot be silenced)
AUDIT_LEVEL = 35  # between WARNING (30) and ERROR (40)
logging.addLevelName(AUDIT_LEVEL, "AUDIT")

# ── Defaults ─────────────────────────────────────────────────────────────

DEFAULT_AUDIT_DIR = "logs"
DEFAULT_AUDIT_FILE = "audit.jsonl"
DEFAULT_MAX_BYTES = 100 * 1024 * 1024  # 100 MB
DEFAULT_BACKUP_COUNT = 5


class AuditLogger:
    """JSON-line audit event writer with file rotation.

    Parameters
    ----------
    log_dir:
        Directory for the audit log file.
    filename:
        Name of the audit log file.
    max_bytes:
        Maximum file size before rotation.
    backup_count:
        Number of rotated files to keep.
    enabled:
        Whether to actually write events.
    """

    def __init__(
        self,
        *,
        log_dir: str = DEFAULT_AUDIT_DIR,
        filename: str = DEFAULT_AUDIT_FILE,
        max_bytes: int = DEFAULT_MAX_BYTES,
        backup_count: int = DEFAULT_BACKUP_COUNT,
        enabled: bool = True,
    ) -> None:
        self._enabled = enabled
        self._file_handler: Optional[RotatingFileHandler] = None
        self._audit_logger = logging.getLogger("argus_mcp.audit")
        self._audit_logger.setLevel(AUDIT_LEVEL)

        if enabled:
            os.makedirs(log_dir, exist_ok=True)
            filepath = os.path.join(log_dir, filename)
            self._file_handler = RotatingFileHandler(
                filepath,
                maxBytes=max_bytes,
                backupCount=backup_count,
                encoding="utf-8",
            )
            self._file_handler.setLevel(AUDIT_LEVEL)
            # Raw JSON — no formatter wrapping
            self._file_handler.setFormatter(logging.Formatter("%(message)s"))
            self._audit_logger.addHandler(self._file_handler)
            logger.info(
                "Audit logger initialized: %s (max %d MB, %d backups)",
                filepath,
                max_bytes // (1024 * 1024),
                backup_count,
            )

    @property
    def enabled(self) -> bool:
        return self._enabled

    def emit(self, event: AuditEvent) -> None:
        """Write an audit event as a JSON line."""
        if not self._enabled:
            return
        try:
            line = event.model_dump_json()
            self._audit_logger.log(AUDIT_LEVEL, line)
        except Exception:
            logger.exception("Failed to emit audit event")

    def emit_dict(self, data: dict) -> None:
        """Write a raw dict as a JSON line (for non-model events)."""
        if not self._enabled:
            return
        try:
            line = json.dumps(data, default=str, separators=(",", ":"))
            self._audit_logger.log(AUDIT_LEVEL, line)
        except Exception:
            logger.exception("Failed to emit audit dict")

    def close(self) -> None:
        """Close the file handler."""
        if self._file_handler is not None:
            self._file_handler.close()
            self._audit_logger.removeHandler(self._file_handler)
            self._file_handler = None
