import logging
import os
import sys
from typing import Optional, Dict, Any
from datetime import datetime

class Logger:
    """
    Centralized logging system for the application.
    Provides standardized logging with different levels and formats.
    """
    
    # Log levels
    DEBUG = logging.DEBUG
    INFO = logging.INFO
    WARNING = logging.WARNING
    ERROR = logging.ERROR
    CRITICAL = logging.CRITICAL
    
    # Default format
    DEFAULT_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    
    def __init__(
        self, 
        name: str, 
        level: int = logging.INFO,
        log_file: Optional[str] = None,
        log_format: str = DEFAULT_FORMAT
    ):
        """
        Initialize a logger instance
        
        Args:
            name: Name of the logger (typically module name)
            level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
            log_file: Optional file path to write logs to
            log_format: Format string for log messages
        """
        self.logger = logging.getLogger(name)
        self.logger.setLevel(level)
        self.logger.propagate = False
        
        # Clear any existing handlers
        if self.logger.handlers:
            self.logger.handlers.clear()
        
        # Create console handler
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(level)
        console_formatter = logging.Formatter(log_format)
        console_handler.setFormatter(console_formatter)
        self.logger.addHandler(console_handler)
        
        # Create file handler if log_file is provided
        if log_file:
            os.makedirs(os.path.dirname(log_file), exist_ok=True)
            file_handler = logging.FileHandler(log_file)
            file_handler.setLevel(level)
            file_formatter = logging.Formatter(log_format)
            file_handler.setFormatter(file_formatter)
            self.logger.addHandler(file_handler)
    
    def debug(self, message: str, **kwargs):
        """Log a debug message"""
        self._log(self.DEBUG, message, **kwargs)
    
    def info(self, message: str, **kwargs):
        """Log an info message"""
        self._log(self.INFO, message, **kwargs)
    
    def warning(self, message: str, **kwargs):
        """Log a warning message"""
        self._log(self.WARNING, message, **kwargs)
    
    def error(self, message: str, **kwargs):
        """Log an error message"""
        self._log(self.ERROR, message, **kwargs)
    
    def critical(self, message: str, **kwargs):
        """Log a critical message"""
        self._log(self.CRITICAL, message, **kwargs)
    
    def _log(self, level: int, message: str, **kwargs):
        """
        Internal method to log a message with additional context
        
        Args:
            level: Log level
            message: Log message
            **kwargs: Additional context to include in the log
        """
        if kwargs:
            # Format additional context as a string
            context_str = " ".join([f"{k}={v}" for k, v in kwargs.items()])
            message = f"{message} - {context_str}"
        
        self.logger.log(level, message)
    
    def log_agent_start(self, agent_name: str, task: str):
        """
        Log when an agent starts processing
        
        Args:
            agent_name: Name of the agent
            task: Description of the task
        """
        self.info(f"Agent '{agent_name}' started processing task: {task}")
    
    def log_agent_complete(self, agent_name: str, execution_time: float):
        """
        Log when an agent completes processing
        
        Args:
            agent_name: Name of the agent
            execution_time: Time taken to execute in seconds
        """
        self.info(f"Agent '{agent_name}' completed in {execution_time:.2f}s")
    
    def log_agent_error(self, agent_name: str, error: Exception):
        """
        Log when an agent encounters an error
        
        Args:
            agent_name: Name of the agent
            error: The exception that occurred
        """
        self.error(f"Agent '{agent_name}' encountered an error: {str(error)}", 
                  exc_info=error)
    
    def log_request(self, endpoint: str, request_data: Dict[str, Any]):
        """
        Log an API request
        
        Args:
            endpoint: The API endpoint
            request_data: The request data
        """
        self.info(f"Request to {endpoint}", request=request_data)
    
    def log_response(self, endpoint: str, status_code: int, response_data: Dict[str, Any]):
        """
        Log an API response
        
        Args:
            endpoint: The API endpoint
            status_code: HTTP status code
            response_data: The response data
        """
        self.info(f"Response from {endpoint} with status {status_code}", 
                 response=response_data)


# Create a default application logger
def get_app_logger(
    log_file: Optional[str] = None,
    level: int = logging.INFO
) -> Logger:
    """
    Get the application logger
    
    Args:
        log_file: Optional file path to write logs to
        level: Logging level
        
    Returns:
        Logger: The application logger
    """
    if log_file is None:
        # Create logs directory if it doesn't exist
        os.makedirs("logs", exist_ok=True)
        
        # Generate log file name with timestamp
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        log_file = f"logs/app_{timestamp}.log"
    
    return Logger("mango_ai_agent", level=level, log_file=log_file)


# Create a singleton app logger
app_logger = get_app_logger()
