"""Custom log formatters."""

import json
import logging
from datetime import datetime
from typing import Any, Dict

try:
    import colorlog
except ImportError:
    colorlog = None


class JSONFormatter(logging.Formatter):
    """JSON formatter for structured logging."""

    def format(self, record: logging.LogRecord) -> str:
        """
        Format log record as JSON.

        Args:
            record: Log record to format

        Returns:
            JSON string
        """
        log_data: Dict[str, Any] = {
            "timestamp": datetime.utcnow().isoformat(),
            "level": record.levelname,
            "logger": record.name,
            "message": record.getMessage(),
            "module": record.module,
            "function": record.funcName,
            "line": record.lineno,
        }

        # Add exception info if present
        if record.exc_info:
            log_data["exception"] = self.formatException(record.exc_info)

        # Add extra fields
        if hasattr(record, "extra_fields"):
            log_data.update(record.extra_fields)

        return json.dumps(log_data)


class DetailedFormatter(logging.Formatter):
    """Detailed text formatter with full context."""

    def __init__(self, *args: Any, **kwargs: Any):
        """Initialize formatter."""
        super().__init__(
            fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s - [%(pathname)s:%(lineno)d]",
            datefmt="%Y-%m-%d %H:%M:%S",
            *args,
            **kwargs,
        )


class ColoredFormatter(logging.Formatter):
    """Colored console formatter."""

    def __init__(self, *args: Any, **kwargs: Any):
        """Initialize formatter."""
        if colorlog is None:
            # Fallback to standard formatter if colorlog not available
            super().__init__(
                fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
                datefmt="%Y-%m-%d %H:%M:%S",
                *args,
                **kwargs,
            )
        else:
            # Use colorlog if available
            super().__init__(*args, **kwargs)

    def format(self, record: logging.LogRecord) -> str:
        """
        Format log record with colors.

        Args:
            record: Log record to format

        Returns:
            Formatted string with colors
        """
        if colorlog is None:
            return super().format(record)

        # Create colored formatter
        formatter = colorlog.ColoredFormatter(
            "%(log_color)s%(asctime)s - %(name)s - %(levelname)s - %(message)s%(reset)s",
            datefmt="%Y-%m-%d %H:%M:%S",
            log_colors={
                "DEBUG": "cyan",
                "INFO": "green",
                "WARNING": "yellow",
                "ERROR": "red",
                "CRITICAL": "red,bg_white",
            },
        )
        return formatter.format(record)

