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

# %% auto 0
__all__ = ['DAC_NoTargetInstance', 'DAC_NoPassword', 'DAC_NoUserName', 'DAC_NoAccessToken', 'DAC_ValidAuth',
           'DomoAccount_Credential']

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

import domolibrary.client.DomoError as dmde
import domolibrary.client.DomoAuth as dmda


import domolibrary.classes.DomoAccount_Default as dmacb
import domolibrary.classes.DomoAccessToken as dmact
import domolibrary.classes.DomoUser as dmdu
import domolibrary.utils.convert as dmcv

from nbdev.showdoc import patch_to

# %% ../../nbs/classes/50_DomoAccount_Credential.ipynb 4
class DAC_NoTargetInstance(dmde.ClassError):
    def __init__(self, cls_instance):
        super().__init__(
            message=f"no target_instance on class - {cls_instance.name}",
            cls_instance=cls_instance,
        )


class DAC_NoPassword(dmde.ClassError):
    def __init__(self, cls_instance):
        super().__init__(
            message=f"no password stored in account - {cls_instance.name}",
            cls_instance=cls_instance,
        )


class DAC_NoUserName(dmde.ClassError):
    def __init__(self, cls_instance):
        super().__init__(
            message=f"no username stored in account - {cls_instance.name}",
            cls_instance=cls_instance,
        )


class DAC_NoAccessToken(dmde.ClassError):
    def __init__(self, cls_instance):
        super().__init__(
            message=f"no access_token stored in account - {cls_instance.name}",
            cls_instance=cls_instance,
        )



class DAC_ValidAuth(dmde.ClassError):
    def __init__(self, cls_instance, message = None):
        super().__init__(
            message=message or f"{cls_instance.name} no valid auth retrieved for domo_instance - {cls_instance.target_instance}",
            cls_instance= cls_instance
        )


# %% ../../nbs/classes/50_DomoAccount_Credential.ipynb 5
@dataclass
class DomoAccount_Credential(dmacb.DomoAccount_Default):

    target_instance: str = None

    is_valid_full_auth: bool = None
    is_valid_token_auth: bool = None

    _token_auth: dmda.DomoAuth = field(repr=False, default=None)
    _full_auth: dmda.DomoAuth = field(repr=False, default=None)

    target_auth: dmda.DomoAuth = field(default=None)
    target_user : dmdu.DomoUser = field(default = None)

    # def __post_init__(self):
    #     if not self.target_instance:
    #         raise DAC_NoTargetInstance(self)
    
    
    @classmethod
    def _class_from_json(
        cls,
        obj: dict,
        is_admin_summary: bool = True,
        auth: dmda.DomoAuth = None,
        **kwargs
    ):
        return cls._default_from_json(
            obj=obj, is_admin_summary=is_admin_summary, auth=auth,
            target_instance = kwargs.get('target_instance')
        )
    

    def set_password(self, password: str):
        self.config.password = password
        return True

    def set_username(self, username: str):
        self.config.username = username
        return True

    def set_access_token(self, access_token: str):
        self.config.domo_access_token = access_token
        return True

    async def test_full_auth(self, debug_api: bool = False):
        self.is_valid_full_auth = False

        if not self.config.username:
            raise DAC_NoUserName(self)

        if not self.config.password:
            raise DAC_NoPassword(self)
        
        if not self.target_instance:
            raise DAC_NoTargetInstance(self)

        self._full_auth = dmda.DomoFullAuth(
            domo_instance=self.target_instance,
            domo_username=self.config.username,
            domo_password=self.config.password,
        )

        try:
            await self._full_auth.print_is_token(debug_api = debug_api)
            await self._full_auth.who_am_i()
            self.is_valid_full_auth = True

            self.target_auth = self._full_auth

        except dmda.AuthError as e:
            dmcv.print_md(f"🤯 test_full_auth for: ***{self.name}*** returned {e}")

            self.is_valid_full_auth = False
        return self.is_valid_full_auth

    async def test_token_auth(self, debug_api: bool = False, ):
        self.is_valid_token_auth = False

        if not self.config.domo_access_token:
            raise DAC_NoAccessToken(self)
    
        if not self.target_instance:
            raise DAC_NoTargetInstance(self)

        self._token_auth = dmda.DomoTokenAuth(
            domo_instance=self.target_instance,
            domo_access_token=self.config.domo_access_token,
        )

        try:
            await self._token_auth.print_is_token(debug_api=debug_api)
            self.is_valid_token_auth = True
            self.target_auth = self._token_auth

        except dmda.AuthError as e:
            dmcv.print_md(f"🤯 test_token_auth for: ***{self.name}*** returned {e}")
            self.is_valid_token_auth = False

        return self.is_valid_token_auth



    def _generate_target_auth(self, backup_auth: dmda.DomoAuth = None):
        target_auth = None

        if self.is_valid_token_auth:
            target_auth = self._token_auth

        if self.is_valid_full_auth:
            target_auth = self._full_auth

        if not target_auth and backup_auth and backup_auth.is_valid_token:
            target_auth = backup_auth

        if not target_auth:
            raise DAC_ValidAuth(self)

        self.target_auth = target_auth

        return self.target_auth
    
    async def test_auths(self, backup_auth: dmda.DomoAuth = None, debug_api: bool = False):
        ## test token auth
        try:
            await self.test_token_auth(debug_api = debug_api)
        
        except dmde.DomoError as e:
            print(f"testing - {self.name}: error generating token_auth: {e}")

        ## test full auth
        try:
            await self.test_full_auth(debug_api = debug_api)

        except dmde.DomoError as e:
            print(f"testing - {self.name}: error generating full_auth: {e}")
        
        ## regenertae target_auth
        try:
            self._generate_target_auth(backup_auth= backup_auth)
        
        except dmde.DomoError as e:
            print(f"{self.name}: unable to generate valid target_auth: {e}")

        return self.to_json()
    
    async def get_target_user(self, 
                               backup_auth:dmda.DomoAuth = None,
                              debug_api: bool = False,
                              session : httpx.AsyncClient =None
                              
                               ):
        user_email = self.config.username
        
        if not user_email:
            raise DAC_NoUserName(self)
        
        if not self.target_auth:
            await self.test_auths(backup_auth=backup_auth)

        if not self.target_auth:
            raise DAC_ValidAuth(self, message="no auths on account - run test_auths")
        
        print(self.target_auth)
        
        self.target_user = await dmdu.DomoUsers.by_email(
                email_ls= [user_email],
                auth = self.target_auth,
                debug_api = debug_api,
                session = session
                )
    
        
        return self.target_user

    def to_json(self):
        return {
            "account_id": self.id,
            "alias": self.name,
            "target_instance": self.target_instance,
            "is_valid_full_auth": self.is_valid_full_auth,
            "is_valid_token_auth": self.is_valid_token_auth,
        }


# %% ../../nbs/classes/50_DomoAccount_Credential.ipynb 6
@patch_to(DomoAccount_Credential)
async def set_target_user_password(self: DomoAccount_Credential,
                                   new_password: str,
                                   debug_api : bool = False):
    
    if not self.target_auth:
        raise DAC_ValidAuth(self, message = "must set valid target_auth")
    
    if not self.target_auth.is_valid_token:
        await self.target_auth.print_is_token()
            
    target_user = await self.get_target_user(debug_api = debug_api)
    
    await target_user.reset_password(new_password, debug_api = debug_api)
    
    self.set_password(new_password)

    await self.update_config(debug_api = debug_api)
    
    return await self.test_full_auth()


@patch_to(DomoAccount_Credential)
async def reset_access_token(self, token_name = None, duration_in_days = 90, debug_api : bool = False):
    
    if not self.target_auth:
        raise DAC_ValidAuth(self, message = "must set valid target_auth")
    
    if not self.target_auth.is_valid_token:
        await self.target_auth.print_is_token()
        
        
    target_user = await self.get_target_user(debug_api = debug_api)

    if not token_name:
        token_name = target_user.email_address


    domo_access_tokens = await target_user.get_access_tokens()
    
    domo_access_token = next((dat for dat in domo_access_tokens if dat.name == token_name), None)
    
    if not domo_access_token:
        domo_access_token = await dmact.DomoAccessToken.generate(
            duration_in_days = duration_in_days,
            token_name = token_name,
            auth = self.target_auth,
            owner = target_user,
            debug_api = debug_api)
    
    else:
        await domo_access_token.regenerate(duration_in_days = duration_in_days)
           
    self.set_access_token(domo_access_token.token)
    await self.update_config(debug_api = debug_api)
    
    return await self.test_token_auth()
