import logging

from logging import Logger
from typing import (
    Any,
    Dict,
    Optional,
    Tuple,
    Type,
    Union,
)

from helper import config_logger
from httpmessageprocessorutil.automapped import AutoMappedMessageProcessor
from httpmessageprocessor import ApiRequest
from messagebus import (
    Event,
    Message,
    MessageBus,
)


class PosLoggerAutoMappedMessageProcessor(AutoMappedMessageProcessor):

    def __init__(
        self,
        request_type,                   # type: Optional[Type]
        interactor,                     # type: Any
        logger_created,                 # type: dict
        exception_map=None,             # type: Optional[Dict[type, Union[int, Tuple[int, str]]]]
        success_status=200,             # type: int
        extra_mapping=None,             # type: dict
        event_name=None,                # type: Optional[str]
        response_content_type=None,     # type: Optional[str]
        log_path=None,                  # type: Optional[str]
        component_name=None,            # type: Optional[str]
        logger=None,                    # type: Optional[Logger]
    ):
        # type: (...) -> None

        super(PosLoggerAutoMappedMessageProcessor, self).__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.logger_created = logger_created
        self.logger = logger
        self.component_name = component_name
        self.log_path = log_path
        self.interactor = interactor

    def parse_data(
        self,
        api_request,    # type: ApiRequest
        event_type,     # type: Optional[str]
    ):
        # type: (...) -> Any

        try:
            pos_id = api_request.path_parameters.get("posId")
            if pos_id:
                log_name = "{}_{:02d}".format(
                    self.component_name,
                    int(pos_id),
                )
                if log_name not in self.logger_created:
                    config_logger(
                        loader_path=self.log_path,
                        log_name=log_name,
                        root_level=logging.DEBUG,
                    )
                    self.logger_created[log_name] = True

                internal_order_logger = logging.getLogger(name=log_name)
                self.interactor.logger = internal_order_logger
                self.interactor.logger.info(msg=api_request)
        except Exception as e:
            if self.logger:
                self.logger.exception(e)

        return super(PosLoggerAutoMappedMessageProcessor, self).parse_data(
            api_request=api_request,
            event_type=event_type,
        )

    def format_exception(
        self,
        message_bus,    # type: MessageBus
        message,        # type: Message
        event,          # type: Event
        input_obj,      # type: Any
        exception,      # type: Exception
    ):
        # type: (...) -> None

        self.interactor.logger.exception(exception)
        super(PosLoggerAutoMappedMessageProcessor, self).format_exception(
            message_bus=message_bus,
            message=message,
            event=event,
            input_obj=input_obj,
            exception=exception,
        )

    def format_parse_exception(
        self,
        message_bus,    # type: MessageBus
        message,        # type: Message
        event,          # type: Event
        data,           # type: Any
        exception,      # type: Exception
    ):
        # type: (...) -> None

        self.interactor.logger.exception(exception)
        super(PosLoggerAutoMappedMessageProcessor, self).format_parse_exception(
            message_bus=message_bus,
            message=message,
            event=event,
            data=data,
            exception=exception,
        )
