"""
RPC Client Logger

Auto-generated logging module for Python RPC client.
Generated by: django_ipc codegen
"""

import json
import logging
from datetime import datetime
from logging.handlers import RotatingFileHandler
from pathlib import Path
from typing import Any, Dict, Optional


class ClientLoggerConfig:
    """Configuration for client logger."""

    def __init__(
        self,
        log_dir: str = "./client_logs",
        level: str = "INFO",
        log_rpc_calls: bool = True,
        max_bytes: int = 10 * 1024 * 1024,  # 10 MB
        backup_count: int = 5,
        console_output: bool = True,
    ):
        """
        Initialize logger config.

        Args:
            log_dir: Directory for log files
            level: Log level (DEBUG, INFO, WARNING, ERROR)
            log_rpc_calls: Whether to log RPC calls
            max_bytes: Max file size before rotation
            backup_count: Number of backup files to keep
            console_output: Whether to output to console
        """
        self.log_dir = log_dir
        self.level = level
        self.log_rpc_calls = log_rpc_calls
        self.max_bytes = max_bytes
        self.backup_count = backup_count
        self.console_output = console_output

        # Create log directory
        Path(log_dir).mkdir(parents=True, exist_ok=True)


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

    def format(self, record: logging.LogRecord) -> str:
        """Format log record as JSON."""
        log_data = {
            "timestamp": datetime.utcfromtimestamp(record.created).isoformat() + "Z",
            "level": record.levelname,
            "logger": record.name,
            "message": record.getMessage(),
        }

        # Add extra fields
        for key in ["method", "correlation_id", "duration_ms", "success", "direction"]:
            if hasattr(record, key):
                log_data[key] = getattr(record, key)

        if record.exc_info:
            log_data["exception"] = self.formatException(record.exc_info)

        return json.dumps(log_data, ensure_ascii=False)


class ClientLogger:
    """
    RPC Client Logger with rotation and structured logging.

    Features:
    - Structured JSON logging
    - Log rotation
    - Separate RPC call logs
    - Automatic request/response tracking

    Example:
        >>> config = ClientLoggerConfig(log_dir="./logs")
        >>> logger = ClientLogger(config)
        >>>
        >>> logger.info("Client connected")
        >>> logger.log_rpc_call("create_user", {...}, {...}, 45.2, True)
    """

    def __init__(self, config: Optional[ClientLoggerConfig] = None):
        """
        Initialize client logger.

        Args:
            config: Logger configuration (uses defaults if None)
        """
        self.config = config or ClientLoggerConfig()

        # Create logger
        self.logger = logging.getLogger("rpc_client")
        self.logger.setLevel(self._get_level(self.config.level))
        self.logger.propagate = False

        # Clear existing handlers
        self.logger.handlers.clear()

        # Setup handlers
        self._setup_handlers()

    def _get_level(self, level: str) -> int:
        """Convert string level to logging constant."""
        levels = {
            "DEBUG": logging.DEBUG,
            "INFO": logging.INFO,
            "WARNING": logging.WARNING,
            "ERROR": logging.ERROR,
            "CRITICAL": logging.CRITICAL,
        }
        return levels.get(level.upper(), logging.INFO)

    def _setup_handlers(self) -> None:
        """Setup file and console handlers."""
        # Main log file (JSON)
        main_handler = RotatingFileHandler(
            filename=str(Path(self.config.log_dir) / "client.log"),
            maxBytes=self.config.max_bytes,
            backupCount=self.config.backup_count,
            encoding="utf-8",
        )
        main_handler.setFormatter(JSONFormatter())
        self.logger.addHandler(main_handler)

        # RPC calls log (JSON)
        if self.config.log_rpc_calls:
            rpc_handler = RotatingFileHandler(
                filename=str(Path(self.config.log_dir) / "client_rpc.log"),
                maxBytes=self.config.max_bytes,
                backupCount=self.config.backup_count,
                encoding="utf-8",
            )
            rpc_handler.setFormatter(JSONFormatter())
            rpc_handler.addFilter(lambda record: hasattr(record, "method"))
            self.logger.addHandler(rpc_handler)

        # Console output
        if self.config.console_output:
            console_handler = logging.StreamHandler()
            console_handler.setLevel(self._get_level(self.config.level))
            console_formatter = logging.Formatter(
                "%(asctime)s - %(levelname)s - %(message)s",
                datefmt="%Y-%m-%d %H:%M:%S",
            )
            console_handler.setFormatter(console_formatter)
            self.logger.addHandler(console_handler)

    def debug(self, message: str, **kwargs) -> None:
        """Log debug message."""
        self.logger.debug(message, extra=kwargs)

    def info(self, message: str, **kwargs) -> None:
        """Log info message."""
        self.logger.info(message, extra=kwargs)

    def warning(self, message: str, **kwargs) -> None:
        """Log warning message."""
        self.logger.warning(message, extra=kwargs)

    def error(self, message: str, **kwargs) -> None:
        """Log error message."""
        self.logger.error(message, extra=kwargs)

    def log_rpc_call(
        self,
        method: str,
        params: Any,
        result: Any,
        duration_ms: float,
        success: bool,
        correlation_id: Optional[str] = None,
    ) -> None:
        """
        Log complete RPC call (request + response).

        Args:
            method: RPC method name
            params: Request parameters
            result: Response result
            duration_ms: Call duration in milliseconds
            success: Whether call succeeded
            correlation_id: Correlation ID for tracking
        """
        if not self.config.log_rpc_calls:
            return

        level = logging.INFO if success else logging.ERROR

        self.logger.log(
            level,
            f"RPC: {method} ({'✅' if success else '❌'}) [{duration_ms:.1f}ms]",
            extra={
                "method": method,
                "params": params,
                "result": result if success else None,
                "duration_ms": round(duration_ms, 2),
                "success": success,
                "correlation_id": correlation_id,
                "direction": "client->server",
            },
        )

    def log_request(
        self,
        method: str,
        params: Any,
        correlation_id: Optional[str] = None,
    ) -> None:
        """
        Log RPC request.

        Args:
            method: RPC method name
            params: Request parameters
            correlation_id: Correlation ID
        """
        if not self.config.log_rpc_calls:
            return

        self.logger.debug(
            f"→ Request: {method}",
            extra={
                "method": method,
                "params": params,
                "correlation_id": correlation_id,
                "direction": "request",
            },
        )

    def log_response(
        self,
        method: str,
        result: Any,
        duration_ms: float,
        success: bool,
        correlation_id: Optional[str] = None,
    ) -> None:
        """
        Log RPC response.

        Args:
            method: RPC method name
            result: Response result
            duration_ms: Duration in milliseconds
            success: Whether successful
            correlation_id: Correlation ID
        """
        if not self.config.log_rpc_calls:
            return

        level = logging.INFO if success else logging.ERROR

        self.logger.log(
            level,
            f"← Response: {method} [{duration_ms:.1f}ms]",
            extra={
                "method": method,
                "result": result if success else None,
                "duration_ms": round(duration_ms, 2),
                "success": success,
                "correlation_id": correlation_id,
                "direction": "response",
            },
        )


__all__ = [
    "ClientLoggerConfig",
    "ClientLogger",
]
