import json

from application.interactor import ApplyBenefitInteractor
from application.model import AsyncUuidMessageProcessor
from messagebus import DefaultToken, DataType, Message, MessageBus, Event
from typing import (
    Optional,
    Any,
    List
)


class ApplyBenefitProcessor(AsyncUuidMessageProcessor):

    def __init__(self, interactor):
        # type: (ApplyBenefitInteractor) -> None

        super(ApplyBenefitProcessor, self).__init__()
        self.interactor = interactor

    def parse_data(self, data):
        # type: (str) -> (int, int, str)

        parsed_data = json.loads(data)
        pos_id = int(parsed_data.get("posId"))
        originator_pos_id = int(parsed_data.get("originatorPosId") or pos_id)
        voucher_id = str(parsed_data.get("voucherId"))
        user_auth_level = parsed_data.get("user_auth_level") or -1

        return pos_id, originator_pos_id, voucher_id, user_auth_level

    def call_business(
            self,
            params      # type: List[int, int, str, bool]
    ):
        # type: (...) -> None

        pos_id, originator_pos_id, voucher_id, user_auth_level = params
        self.interactor.apply_benefit(
                current_pos_id=pos_id,
                originator_pos_id=originator_pos_id,
                voucher_id=voucher_id,
                user_auth_level=user_auth_level
        )

    def format_response(self, message_bus, message, event, request, response):
        # type: (MessageBus, Optional[Message], Optional[Event], Any, Any) -> None

        message_bus.reply_message(message, Message(DefaultToken.TK_SYS_ACK, DataType.string, response))

    def format_exception(self, message_bus, message, event, input_obj, exception):
        # type: (MessageBus, Optional[Message], Optional[Event], Any, BaseException) -> None

        message_bus.reply_message(message, Message(DefaultToken.TK_SYS_NAK, DataType.param, str(exception)))

    def format_parse_exception(self, message_bus, message, event, data, exception):
        # type: (MessageBus, Optional[Message], Optional[Event], bytes, BaseException) -> None

        message_bus.reply_message(message, Message(DefaultToken.TK_SYS_NAK, DataType.param, str(exception)))
