# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/classes/50_DomoAccount.ipynb.

# %% auto 0
__all__ = ['DomoAccount', 'DomoAccount_Types', 'DomoAccounts_NoAccount', 'DomoAccounts']

# %% ../../nbs/classes/50_DomoAccount.ipynb 3
from domolibrary.routes.account import (
    Account_GET_Error,
    Account_NoMatch,
    Account_CRUD_Error,
    Account_CreateParams_Error,
    Account_Config_Error,
    ShareAccount,
    ShareAccount_V1_AccessLevel,
    ShareAccount_AccessLevel,
    Account_Share_Error,
    Account_AlreadyShared_Error,
)

from domolibrary.classes.DomoAccount_Config import (
    AccountConfig_UsesOauth,
    AccountConfig_ProviderTypeNotDefined,
    DomoAccount_Config,
    AccountConfig,
)

from domolibrary.classes.DomoAccount_Default import (
    Account_CanIModify,
    UpsertAccount_MatchCriteria,
    DomoAccount_Default,
    DomoAccounConfig_MissingFields,
)

from domolibrary.classes.DomoAccount_Credential import (
    DAC_NoTargetInstance,
    DAC_NoPassword,
    DAC_NoUserName,
    DAC_NoAccessToken,
    DAC_ValidAuth,
    DomoAccount_Credential,
)

from domolibrary.classes.DomoAccount_OAuth import (
    DomoAccount_OAuth,
    OAuthConfig
)

# %% ../../nbs/classes/50_DomoAccount.ipynb 4
from dataclasses import dataclass, field
from typing import List
from enum import Enum

import httpx
import datetime as dt
from copy import deepcopy

from nbdev.showdoc import patch_to

import domolibrary.routes.account as account_routes
import domolibrary.routes.datacenter as datacenter_routes

import domolibrary.client.DomoAuth as dmda
import domolibrary.client.DomoError as dmde
import domolibrary.utils.chunk_execution as dmce

# %% ../../nbs/classes/50_DomoAccount.ipynb 8
@dataclass
class DomoAccount(DomoAccount_Default):
    pass

# %% ../../nbs/classes/50_DomoAccount.ipynb 10
class DomoAccount_Types(Enum):
    CREDENTIAL = DomoAccount_Credential
    DEFAULT = DomoAccount

    @classmethod
    def _missing_(cls, value):
        value = value.lower()

        for member in cls:
            if member.value == value:
                return member

            if value == "domo-access-token" and member.name == "CREDENTIAL":
                return member

        return cls.DEFAULT

    @classmethod
    def get(cls, value):

        if value == "domo-access-token":
            return cls.CREDENTIAL.value

        try:
            return cls[value].value

        except:
            return cls.DEFAULT.value

# %% ../../nbs/classes/50_DomoAccount.ipynb 13
@patch_to(DomoAccount, cls_method=True)
def _from_json(
    cls,
    obj: dict,
    is_admin_summary: bool = True,
    auth: dmda.DomoAuth = None,
    is_use_default_account_class=False,
    **kwargs
):
    """converts data_v1_accounts API response into an accounts class object"""

    if is_use_default_account_class:
        new_class = DomoAccount_Types.DEFAULT.value

    else:
        new_class = DomoAccount_Types.get(
            obj.get("dataProviderId") or obj.get("dataProviderType")
        )

    return new_class._class_from_json(
        obj=obj, is_admin_summary=is_admin_summary, auth=auth, **kwargs
    )

# %% ../../nbs/classes/50_DomoAccount.ipynb 25
class DomoAccounts_NoAccount(dmde.ClassError):
    def __init__(self, cls=None, cls_instance=None, message=None, domo_instance=None):
        super().__init__(
            cls=cls, cls_instance=cls_instance, message=message, entity_id=domo_instance
        )


@dataclass
class DomoAccounts:
    auth: dmda.DomoAuth = field(repr=False)

    accounts: List[DomoAccount] = None
    oauths : List[DomoAccount_OAuth] = None

    @staticmethod
    async def _get_accounts_accountsapi(
        auth: dmda.DomoAuth,
        debug_api: bool = False,
        session: httpx.AsyncClient = None,
        return_raw: bool = False,
        is_use_default_account_class: bool = True,
        **kwargs,
    ):
        res = await account_routes.get_accounts(
            auth=auth, debug_api=debug_api, session=session
        )

        if return_raw:
            return res

        if len(res.response) == 0:
            return []

        return await dmce.gather_with_concurrency(
            n=60,
            *[
                DomoAccount.get_by_id(
                    account_id=json_obj.get("id"),
                    debug_api=debug_api,
                    session=session,
                    auth=auth,
                    is_use_default_account_class=is_use_default_account_class,
                    **kwargs,
                )
                for json_obj in res.response
            ],
        )

    @staticmethod
    async def _get_accounts_queryapi(
        auth: dmda.DomoAuth,
        debug_api: bool = False,
        additional_filters_ls=None,
        session: httpx.AsyncClient = None,
        return_raw: bool = False,
        is_use_default_account_class: bool = False,
        **kwargs,
    ):
        """v2 api for works with group_account_v2 beta"""

        import domolibrary.routes.datacenter as datacenter_routes

        res = await datacenter_routes.search_datacenter(
            auth=auth,
            entity_type=datacenter_routes.Datacenter_Enum.ACCOUNT.value,
            additional_filters_ls=additional_filters_ls,
            session=session,
            debug_api=debug_api,
        )

        if return_raw:
            return res

        if len(res.response) == 0:
            return []

        return [
            DomoAccount._from_json(
                account_obj,
                auth=auth,
                is_use_default_account_class=is_use_default_account_class,
                **kwargs,
            )
            for account_obj in res.response
        ]

    async def get(
        self,
        debug_api: bool = False,
        session: httpx.AsyncClient = None,
        return_raw: bool = False,
        is_use_default_account_class: bool = False,
        debug_num_stacks_to_drop: int = 2,
        **kwargs,
    ):
        domo_accounts = None
        try:
            domo_accounts = await self._get_accounts_queryapi(
                auth=self.auth,
                debug_api=debug_api,
                session=session,
                is_use_default_account_class=is_use_default_account_class,
                return_raw=return_raw,
                debug_num_stacks_to_drop=debug_num_stacks_to_drop + 1,
                **kwargs,
            )

        except datacenter_routes.SearchDatacenter_NoResultsFound as e:
            print(e)

        if not domo_accounts:
            domo_accounts = await self._get_accounts_accountsapi(
                auth=self.auth,
                debug_api=debug_api,
                session=session,
                debug_num_stacks_to_drop=debug_num_stacks_to_drop + 1,
                is_use_default_account_class=is_use_default_account_class,
                return_raw=return_raw,
                **kwargs,
            )

        if return_raw:
            return domo_accounts

        self.accounts = domo_accounts
        return self.accounts

# %% ../../nbs/classes/50_DomoAccount.ipynb 27
@patch_to(DomoAccounts)
async def get_oauths(
    self,
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
    return_raw: bool = False,
    debug_num_stacks_to_drop: int = 2,
):
    res = await account_routes.get_oauth_accounts(
        auth=self.auth,
        debug_api=debug_api,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=self.__class__ .__name__,
    )

    if return_raw:
        return res
    
    return [ DomoAccount_OAuth._from_json(obj = obj, auth = self.auth) for obj in res.response]

    return res

# %% ../../nbs/classes/50_DomoAccount.ipynb 30
@patch_to(DomoAccounts, cls_method=True)
async def upsert_account(
    cls: DomoAccounts,
    auth: dmda.DomoAuth,

    account_id: str = None,
    account_name: str = None,
    account_config: AccountConfig = None,
    
    debug_api: bool = False,
    debug_prn: bool = False,
    return_raw: bool = False,
    return_search: bool = False,
    is_use_default_account_class: bool = True,
    session: httpx.AsyncClient = None,
    **kwargs,
):
    """search for an account and upsert it"""

    if not account_name and not account_id:
        raise UpsertAccount_MatchCriteria(domo_instance=auth.domo_instance)

    acc = None

    if account_id:
        try:
            acc = await DomoAccount.get_by_id(
                auth=auth,
                session=session,
                debug_api=debug_api,
                account_id=account_id,
                is_use_default_account_class=is_use_default_account_class,
                **kwargs,
            )
        except dmde.DomoError:
            pass

    if account_name and not acc:
        try:
            domo_accounts = DomoAccounts(auth =auth)
            await domo_accounts.get(
                debug_api=debug_api,
                session=session,
                is_use_default_account_class=is_use_default_account_class,
                **kwargs,
            )

            acc = next((da for da in domo_accounts.accounts if da.name.lower() == account_name.lower()), None)
        
        except dmde.DomoError:
            pass

    if return_search:
        return acc

    if not isinstance(acc, (DomoAccount_Default, DomoAccount, DomoAccount_Credential)):
        if debug_prn:
            print(f"creating {account_name} in {auth.domo_instance}")

        return await DomoAccount.create_account(
            account_name=account_name,
            config=account_config,
            auth=auth,
            debug_api=debug_api,
            return_raw=return_raw,
        )

    if account_name and account_id:
        if debug_prn:
            print(f"upsert-ing {acc.id} - {acc.name} in {auth.domo_instance}")

        await acc.update_name(
            account_name=account_name,
            debug_api=debug_api,
            return_raw=return_raw,
            session=session,
        )

    if account_config:  # upsert account
        acc.Config = account_config

        if debug_prn:
            print(f"upsertting {acc.id}:  updating config")

        await acc.update_config(
            debug_api=debug_api, return_raw=return_raw, session=session
        )

    return acc


@patch_to(DomoAccount_Default)
async def upsert_target_account(
    self,
    target_auth: dmda.DomoAuth,  # valid auth for target destination
    account_name: str = None,  # defaults to self.name
    debug_api: bool = False,
):
    """
    upsert an account in a target instance with self.Config
    """

    return await DomoAccounts.upsert_account(
        auth=target_auth,
        account_name=account_name or self.name,
        account_config=deepcopy(self.Config),
        debug_api=debug_api,
    )
