from typing import Any, Callable, Dict, Optional, Tuple, Type, Union

from edpauthorization.dto import AuthorizationAction
from edpauthorization.exception import NotAuthorizedException
from edpauthorization.registry import set_action_name, set_resource_type
from httpmessageprocessorutil.automapped import AutoMappedMessageProcessor

from ._utils import reply_forbidden


class SecureApiProcessor(AutoMappedMessageProcessor):
    def __init__(
        self,
        request_type: Optional[Type],
        interactor: Any,
        exception_map: Optional[Dict[type, Union[int, Tuple[int, Any], Callable]]] = None,
        success_status: int = 200,
        extra_mapping: dict = None,
        event_name: Optional[str] = None,
        response_content_type: Optional[str] = None,
        resource_type: str | None = None,
        action_name: AuthorizationAction | None = None,
    ):
        super().__init__(
            request_type=request_type,
            interactor=interactor,
            exception_map=exception_map,
            success_status=success_status,
            extra_mapping=extra_mapping,
            event_name=event_name,
            response_content_type=response_content_type,
        )
        self.resource_type = resource_type
        self.action_name = action_name

    def parse_data(self, api_request, event_type):
        set_resource_type(self.resource_type)
        set_action_name(self.action_name)
        return super().parse_data(api_request, event_type)

    def format_exception(self, message_bus, message, event, input_obj, exception):
        if isinstance(exception, NotAuthorizedException):
            reply_forbidden(message_bus=message_bus, message=message)
            return
        super().format_exception(message_bus, message, event, input_obj, exception)

    def format_parse_exception(self, message_bus, message, event, data, exception):
        if isinstance(exception, NotAuthorizedException):
            reply_forbidden(message_bus=message_bus, message=message)
            return
        super().format_parse_exception(message_bus, message, event, data, exception)
