from typing import Tuple, Optional

from clarabot_nano.common.core.message import MSG_TYPE_REQUEST_CONFIG_UPDATE
from clarabot_nano.common.handler.base import NanoHandlerError
from clarabot_nano.common.protocol.errors import (
    NANO_REQUEST_ERROR_HANDLER_BAD_REQUEST,
    NANO_REQUEST_ERROR_HANDLER_DENIED,
)
from clarabot_nano.server.base.handler.base import AbstractNanoServerHandler
from clarabot_nano.server.general.handler.base import GeneralServerHandleHelper
from clarabot_nano.utility.serialize import msgpack_dumps, msgpack_loads


class AbstractAdminConfigUpdateServerHandler(AbstractNanoServerHandler):
    REQUIRES_OWNER_IDENTITY = True
    REQUIRES_ADMIN_PASSWORD = True

    helper: GeneralServerHandleHelper

    async def _create_request_key(self) -> Tuple[bool, Optional[list], int]:
        return False, None, 1

    async def _execute_initial(self) -> dict:
        reply = await self.helper.core_requester.request(
            [MSG_TYPE_REQUEST_CONFIG_UPDATE, msgpack_dumps(self._create_config_update_request())]
        )
        if len(reply) == 1:
            response = msgpack_loads(reply[0])
            if bool(response.get("ok")):
                return await AbstractNanoServerHandler._execute_initial(self)
            if response.get("info") == "sensitive":
                raise NanoHandlerError(NANO_REQUEST_ERROR_HANDLER_DENIED, "Config update denied", self.context)
        raise NanoHandlerError(NANO_REQUEST_ERROR_HANDLER_BAD_REQUEST, "Config update failed", self.context)

    def _create_config_update_request(self) -> dict:
        raise NotImplementedError()

    async def _execute_part(self, part: int, s_hmac_start_part: Optional[int]) -> dict:  # pragma: no cover
        raise NanoHandlerError(NANO_REQUEST_ERROR_HANDLER_BAD_REQUEST, "Part request is invalid", self.context)
