import typing

from bithustler_client.client.client import BithustlerClient
from cards_client.client.client import CardsClient
from cards_client.generated_protobuf import base_pb2
from vault_client.client.client_definition import VaultClient
from vault_client.client.conio_user import ConioUser

from conio_sdk.common.decorators import xray_this
from conio_sdk.services.conio import UserLevel
from conio_sdk.services.conio.fiat_limits.fiat_limits_service import FiatLimitsService


class CardsBithustlerFiatLimitsService(FiatLimitsService):
    def __init__(
            self,
            bithustler_client: BithustlerClient,
            cards_client: CardsClient,
            vault_client: VaultClient):
        self._bithustler_client = bithustler_client
        self._cards_client = cards_client
        self._vault_client = vault_client

    def _ensure_payer_id(self, user: ConioUser) -> typing.Optional[str]:
        payer_id = user.cards_integration_id
        if not payer_id:
            resp = self._cards_client.create_payer(base_pb2.MsgCreatePayer(payer_descr=user.reference_key_id))
            if resp.HasField('error'):
                raise ValueError(str(resp))
            payer_id = resp.data.payer_id
            return payer_id
        return None

    def _ensure_seller_id(self, user: ConioUser) -> typing.Optional[str]:
        seller_id = user.seller_id
        if not seller_id:
            return self._bithustler_client.create_seller(user.reference_key_id).id
        return None

    @xray_this
    def associate_fiat_limits(self, user: ConioUser, user_level: UserLevel):
        user_data_to_upgrade = {}
        new_payer_id = self._ensure_payer_id(user)
        if new_payer_id:
            user_data_to_upgrade['cards_integration_id'] = new_payer_id
        new_seller_id = self._ensure_seller_id(user)
        if new_seller_id:
            user_data_to_upgrade['seller_id'] = new_seller_id

        if user_data_to_upgrade:
            self._vault_client.save_user_info_v2(user_data_to_upgrade, user.reference_key_id)

        self._cards_client.set_fiat_limits_by(
            new_payer_id or user.cards_integration_id, description=user_level,
            associate_virtual_iban=False
        )
        limits = self._bithustler_client.get_limits_by(description=user_level)
        self._bithustler_client.set_limits(new_seller_id or user.seller_id, *(l.uuid for l in limits.fiat_limits))

    @xray_this
    def associate_payer_and_seller(self, user: ConioUser):
        payer_id, seller_id = self._ensure_payer_id(user), self._ensure_seller_id(user)
        user_info_dict = dict()
        if payer_id:
            user_info_dict['cards_integration_id'] = payer_id
        if seller_id:
            user_info_dict['seller_id'] = seller_id
        if user_info_dict:
            self._vault_client.save_user_info(user_info_dict, reference_user_id=user.reference_key_id)
