from admac.grpc.accounts_pb2 import (
    AssetCreateRequest,
    EducationalExperienceRequest,
    GoalRequest,
    ListAssetRequest,
    ProfileRequest,
    SkillRequest,
    SocialMediaRequest,
    SuggestionRequest,
    UserBulkRetrieveRequest,
    UserRetrieveRequest,
    UserUpdateRequest,
    WalletRetrieveRequest,
    WalletSpendRequest,
    WalletTopupRequest,
    WorkExperienceRequest,
)
from admac.grpc.accounts_pb2_grpc import (
    AssetControllerStub,
    UserControllerStub,
    WalletControllerStub,
)

SUCCESS_CODE = "0"


def _singletonize_class_vars(cls):
    for attr_name, attr_value in cls.__dict__.items():
        if isinstance(attr_value, type):  # it's a class
            orig_cls = attr_value

            class SingletonWrapper(orig_cls):
                _instances = {}

                def __new__(cls, *args, **kwargs):
                    if cls not in cls._instances:
                        cls._instances[cls] = super().__new__(cls)
                    return cls._instances[cls]

            setattr(cls, attr_name, SingletonWrapper)
    return cls


class RequestMessages:
    # Main
    FETCH_USER = UserRetrieveRequest
    FETCH_BULK_USER = UserBulkRetrieveRequest
    UPDATE_USER = UserUpdateRequest
    CREATE_ASSET = AssetCreateRequest
    LIST_ASSET = ListAssetRequest
    FETCH_WALLET = WalletRetrieveRequest
    TOPUP_WALLET = WalletTopupRequest
    SPEND_WALLET = WalletSpendRequest

    # Side
    PROFILE = ProfileRequest
    WORK_EXPERIENCE = WorkExperienceRequest
    SKILL = SkillRequest
    EDUCATIONAL_EXPERIENCE = EducationalExperienceRequest
    GOAL = GoalRequest
    SUGGESTION = SuggestionRequest
    SOCIAL_MEDIA = SocialMediaRequest


class RPCMethodNames:
    FETCH_ONE = "Retrieve"
    FETCH_BULK = "BulkRetrieve"
    FETCH_ALL = "List"
    FETCH_ONE_PACKAGE = "RetrievePackage"
    FETCH_ALL_PACKAGES = "ListPackages"
    SPEND = "Spend"
    TOPUP = "Topup"
    UPDATE_ONE = "Update"
    CREATE = "Create"


@_singletonize_class_vars
class Stubs:
    USER = UserControllerStub
    ASSET = AssetControllerStub
    WALLET = WalletControllerStub
