import logging
from typing import Callable
from .access_control import AccessControl

class WatchMaster:
    """The WatchMaster ensures all Genesis operations are gated through the RWL."""

    def __init__(self, access_control: AccessControl, bypass_allowed: bool = False):
        self.access_control = access_control
        self.bypass_allowed = bypass_allowed # For exceptional circumstances during initial bootstrapping.  NEVER use in production.
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.INFO) # Or whatever level you need

    def enforce(self, operation: Callable, *args, context: dict = None, **kwargs):
        """Enforces the RWL guard on a given operation.

        Args:
            operation: The callable representing the operation to be performed.
            *args: Positional arguments to pass to the operation.
            context:  A dictionary providing context for access control decisions.
            **kwargs: Keyword arguments to pass to the operation.

        Returns:
            The result of the operation if access is granted.

        Raises:
            PermissionError: If access is denied.
        """
        if self.bypass_allowed:
           self.logger.warning("RWL Guard bypassed!  DO NOT USE IN PRODUCTION.")
           return operation(*args, **kwargs)

        if self.access_control.is_allowed(operation, context):
            self.logger.debug(f"Access granted for operation: {operation.__name__}")
            return operation(*args, **kwargs)
        else:
            self.logger.error(f"Access denied for operation: {operation.__name__}")
            raise PermissionError(f"Operation {operation.__name__} denied by RWL.")

    def check_access(self, operation: Callable, context: dict = None) -> bool:
        """Checks if access is allowed for a given operation without executing it.

        Args:
            operation: The callable representing the operation to be checked.
            context: A dictionary providing context for access control decisions.

        Returns:
            True if access is allowed, False otherwise.
        """
        return self.access_control.is_allowed(operation, context)
