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

# %% auto 0
__all__ = ['DomoAccountOAuth_Config_SnowflakeOauth', 'DomoAccountOAuth_Config_JiraOnPremOauth', 'OAuthConfig',
           'DomoAccount_OAuth']

# %% ../../nbs/classes/50_DomoAccount_OAuth.ipynb 3
from dataclasses import dataclass, field
import httpx
from typing import Any

import domolibrary.client.DomoAuth as dmda

import domolibrary.routes.account as account_routes
import domolibrary.classes.DomoAccount_Default as dmacb
import domolibrary.classes.DomoAccount_Config as dmacnfg
import domolibrary.classes.DomoAccess as dmacc

from nbdev.showdoc import patch_to

# %% ../../nbs/classes/50_DomoAccount_OAuth.ipynb 7
@dataclass
class DomoAccountOAuth_Config_SnowflakeOauth(dmacnfg.DomoAccount_Config):
    data_provider_type: str = "snowflake-oauth-config"
    is_oauth: bool = True

    client_id: str = None
    secret: str = None

    @classmethod
    def _from_json(cls, obj: dict, parent: Any = None, **kwargs):
        return cls(
            client_id=obj["client-id"],
            secret=obj["client-secret"],
            raw=obj,
            parent=parent,
        )

    def to_json(self):
        return {"client-id": self.client_id, "client-secret": self.secret}


@dataclass
class DomoAccountOAuth_Config_JiraOnPremOauth(dmacnfg.DomoAccount_Config):
    data_provider_type: str = "jira-on-prem-oauth-config"
    is_oauth: bool = True

    client_id: str = None
    secret: str = None

    @classmethod
    def _from_json(cls, obj: dict, parent: Any = None):
        return cls(
            client_id=obj["client_id"],
            secret=obj["client_secret"],
            raw=obj,
            parent=parent,
        )

    def to_json(self):
        return {"client_id": self.client_id, "client_secret": self.secret}


class OAuthConfig(dmacnfg.ConfigEnum):
    snowflake_oauth_config = DomoAccountOAuth_Config_SnowflakeOauth

    jira_on_prem_oauth_config = DomoAccountOAuth_Config_JiraOnPremOauth

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

        config_match = next(
            (member for member in cls if member.name in [value, alt_search_str]),
            None,
        )

        ## best case scenario alt_search yields a result
        if not config_match:
            raise dmacnfg.AccountConfig_ProviderTypeNotDefined(value)

        return config_match

# %% ../../nbs/classes/50_DomoAccount_OAuth.ipynb 9
@dataclass
class DomoAccount_OAuth(dmacb.DomoAccount_Default):
    Access: dmacc.DomoAccess_OAuth = field(repr=False, default=None)

    def __post_init__(self):
        self.Access = dmacc.DomoAccess_OAuth(auth=self.auth, parent=self)

    async def _get_config(
        self,
        session=None,
        return_raw: bool = False,
        debug_api: bool = None,
        debug_num_stacks_to_drop=2,
        is_suppress_no_config: bool = False,  # can be used to suppress cases where the config is not defined, either because the account_config is OAuth, and therefore not stored in Domo OR because the AccountConfig class doesn't cover the data_type
    ):
        if not self.data_provider_type:
            res = await account_routes.get_account_by_id(
                auth=self.auth,
                account_id=self.id,
                session=session,
                debug_api=debug_api,
                parent_class=self.__class__.__name__,
                debug_num_stacks_to_drop=debug_num_stacks_to_drop,
            )

            self.data_provider_type = res.response["dataProviderType"]

        res = await account_routes.get_oauth_account_config(
            auth=self.auth,
            account_id=self.id,
            session=session,
            debug_api=debug_api,
            data_provider_type=self.data_provider_type,
            parent_class=self.__class__.__name__,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        )

        if return_raw:
            return res

        config_fn = OAuthConfig(self.data_provider_type).value

        if not is_suppress_no_config and not config_fn.is_defined_config:
            raise config_fn._associated_exception(self.data_provider_type)

        self.Config = config_fn._from_json(res.response)

        if self.Config and self.Config.to_json() != {}:
            if not res.response:
                print(self.data_provider_type, "no response")

            if not self.Config.to_json():
                print(
                    self.id,
                    self.data_provider_type,
                    "no config",
                    self.Config.to_json(),
                    res.response,
                )

            self._test_missing_keys(
                res_obj=res.response, config_obj=self.Config.to_json()
            )

        return self.Config

    @classmethod
    async def get_by_id(
        cls,
        auth: dmda.DomoAuth,
        account_id: int,
        is_suppress_no_config: bool = True,
        session: httpx.AsyncClient = None,
        return_raw: bool = False,
        debug_api: bool = False,
        debug_num_stacks_to_drop=2,
        **kwargs
    ):
        """retrieves account metadata and attempts to retrieve config"""

        res = await account_routes.get_oauth_account_by_id(
            auth=auth,
            account_id=account_id,
            session=session,
            debug_api=debug_api,
            parent_class=cls.__name__,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        )

        if return_raw:
            return res

        acc = cls._from_json(
            obj=res.response,
            auth=auth,
            is_admin_summary=False,
            is_use_default_account_class=False,
            **kwargs
        )

        await acc._get_config(
            session=session,
            debug_api=debug_api,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop + 1,
            is_suppress_no_config=is_suppress_no_config,
        )

        return acc

    @classmethod
    async def create(
        cls,
        auth: dmda.DomoAuth,
        account_name: str,
        oauth_config: OAuthConfig,
        origin: str = "OAUTH_CONFIGURATION",
        debug_api: bool = False,
        session: httpx.AsyncClient = None,
        debug_num_stacks_to_drop=2,
    ):
        res = await account_routes.create_oauth_account(
            account_name=account_name,
            data_provider_type=oauth_config.data_provider_type,
            origin=origin,
            config=oauth_config.to_json(),
            debug_api=debug_api,
            session=session,
            parent_class=cls.__name__,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        )

        return await cls.get_by_id(
            auth=auth,
            account_id=res.response["id"],
            debug_api=debug_api,
            session=session,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        )

    async def delete(
        self,
        debug_api: bool = False,
        debug_num_stacks_to_drop=2,
        session: httpx.AsyncClient = None,
    ):
        return await account_routes.delete_oauth_account(
            auth=self.auth,
            account_id=self.id,
            debug_api=debug_api,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
            parent_class=self.__class__.__name__,
            session=session,
        )

    async def update_name(
        self,
        account_name: str,
        debug_api: bool = False,
        debug_num_stacks_to_drop: int = 2,
        session: httpx.AsyncClient = None,
    ):
        await account_routes.update_oauth_account_name(
            auth=self.auth,
            account_id=self.id,
            account_name=account_name,
            debug_api=debug_api,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
            parent_class=self.__class__.__name__,
            session=session,
        )

        self.name = account_name
        return self

    async def update_config(
        self,
        oauth_config: OAuthConfig = None,
        debug_api: bool = False,
        debug_num_stacks_to_drop=2,
        session: httpx.AsyncClient = None,
    ):
        await account_routes.update_oauth_account_config(
            auth=self.auth,
            account_id=self.id,
            config_body=oauth_config.to_json() or self.Config.to_json(),
            data_provider_type=self.data_provider_type,
            debug_api=debug_api,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
            parent_class=self.__class__.__name__,
            session=session,
        )

        self.Config = oauth_config

        return self
