"""
Centralized logging configuration for ThrillWiki.
Provides structured logging with proper formatting and context.
"""

import logging
import sys
from typing import Any

from django.conf import settings
from django.utils import timezone


class ThrillWikiFormatter(logging.Formatter):
    """Custom formatter for ThrillWiki logs with structured output."""

    def format(self, record):
        # Add timestamp if not present
        if not hasattr(record, "timestamp"):
            record.timestamp = timezone.now().isoformat()

        # Add request context if available
        if hasattr(record, "request"):
            record.request_id = getattr(record.request, "id", "unknown")
            record.user_id = (
                getattr(record.request.user, "id", "anonymous") if hasattr(record.request, "user") else "unknown"
            )
            record.path = getattr(record.request, "path", "unknown")
            record.method = getattr(record.request, "method", "unknown")

        # Structure the log message
        if hasattr(record, "extra_data"):
            record.structured_data = record.extra_data

        return super().format(record)


def get_logger(name: str) -> logging.Logger:
    """
    Get a configured logger for ThrillWiki components.

    Args:
        name: Logger name (usually __name__)

    Returns:
        Configured logger instance
    """
    logger = logging.getLogger(name)

    # Only configure if not already configured
    if not logger.handlers:
        handler = logging.StreamHandler(sys.stdout)
        formatter = ThrillWikiFormatter(fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        logger.setLevel(logging.INFO if settings.DEBUG else logging.WARNING)

    return logger


def log_exception(
    logger: logging.Logger,
    exception: Exception,
    *,
    context: dict[str, Any] | None = None,
    request=None,
    level: int = logging.ERROR,
) -> None:
    """
    Log an exception with structured context.

    Args:
        logger: Logger instance
        exception: Exception to log
        context: Additional context data
        request: Django request object
        level: Log level
    """
    log_data = {
        "exception_type": exception.__class__.__name__,
        "exception_message": str(exception),
        "context": context or {},
    }

    if request:
        log_data.update(
            {
                "request_path": getattr(request, "path", "unknown"),
                "request_method": getattr(request, "method", "unknown"),
                "user_id": (getattr(request.user, "id", "anonymous") if hasattr(request, "user") else "unknown"),
            }
        )

    logger.log(
        level,
        f"Exception occurred: {exception}",
        extra={"extra_data": log_data},
        exc_info=True,
    )


def log_business_event(
    logger: logging.Logger,
    event_type: str,
    *,
    message: str,
    context: dict[str, Any] | None = None,
    request=None,
    level: int = logging.INFO,
) -> None:
    """
    Log a business event with structured context.

    Args:
        logger: Logger instance
        event_type: Type of business event
        message: Event message
        context: Additional context data
        request: Django request object
        level: Log level
    """
    log_data = {"event_type": event_type, "context": context or {}}

    if request:
        log_data.update(
            {
                "request_path": getattr(request, "path", "unknown"),
                "request_method": getattr(request, "method", "unknown"),
                "user_id": (getattr(request.user, "id", "anonymous") if hasattr(request, "user") else "unknown"),
            }
        )

    logger.log(level, message, extra={"extra_data": log_data})


def log_performance_metric(
    logger: logging.Logger,
    operation: str,
    *,
    duration_ms: float,
    context: dict[str, Any] | None = None,
    level: int = logging.INFO,
) -> None:
    """
    Log a performance metric.

    Args:
        logger: Logger instance
        operation: Operation name
        duration_ms: Duration in milliseconds
        context: Additional context data
        level: Log level
    """
    log_data = {
        "metric_type": "performance",
        "operation": operation,
        "duration_ms": duration_ms,
        "context": context or {},
    }

    message = f"Performance: {operation} took {duration_ms:.2f}ms"
    logger.log(level, message, extra={"extra_data": log_data})


def log_api_request(
    logger: logging.Logger,
    request,
    *,
    response_status: int | None = None,
    duration_ms: float | None = None,
    level: int = logging.INFO,
) -> None:
    """
    Log an API request with context.

    Args:
        logger: Logger instance
        request: Django request object
        response_status: HTTP response status code
        duration_ms: Request duration in milliseconds
        level: Log level
    """
    log_data = {
        "request_type": "api",
        "path": getattr(request, "path", "unknown"),
        "method": getattr(request, "method", "unknown"),
        "user_id": (getattr(request.user, "id", "anonymous") if hasattr(request, "user") else "unknown"),
        "response_status": response_status,
        "duration_ms": duration_ms,
    }

    message = f"API Request: {request.method} {request.path}"
    if response_status:
        message += f" -> {response_status}"
    if duration_ms:
        message += f" ({duration_ms:.2f}ms)"

    logger.log(level, message, extra={"extra_data": log_data})


def log_security_event(
    logger: logging.Logger,
    event_type: str,
    *,
    message: str,
    severity: str = "medium",
    context: dict[str, Any] | None = None,
    request=None,
) -> None:
    """
    Log a security-related event.

    Args:
        logger: Logger instance
        event_type: Type of security event
        message: Event message
        severity: Event severity (low, medium, high, critical)
        context: Additional context data
        request: Django request object
    """
    log_data = {
        "security_event": True,
        "event_type": event_type,
        "severity": severity,
        "context": context or {},
    }

    if request:
        log_data.update(
            {
                "request_path": getattr(request, "path", "unknown"),
                "request_method": getattr(request, "method", "unknown"),
                "user_id": (getattr(request.user, "id", "anonymous") if hasattr(request, "user") else "unknown"),
                "remote_addr": request.META.get("REMOTE_ADDR", "unknown"),
                "user_agent": request.META.get("HTTP_USER_AGENT", "unknown"),
            }
        )

    # Use WARNING for medium/high, ERROR for critical
    level = logging.ERROR if severity in ["high", "critical"] else logging.WARNING

    logger.log(level, f"SECURITY: {message}", extra={"extra_data": log_data})
