"""JSON formatter for structured logging."""

import json
from datetime import datetime
from typing import Any

from ..core.backend import LogRecord
from .base import LogFormatter


class JSONFormatter(LogFormatter):
    """Formatter that outputs structured JSON logs."""

    def __init__(
        self,
        include_timestamp: bool = True,
        include_level: bool = True,
        include_logger_name: bool = True,
        include_extra: bool = True,
        timestamp_key: str = "timestamp",
        level_key: str = "level",
        message_key: str = "message",
        logger_key: str = "logger",
        exception_key: str = "exception",
        stack_key: str = "stack_info",
        indent: bool = False,
        ensure_ascii: bool = False,
        # Backward compatibility
        include_logger: bool = None,
        **kwargs: Any
    ) -> None:
        """Initialize JSON formatter.
        
        Args:
            include_timestamp: Include timestamp in output
            include_level: Include log level in output
            include_logger_name: Include logger name in output
            include_extra: Include extra fields in output
            timestamp_key: Key name for timestamp field
            level_key: Key name for level field
            message_key: Key name for message field
            logger_key: Key name for logger field
            exception_key: Key name for exception field
            stack_key: Key name for stack info field
            indent: Whether to pretty-print JSON with indentation
            ensure_ascii: Whether to escape non-ASCII characters
            **kwargs: Additional configuration
        """
        super().__init__(**kwargs)
        # Handle backward compatibility for include_logger
        if include_logger is not None:
            include_logger_name = include_logger

        self.include_timestamp = include_timestamp
        self.include_level = include_level
        self.include_logger_name = include_logger_name
        self.include_extra = include_extra

        # Backward compatibility
        self.include_logger = include_logger_name
        self.timestamp_key = timestamp_key
        self.level_key = level_key
        self.message_key = message_key
        self.logger_key = logger_key
        self.exception_key = exception_key
        self.stack_key = stack_key
        self.indent = 2 if indent else None
        self.ensure_ascii = ensure_ascii

    def format(self, record: LogRecord) -> str:
        """Format log record as JSON string.
        
        Args:
            record: The log record to format
            
        Returns:
            JSON-formatted log message
        """
        data = self.format_dict(record)
        return json.dumps(
            data,
            indent=self.indent,
            ensure_ascii=self.ensure_ascii,
            default=self._json_serializer
        )

    def format_dict(self, record: LogRecord) -> dict[str, Any]:
        """Format log record as dictionary.
        
        Args:
            record: The log record to format
            
        Returns:
            Dictionary representation of log record
        """
        data: dict[str, Any] = {}

        if self.include_timestamp:
            data[self.timestamp_key] = self._format_timestamp(record)

        if self.include_level:
            data[self.level_key] = {
                "name": self._get_level_name(record.level),
                "value": record.level
            }

        data[self.message_key] = record.message

        if self.include_logger_name:
            data[self.logger_key] = record.logger_name

        # Include extra fields
        if self.include_extra and record.extra:
            # Flatten extra fields into the main data dict
            # but avoid key collisions with reserved fields
            reserved_keys = {
                self.timestamp_key, self.level_key, self.message_key,
                self.logger_key, self.exception_key, self.stack_key
            }
            for key, value in record.extra.items():
                if key not in reserved_keys:
                    data[key] = value
                else:
                    # Prefix conflicting keys
                    data[f"extra_{key}"] = value

        # Include exception information if present
        if record.exc_info:
            exception_text = self._format_exception(record)
            if exception_text:
                data[self.exception_key] = {
                    "type": record.exc_info[0].__name__ if record.exc_info[0] else None,
                    "message": str(record.exc_info[1]) if record.exc_info[1] else None,
                    "traceback": exception_text
                }

        # Include stack information if present
        if record.stack_info:
            data[self.stack_key] = record.stack_info

        return data

    def _json_serializer(self, obj: Any) -> Any:
        """Custom JSON serializer for non-standard types.
        
        Args:
            obj: Object to serialize
            
        Returns:
            Serializable representation of the object
        """
        if isinstance(obj, datetime):
            return obj.isoformat()
        elif hasattr(obj, '__dict__'):
            return obj.__dict__
        else:
            return str(obj)
