import json

from messagebus import (
    AckMessage,
    Message,
    MessageBus,
    InternalErrorMessage,
)
from messageprocessorutil import UuidMessageProcessor
from typing import (
    Any,
    Optional,
)

from devicemanager.interactor.get_used_service import GetUsedServiceInteractor
from devicemanager.interactor.get_used_service.dto import GetUsedServiceRequest


class GetUsedServiceProcessor(UuidMessageProcessor):
    def __init__(
        self,
        get_used_service_interactor,    # type: GetUsedServiceInteractor
    ):
        # type: (...) -> None

        super(GetUsedServiceProcessor, self).__init__()
        self.get_used_service_interactor = get_used_service_interactor

    def parse_data(
        self,           # type: GetUsedServiceProcessor
        data,           # type: str
        event_type,     # type: str
    ):
        # type: (...) -> GetUsedServiceRequest

        request_json = json.loads(data)
        self._validate_request(request_json)
        return GetUsedServiceRequest(
            pos_id=request_json.get("posId", None),
            device_type=request_json["deviceType"],
            sector=request_json.get("sector", None),
            kds_id=request_json.get("kdsId", None),
            brand=request_json.get("brand", None),
        )

    def call_business(
        self,       # type: GetUsedServiceProcessor
        request,    # type: GetUsedServiceRequest
    ):
        # type: (...) -> str

        return self.get_used_service_interactor.get_used_service(request=request)

    def format_response(
        self,           # type: GetUsedServiceProcessor
        message_bus,    # type: MessageBus
        message,        # type: Message
        event,          # type: Optional[Any]
        request,        # type: GetUsedServiceRequest
        result,         # type: str
    ):
        # type: (...) -> None

        data = result.encode("utf-8") if result is not None else None
        message_bus.reply_message(
            message=message,
            reply_message=AckMessage(data=data),
        )

    def format_exception(
        self,           # type: GetUsedServiceProcessor
        message_bus,    # type: MessageBus
        message,        # type: Message
        event,          # type: Optional[Any]
        input_obj,      # type: GetUsedServiceRequest
        exception,      # type: Exception
    ):
        # type: (...) -> None

        message_bus.reply_message(
            message=message,
            reply_message=InternalErrorMessage(ex=exception),
        )

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

        message_bus.reply_message(
            message=message,
            reply_message=InternalErrorMessage(ex=exception),
        )

    @staticmethod
    def _validate_request(
        request_json,   # type: dict
    ):
        # type: (...) -> None

        if "deviceType" not in request_json:
            raise Exception("Invalid request json: deviceType key not sent")
        if "posId" not in request_json and "kdsId" not in request_json:
            raise Exception("Invalid request json: posId nor kdsId sent")
