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

# %% auto 0
__all__ = ['DomoGroup', 'DomoGroups']

# %% ../../nbs/classes/50_DomoGroup.ipynb 2
from domolibrary.routes.group import (
    SearchGroups_Error,
    Group_CRUD_Error,
    GroupType_Enum,
)

from ..routes.user import SearchUser_NoResults

# %% ../../nbs/classes/50_DomoGroup.ipynb 3
from dataclasses import dataclass, field
from typing import List

import httpx
import asyncio
from nbdev.showdoc import patch_to

import datetime as dt

import domolibrary.utils.chunk_execution as dmce

import domolibrary.client.DomoAuth as dmda
import domolibrary.utils.DictDot as util_dd

import domolibrary.routes.group as group_routes

import domolibrary.classes.DomoGroup_Membership as dmgm
import domolibrary.classes.DomoUser as dmu


# %% ../../nbs/classes/50_DomoGroup.ipynb 7
@dataclass
class DomoGroup:
    auth: dmda.DomoAuth = field(repr=False, default=None)
    id: str = None
    name: str = None
    type: str = None
    description: str = None
    members_id_ls: list[str] = field(repr=False, default_factory=list)
    owner_id_ls: list[str] = field(repr=False, default_factory=list)

    members_ls: list[dict] = field(repr=False, default_factory=list)
    owner_ls: list[dict] = field(repr=False, default_factory=list)

    custom_attributes: dict = field(default_factory=dict)

    def __post_init__(self):
        # self.domo_instance = self.domo_instance or auth.domo_instance
        self.Membership = dmgm.GroupMembership(self)

    @classmethod
    def _from_group_json(cls, auth: dmda.DomoAuth, json_obj):
        dd = json_obj

        if not isinstance(json_obj, util_dd.DictDot):
            dd = util_dd.DictDot(json_obj)

        return cls(
            auth=auth,
            id=dd.id or dd.groupId,
            name=dd.name,
            description=dd.description,
            type=dd.type or dd.groupType,
            members_id_ls=dd.userIds,
            owner_ls=dd.owners,
        )

    @classmethod
    def _from_grouplist_json(cls, auth: dmda.DomoAuth, json_obj):
        dd = json_obj

        if not isinstance(json_obj, util_dd.DictDot):
            dd = util_dd.DictDot(json_obj)

        return cls(
            auth=auth,
            id=dd.groupId,
            name=dd.name,
            description=dd.description,
            type=dd.groupType,
            owner_ls=dd.owners,
            owner_id_ls=[owner.id for owner in dd.owners],
            members_ls=dd.groupMembers,
            members_id_ls=[member.id for member in dd.members],
        )

    @staticmethod
    def _groups_to_domo_group(json_list, auth: dmda.DomoAuth) -> List[dict]:
        domo_groups = [
            DomoGroup._from_group_json(auth=auth, json_obj=json_obj)
            for json_obj in json_list
        ]

        return domo_groups

# %% ../../nbs/classes/50_DomoGroup.ipynb 9
@patch_to(DomoGroup, cls_method=True)
async def get_by_id(
    cls,
    auth: dmda.DomoAuth,
    group_id: str,
    return_raw: bool = False,
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
    debug_num_stacks_to_drop: int = 2,
):
    res = await group_routes.get_group_by_id(
        auth=auth,
        group_id=group_id,
        debug_api=debug_api,
        session=session,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=cls.__name__,
    )
    if return_raw:
        return res

    dg = cls._from_group_json(auth=auth, json_obj=res.response)

    # await dg.Membership.get_owners()
    # await dg.Membership.get_members() # disabled because causes recursion
    return dg

# %% ../../nbs/classes/50_DomoGroup.ipynb 12
@patch_to(DomoGroup, cls_method=True)
async def search_by_name(
    cls,
    auth: dmda.DomoAuth,
    group_name: str,
    is_exact_match: bool = True,
    return_raw: bool = False,
    debug_api: bool = False,
    debug_prn: bool = False,
    session: httpx.AsyncClient = None,
):
    res = await group_routes.search_groups_by_name(
        auth=auth,
        search_name=group_name,
        debug_api=debug_api,
        is_exact_match=is_exact_match,
        session=session,
    )

    if return_raw:
        return res

    if isinstance(res.response, list):
        return cls._groups_to_domo_group(res.response, auth)

    return cls._from_group_json(auth=auth, json_obj=res.response)

# %% ../../nbs/classes/50_DomoGroup.ipynb 33
class DomoGroups:
    def __init__(self):
        pass

    @staticmethod
    def _groups_to_domo_group(json_list, auth: dmda.DomoAuth):
        return [
            DomoGroup._from_group_json(auth=auth, json_obj=json_obj)
            for json_obj in json_list
        ]

# %% ../../nbs/classes/50_DomoGroup.ipynb 35
@patch_to(DomoGroups, cls_method=True)
async def get_all_groups(
    cls: DomoGroups,
    auth: dmda.DomoAuth,
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
):
    res = await group_routes.get_all_groups(
        auth=auth, debug_api=debug_api, session=session
    )

    if len(res.response) > 0:
        json_list = res.response

        return cls._groups_to_domo_group(json_list=json_list, auth=auth)

    else:
        return []

# %% ../../nbs/classes/50_DomoGroup.ipynb 39
@patch_to(DomoGroups, cls_method=True)
async def toggle_system_group_visibility(
    cls: DomoGroups,
    auth: dmda.DomoAuth,
    is_hide_system_groups: bool,
    debug_api: bool = False,
):
    return await group_routes.toggle_system_group_visibility(
        auth=auth, is_hide_system_groups=is_hide_system_groups, debug_api=debug_api
    )

# %% ../../nbs/classes/50_DomoGroup.ipynb 42
@patch_to(DomoGroups, cls_method = True)
async def by_name(
    cls,
    auth:dmda.DomoAuth,
    group_names: List[str],
    is_search_system_accounts : bool = True
) -> List[DomoGroup]:
    
    if is_search_system_accounts:
        await DomoGroups.toggle_system_group_visibility(
            is_hide_system_groups=False, auth=auth
        )

    await asyncio.sleep(2)

    domo_groups = await dmce.gather_with_concurrency(
        *[
            DomoGroup.search_by_name(group_name=group_name, auth=auth)
            for group_name in group_names
        ],
        n=10
    )
    
    if is_search_system_accounts:
        await DomoGroups.toggle_system_group_visibility(
            is_hide_system_groups=True, auth=auth
        )

    return domo_groups

# %% ../../nbs/classes/50_DomoGroup.ipynb 45
@patch_to(DomoGroup, cls_method=True)
async def create_from_name(
    cls: DomoGroup,
    auth: dmda.DomoAuth,
    group_name: str = None,
    group_type: str = "open",  # use GroupType_Enum
    description: str = None,
    is_include_manage_groups_role: bool = True,
    debug_api: bool = False,
    session: httpx.AsyncClient = None,
):
    res = await group_routes.create_group(
        auth=auth,
        group_name=group_name,
        group_type=group_type,
        description=description,
        debug_api=debug_api,
        session = session,
    )

    domo_group = cls._from_group_json(auth=auth, json_obj=res.response)

    if is_include_manage_groups_role:
        await domo_group.Membership.add_owner_manage_groups_role()

    return domo_group

# %% ../../nbs/classes/50_DomoGroup.ipynb 49
@patch_to(DomoGroup)
async def update_metadata(
    self: DomoGroup,
    auth: dmda.DomoAuth = None,
    group_name: str = None,
    group_type: str = None,  # use GroupType_Enum
    description: str = None,
    additional_params: dict = None,
    debug_api: bool = False,
    return_raw: bool = False,
    session: httpx.AsyncClient = None,
):
    auth = auth or self.auth

    try:
        res = await group_routes.update_group(
            auth=auth,
            group_id=self.id,
            group_name=group_name,
            group_type=group_type,
            description=description,
            additional_params=additional_params,
            debug_api=debug_api,
            session=session,
        )

        if return_raw:
            return res

        updated_group = await DomoGroup.get_by_id(auth=auth, group_id=self.id)

        self.name = updated_group.name or self.name
        self.description = updated_group.description or self.description
        self.type = updated_group.type or self.type

    except Group_CRUD_Error as e:
        if group_type != self.type:
            raise Group_CRUD_Error(
                res = res,
                message=f"probably cannot change group_type to '{group_type}' from current type '{self.type}' consider passing `addtional_parameters`",
            ) from e

        else:
            raise e

    return self

# %% ../../nbs/classes/50_DomoGroup.ipynb 54
@patch_to(DomoGroup, cls_method=True)
async def upsert(
    cls: DomoGroup,
    auth: dmda.DomoAuth,
    group_name: str,
    group_type: str = None,  # if create_group, use routes.class.GroupType_Enum
    description: str = None,
    debug_api: bool = False,
    additional_params: dict = None,
    session: httpx.AsyncClient = None,
):
    domo_group = None

    try:
        domo_group = await DomoGroup.search_by_name(
            auth=auth, group_name=group_name, is_exact_match=True, session=session
        )

        return await domo_group.update_metadata(
            group_type=group_type, description=description, debug_api=debug_api
        )

    except group_routes.SearchGroups_Error as e:
        print(e)
        return await DomoGroup.create_from_name(
            auth=auth,
            group_name=group_name,
            group_type=group_type,
            description=description,
            debug_api=debug_api,
            session=session,
        )

    except Group_CRUD_Error as e:
        print(e)

        # try running without changing group type

        return await group_routes.update_group(
            auth=auth,
            group_id=domo_group.id,
            group_name=group_name,
            # group_type=group_type,
            description=description,
            additional_params=additional_params,
            debug_api=debug_api,
            session=session,
        )

# %% ../../nbs/classes/50_DomoGroup.ipynb 57
@patch_to(DomoGroups, cls_method= True)
async def upsert(
    cls : DomoGroups,
    auth: dmda.DomoAuth,
    group_name: str,
    description: str = f"updated via {dt.date.today()}",
    group_owner_names: List[str] = None,  # ["Role: Admin"]
    group_type: GroupType_Enum = GroupType_Enum["CLOSED"].value,
    is_search_system_accounts: bool = True,
    debug_api: bool = False,
) -> DomoGroup:

    group_owner_names = group_owner_names or ["Role: Admin"]

    domo_group = await DomoGroup.upsert(
        group_name=group_name,
        group_type=group_type,
        description=description,
        auth=auth,
        debug_api=debug_api,
    )

    domo_group_owners = await DomoGroups.by_name(
        auth=auth,
        group_names=group_owner_names,
        is_search_system_accounts=is_search_system_accounts,
    )

    await domo_group.Membership.add_owners(add_owner_ls=domo_group_owners)

    return domo_group

# %% ../../nbs/classes/50_DomoGroup.ipynb 59
@patch_to(DomoGroup)
async def delete(
    self: DomoGroup,
    debug_api: bool = False,
    debug_num_stacks_to_drop=2,
    session: httpx.AsyncClient = None,
):
    res = await group_routes.delete_groups(
        auth=self.auth,
        group_ids=[str(self.id)],
        debug_api=debug_api,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        parent_class=self.__class__.__name__,
        session=session,
    )

    res.parent_class = self.__class__.__name__

    return res
