"""Base middleware interface."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any, Dict, Optional


class Middleware(ABC):
    """Base class for all middleware components.
    
    Middleware can intercept requests before they reach tools and responses
    before they're returned to clients. This enables cross-cutting concerns
    like authentication, rate limiting, logging, and metrics.
    """
    
    def __init__(self, name: Optional[str] = None):
        """Initialize the middleware.
        
        Args:
            name: Optional name for the middleware (defaults to class name)
        """
        self.name = name or self.__class__.__name__
        self._enabled = True
    
    @abstractmethod
    async def before_request(self, request: Dict[str, Any]) -> Dict[str, Any]:
        """Process request before it reaches the tool handler.
        
        Args:
            request: The request data with tool_name, arguments, context
            
        Returns:
            Modified request (or original if no changes)
            
        Raises:
            Exception: If the request should be rejected
        """
        pass
    
    @abstractmethod
    async def after_response(self, response: Any, request: Dict[str, Any]) -> Any:
        """Process response before it's returned to the client.
        
        Args:
            response: The response from the tool handler
            request: The original request data
            
        Returns:
            Modified response (or original if no changes)
        """
        pass
    
    def enable(self) -> None:
        """Enable this middleware."""
        self._enabled = True
    
    def disable(self) -> None:
        """Disable this middleware."""
        self._enabled = False
    
    def is_enabled(self) -> bool:
        """Check if middleware is enabled.
        
        Returns:
            True if enabled, False otherwise
        """
        return self._enabled


class MiddlewareStack:
    """Stack of middleware to apply to requests/responses.
    
    Middleware are applied in order for requests (first to last)
    and in reverse order for responses (last to first).
    """
    
    def __init__(self):
        """Initialize the middleware stack."""
        self._middleware: list[Middleware] = []
    
    def add(self, middleware: Middleware) -> None:
        """Add middleware to the stack.
        
        Args:
            middleware: Middleware instance to add
        """
        self._middleware.append(middleware)
    
    def remove(self, middleware: Middleware) -> None:
        """Remove middleware from the stack.
        
        Args:
            middleware: Middleware instance to remove
        """
        if middleware in self._middleware:
            self._middleware.remove(middleware)
    
    async def process_request(self, request: Dict[str, Any]) -> Dict[str, Any]:
        """Process request through all middleware.
        
        Args:
            request: The request data
            
        Returns:
            Processed request
            
        Raises:
            Exception: If any middleware rejects the request
        """
        result = request
        for middleware in self._middleware:
            if middleware.is_enabled():
                result = await middleware.before_request(result)
        return result
    
    async def process_response(self, response: Any, request: Dict[str, Any]) -> Any:
        """Process response through all middleware in reverse order.
        
        Args:
            response: The response data
            request: The original request data
            
        Returns:
            Processed response
        """
        result = response
        for middleware in reversed(self._middleware):
            if middleware.is_enabled():
                result = await middleware.after_response(result, request)
        return result
    
    def clear(self) -> None:
        """Clear all middleware from the stack."""
        self._middleware.clear()
    
    def list_middleware(self) -> list[str]:
        """List all middleware names.
        
        Returns:
            List of middleware names
        """
        return [m.name for m in self._middleware]

