"""
Enhanced Logging Configuration for Connectors
Centralized logging setup with structured logging capabilities
"""

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


class StructuredFormatter(logging.Formatter):
    """Custom formatter for structured JSON logging"""
    
    def format(self, record: logging.LogRecord) -> str:
        log_entry = {
            "timestamp": datetime.utcnow().isoformat() + "Z",
            "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_entry["exception"] = self.formatException(record.exc_info)
        
        # Add extra fields
        for key, value in record.__dict__.items():
            if key not in {
                'name', 'msg', 'args', 'levelname', 'levelno', 'pathname',
                'filename', 'module', 'lineno', 'funcName', 'created',
                'msecs', 'relativeCreated', 'thread', 'threadName',
                'processName', 'process', 'getMessage', 'exc_info',
                'exc_text', 'stack_info'
            }:
                log_entry[key] = value
        
        return json.dumps(log_entry, default=str)


class ColoredFormatter(logging.Formatter):
    """Colored formatter for console output"""
    
    COLORS = {
        'DEBUG': '\033[36m',    # Cyan
        'INFO': '\033[32m',     # Green
        'WARNING': '\033[33m',  # Yellow
        'ERROR': '\033[31m',    # Red
        'CRITICAL': '\033[35m', # Magenta
        'RESET': '\033[0m'      # Reset
    }
    
    def format(self, record: logging.LogRecord) -> str:
        color = self.COLORS.get(record.levelname, self.COLORS['RESET'])
        reset = self.COLORS['RESET']
        
        # Format the message
        formatted = super().format(record)
        
        # Add color
        return f"{color}[{record.levelname}]{reset} {formatted}"


def setup_logging(
    level: str = "INFO",
    log_file: Optional[str] = None,
    structured: bool = False,
    console: bool = True,
    max_file_size: int = 10 * 1024 * 1024,  # 10MB
    backup_count: int = 5,
    enable_rich: bool = False
) -> None:
    """
    Setup comprehensive logging configuration
    
    Args:
        level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
        log_file: Path to log file (optional)
        structured: Use structured JSON logging
        console: Enable console logging
        max_file_size: Maximum log file size in bytes
        backup_count: Number of backup files to keep
        enable_rich: Enable rich console formatting (if rich is available)
    """
    
    # Get the root logger
    root_logger = logging.getLogger()
    root_logger.setLevel(getattr(logging, level.upper()))
    
    # Clear existing handlers
    root_logger.handlers.clear()
    
    # Setup formatters
    if structured:
        formatter = StructuredFormatter()
    else:
        if enable_rich and _is_rich_available():
            formatter = _get_rich_formatter()
        else:
            formatter = ColoredFormatter(
                fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                datefmt='%Y-%m-%d %H:%M:%S'
            )
    
    # Console handler
    if console:
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(formatter)
        root_logger.addHandler(console_handler)
    
    # File handler with rotation
    if log_file:
        log_path = Path(log_file)
        log_path.parent.mkdir(parents=True, exist_ok=True)
        
        file_handler = logging.handlers.RotatingFileHandler(
            log_file,
            maxBytes=max_file_size,
            backupCount=backup_count,
            encoding='utf-8'
        )
        
        # Use structured format for files
        if structured:
            file_handler.setFormatter(StructuredFormatter())
        else:
            file_handler.setFormatter(logging.Formatter(
                fmt='%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s',
                datefmt='%Y-%m-%d %H:%M:%S'
            ))
        
        root_logger.addHandler(file_handler)


def setup_connector_logging(
    connector_name: str,
    level: str = "INFO",
    log_file: Optional[str] = None,
    structured: bool = False
) -> logging.Logger:
    """
    Setup logging for a specific connector
    
    Args:
        connector_name: Name of the connector (e.g., 'confluence', 'jira')
        level: Logging level
        log_file: Optional log file path
        structured: Use structured logging
        
    Returns:
        Logger instance for the connector
    """
    logger_name = f"connectors.{connector_name}"
    logger = logging.getLogger(logger_name)
    logger.setLevel(getattr(logging, level.upper()))
    
    # Clear existing handlers for this logger
    logger.handlers.clear()
    
    # Prevent propagation to root logger to avoid duplicate logs
    logger.propagate = False
    
    # Setup formatters
    if structured:
        formatter = StructuredFormatter()
    else:
        formatter = ColoredFormatter(
            fmt=f'%(asctime)s - {connector_name.upper()} - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
    
    # Console handler
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(formatter)
    logger.addHandler(console_handler)
    
    # File handler if specified
    if log_file:
        log_path = Path(log_file)
        log_path.parent.mkdir(parents=True, exist_ok=True)
        
        file_handler = logging.handlers.RotatingFileHandler(
            log_file,
            maxBytes=5 * 1024 * 1024,  # 5MB
            backupCount=3,
            encoding='utf-8'
        )
        
        if structured:
            file_handler.setFormatter(StructuredFormatter())
        else:
            file_handler.setFormatter(logging.Formatter(
                fmt=f'%(asctime)s - {connector_name.upper()} - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s',
                datefmt='%Y-%m-%d %H:%M:%S'
            ))
        
        logger.addHandler(file_handler)
    
    return logger


def _is_rich_available() -> bool:
    """Check if rich library is available for enhanced console output"""
    try:
        import rich  # noqa: F401
        return True
    except ImportError:
        return False


def _get_rich_formatter():
    """Get rich console formatter if available"""
    try:
        from rich.console import Console
        from rich.logging import RichHandler
        
        console = Console()
        return RichHandler(console=console, show_time=True, show_path=True)
    except ImportError:
        # Fallback to colored formatter
        return ColoredFormatter()


class LoggerMixin:
    """Mixin class to add logging capabilities to any class"""
    
    @property
    def logger(self) -> logging.Logger:
        """Get logger for the class"""
        if not hasattr(self, '_logger'):
            self._logger = logging.getLogger(self.__class__.__module__ + '.' + self.__class__.__name__)
        return self._logger
    
    def log_with_context(
        self, 
        level: int, 
        message: str, 
        **context
    ) -> None:
        """Log message with additional context"""
        extra = {k: v for k, v in context.items() if k not in {'exc_info', 'stack_info'}}
        self.logger.log(level, message, extra=extra)


def get_logger(name: str) -> logging.Logger:
    """Get a logger instance with standard configuration"""
    return logging.getLogger(f"connectors.{name}")


# Performance logging decorator
def log_performance(func):
    """Decorator to log function performance"""
    def wrapper(*args, **kwargs):
        logger = logging.getLogger(func.__module__)
        start_time = datetime.now()
        
        try:
            result = func(*args, **kwargs)
            end_time = datetime.now()
            duration = (end_time - start_time).total_seconds()
            
            logger.debug(
                f"Function {func.__name__} completed in {duration:.3f}s",
                extra={
                    'function': func.__name__,
                    'duration': duration,
                    'start_time': start_time.isoformat(),
                    'end_time': end_time.isoformat()
                }
            )
            
            return result
            
        except Exception as e:
            end_time = datetime.now()
            duration = (end_time - start_time).total_seconds()
            
            logger.error(
                f"Function {func.__name__} failed after {duration:.3f}s: {e}",
                extra={
                    'function': func.__name__,
                    'duration': duration,
                    'error': str(e),
                    'start_time': start_time.isoformat(),
                    'end_time': end_time.isoformat()
                },
                exc_info=True
            )
            raise
    
    return wrapper


# Security logging
def log_security_event(
    event_type: str,
    user: Optional[str] = None,
    resource: Optional[str] = None,
    details: Optional[Dict[str, Any]] = None
) -> None:
    """Log security-related events"""
    logger = logging.getLogger("connectors.security")
    
    log_data = {
        'event_type': event_type,
        'timestamp': datetime.utcnow().isoformat(),
        'user': user,
        'resource': resource,
        'details': details or {}
    }
    
    logger.warning(f"Security event: {event_type}", extra=log_data)
