import typing

from conio_domain.wallet import WalletCryptoCurrency
from vault_client.client.types import AcceptanceType, AcceptanceChoiceType

from conio_sdk.common import ACCEPTANCE_TYPE_NAMES_BY_PB2
from conio_sdk.generated_protobuf import v1_pb2
from conio_sdk.services.conio.user.user_service import UserService, UserCredentials, AuthenticationData
from conio_sdk.services.conio.wallet.core_wallet_service import CoreWalletService


class LoginVOServices:
    _ACCEPTANCES_PB2 = {
        AcceptanceType.APP_IMPROVEMENT: ACCEPTANCE_TYPE_NAMES_BY_PB2[v1_pb2.ACCEPTANCE_APP_IMPROVEMENT],
        AcceptanceType.CLIENT_SUPPORT: ACCEPTANCE_TYPE_NAMES_BY_PB2[v1_pb2.ACCEPTANCE_CLIENT_SUPPORT]
    }

    def __init__(self, user_service: UserService, core_wallet_service: CoreWalletService):
        self._user_service = user_service
        self._core_wallet_service = core_wallet_service

    def login(
            self, msg: v1_pb2.Login, user_language: typing.Optional[str]) -> typing.Tuple[v1_pb2.LoginResponse, AuthenticationData]:
        authentication_data = self._user_service.external_user_login(
            UserCredentials(
                msg.conioCredentials.externalUserID,
                msg.conioCredentials.hashedConioPassword
            ),
            user_language
        )

        user = self._user_service.get_user(msg.conioCredentials.externalUserID)
        response = v1_pb2.LoginResponse()
        wallet = user.get_wallet(WalletCryptoCurrency.BITCOIN)
        response.encryptedUserKey.encryptedPrivateKey = wallet['encrypted_private_key']
        response.encryptedUserKey.encryptedMnemonic = wallet['encrypted_mnemonic']
        response.encryptedUserKey.encryptedSeed = wallet['encrypted_seed']
        response.encryptedUserKey.bip32PublicKey = \
            self._core_wallet_service.get_bip32_public_key(wallet['reference_id'])
        for a, c in user.acceptances.items():
            if a not in self._ACCEPTANCES_PB2:
                continue
            response.tc.acceptances.add(
                acceptance_type=self._ACCEPTANCES_PB2[a],
                acceptance_choice=
                c == AcceptanceChoiceType.ACCEPTED and v1_pb2.ACC_CHOICE_ACCEPTED or v1_pb2.ACC_CHOICE_REJECTED
            )
        return response, authentication_data
