import random
import string
import unittest
import uuid

from bithustler_client.generated_protobuf import bithustler_pb2
from cards_client.generated_protobuf import base_pb2
from schwifty import IBAN

from conio_sdk.ioc import ioc_bithustler, ioc_cards, ioc_bittrade
from test.integration import SELL_LIMIT, USER_LEVEL, BUY_LIMIT


class BaseIntegrationTest(unittest.TestCase):
    def setUp(self) -> None:
        self._create_limits()

    @classmethod
    def _create_limits(cls):
        ioc_bithustler.bithustler_client.get_or_create_limit(
            bithustler_pb2.FiatLimit(
                limit_type=bithustler_pb2.DAILY,
                limit=SELL_LIMIT,
                currency=bithustler_pb2.EUR,
                description=USER_LEVEL
            )
        )
        ioc_cards.cards_client.create_fiat_limit(
            base_pb2.FiatLimit(
                limit_type=base_pb2.DAILY,
                limit=BUY_LIMIT,
                currency=base_pb2.EUR,
                description=USER_LEVEL
            )
        )
        ioc_cards.cards_client.create_fiat_limit(
            base_pb2.FiatLimit(
                limit_type=base_pb2.DAILY,
                limit=BUY_LIMIT,
                currency=base_pb2.EUR,
                description=USER_LEVEL,
                payment_method_family=base_pb2.PAYMENT_METHOD_FAMILY_WIRETRANSFER
            )
        )

    @classmethod
    def create_explicit_fees(cls):
        try:
            explicit_fees = next(iter(
                filter(
                    lambda d: d.description == USER_LEVEL,
                    ioc_bittrade.bittrade_client.get_explicit_fees()
                )
            )
            )
            ioc_bittrade.bittrade_client.update_explicit_fees(
                uuid.UUID(explicit_fees.explicit_fees_id),
                'EUR', USER_LEVEL, 0, True, 0, True
            )
        except StopIteration:
            ioc_bittrade.bittrade_client.create_explicit_fees(
                'EUR', USER_LEVEL, 0, True, 0, True
            )

    @classmethod
    def random_iban(cls, nation: str = 'IT') -> str:
        return str(IBAN.generate(
            nation, bank_code=cls.random_strnum(5),
            account_code=cls.random_strnum(12)))

    @classmethod
    def random_strnum(cls, num_digits: int) -> str:
        return ''.join(map(lambda _: random.choice(string.digits), range(num_digits)))
