"""
Structured logging configuration for The Iron Vault.

Uses structlog for JSON-formatted, context-rich logging suitable
for production observability systems (ELK, Datadog, etc.).
"""

from __future__ import annotations

import logging
import os
import sys
from typing import Any

import structlog


def configure_logging(
    level: str = "INFO",
    json_format: bool | None = None,
) -> None:
    """
    Configure structured logging for the application.

    Args:
        level: Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
        json_format: If True, output JSON. If None, auto-detect (JSON in prod).
    """
    # Auto-detect JSON format based on environment
    if json_format is None:
        env = os.environ.get("APERION_ENV", "").lower()
        json_format = env not in ("dev", "test")

    # Configure standard library logging
    logging.basicConfig(
        format="%(message)s",
        stream=sys.stdout,
        level=getattr(logging, level.upper(), logging.INFO),
    )

    # Shared processors for all output formats
    shared_processors: list[Any] = [
        structlog.contextvars.merge_contextvars,
        structlog.stdlib.add_log_level,
        structlog.stdlib.add_logger_name,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.UnicodeDecoder(),
    ]

    if json_format:
        # Production: JSON output
        processors = shared_processors + [
            structlog.processors.format_exc_info,
            structlog.processors.JSONRenderer(),
        ]
    else:
        # Development: Pretty console output
        processors = shared_processors + [
            structlog.dev.ConsoleRenderer(colors=True),
        ]

    structlog.configure(
        processors=processors,
        wrapper_class=structlog.stdlib.BoundLogger,
        context_class=dict,
        logger_factory=structlog.stdlib.LoggerFactory(),
        cache_logger_on_first_use=True,
    )


def get_logger(name: str | None = None) -> structlog.stdlib.BoundLogger:
    """
    Get a structured logger instance.

    Args:
        name: Logger name (usually __name__)

    Returns:
        Configured structlog logger
    """
    return structlog.get_logger(name)


def bind_request_context(
    request_id: str | None = None,
    client_ip: str | None = None,
    path: str | None = None,
    method: str | None = None,
) -> None:
    """
    Bind request context to the current logging context.

    This makes the context available to all log messages in the current
    request/task context.
    """
    ctx: dict[str, Any] = {}
    if request_id:
        ctx["request_id"] = request_id
    if client_ip:
        ctx["client_ip"] = client_ip
    if path:
        ctx["path"] = path
    if method:
        ctx["method"] = method

    if ctx:
        structlog.contextvars.bind_contextvars(**ctx)


def clear_request_context() -> None:
    """Clear the request context after handling."""
    structlog.contextvars.clear_contextvars()


# Security-specific log events
class SecurityLogger:
    """Logger for security-relevant events with consistent format."""

    def __init__(self):
        self._log = get_logger("security")

    def auth_success(self, client_ip: str, path: str) -> None:
        """Log successful authentication."""
        self._log.info(
            "auth_success",
            client_ip=client_ip,
            path=path,
            event_type="security.auth",
        )

    def auth_failure(self, client_ip: str, path: str, reason: str) -> None:
        """Log authentication failure."""
        self._log.warning(
            "auth_failure",
            client_ip=client_ip,
            path=path,
            reason=reason,
            event_type="security.auth",
        )

    def sandbox_violation(self, client_ip: str, attempted_path: str, reason: str) -> None:
        """Log sandbox escape attempt."""
        self._log.error(
            "sandbox_violation",
            client_ip=client_ip,
            attempted_path=attempted_path,
            reason=reason,
            event_type="security.sandbox",
        )

    def rate_limit_exceeded(self, client_ip: str, path: str) -> None:
        """Log rate limit exceeded."""
        self._log.warning(
            "rate_limit_exceeded",
            client_ip=client_ip,
            path=path,
            event_type="security.rate_limit",
        )

    def file_operation(
        self,
        operation: str,
        path: str,
        client_ip: str | None = None,
        size: int | None = None,
        success: bool = True,
    ) -> None:
        """Log file operation for audit trail."""
        self._log.info(
            "file_operation",
            operation=operation,
            file_path=path,
            client_ip=client_ip,
            size=size,
            success=success,
            event_type="audit.file",
        )


# Global security logger instance
security_log = SecurityLogger()
