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

# %% ../../nbs/classes/50_DomoPublish.ipynb 2
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Optional, List, Any
from enum import Enum

import datetime as dt
import pandas as pd
import asyncio
import httpx

import uuid

from nbdev.showdoc import patch_to

import domolibrary.utils.DictDot as util_dd
import domolibrary.client.DomoAuth as dmda
import domolibrary.routes.publish as publish_routes

import domolibrary.classes.DomoLineage as dmdl

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


# %% auto 0
__all__ = ['DomoPublication_Subscription', 'DomoPublication_Content_Enum', 'DomoPublication_Content',
           'DomoPublication_UnexpectedContentType', 'DomoPublication', 'DomoPublications']

# %% ../../nbs/classes/50_DomoPublish.ipynb 6
@dataclass
class DomoPublication_Subscription:
    """the subscriber represents a location a publication is sent to"""

    auth: dmda.DomoAuth = field(repr=False)
    subscription_id: str
    publication_id: str
    domain: str
    created_dt: Optional[dt.datetime] = (None,)

    parent : Any = field(repr = False, default = None)

    @classmethod
    def _from_json(cls, obj, auth: dmda.DomoAuth, parent : Any= None):

        return cls(
            auth=auth,
            subscription_id=obj.get("id") or obj.get("subscriptionId"),
            publication_id=obj["publicationId"],
            domain=obj.get("domain") or obj.get("publisherDomain"),
            created_dt=(
                (dt.datetime.fromtimestamp(obj.get("created") / 1000))
                if obj.get("created")
                else None
            ),
            parent = parent
        )

    async def get_content_details(
        self,
        debug_api: bool = False,
        debug_num_stacks_to_drop=2,
        session: httpx.AsyncClient = None,
    ):
        
        publication_content = self.parent.content

        res = await publish_routes.get_subscriber_content_details(
            auth=self.auth,
            publication_id=self.publication_id,
            subscriber_instance=self.domain,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
            debug_api=debug_api,
            session = session,
            parent_class=self.__class__.__name__,
        )

        for content in publication_content:
            subscriber_obj = next(
                (
                    subscriber_obj
                    for subscriber_obj in res.response
                    if subscriber_obj["publisherObjectId"] == content.entity_id
                    and subscriber_obj["contentType"] == content.entity_type
                ),
                None,
            )
            if subscriber_obj is not None:
                content.subscriber_content_id = subscriber_obj["subscriberObjectId"]
                content.subscriber_insance = subscriber_obj["subscriberDomain"]

        self.content = publication_content

        return self.content

# %% ../../nbs/classes/50_DomoPublish.ipynb 9
class DomoPublication_Content_Enum(Enum):
    import domolibrary.classes.DomoDataset as dmdc
    import domolibrary.classes.DomoCard as dmac
    import domolibrary.classes.DomoPage as dmpg
    import domolibrary.classes.DomoAppStudio as dmas

    CARD = dmac.DomoCard
    DATASET = dmdc.DomoDataset
    DATA_APP = dmas.DomoAppStudio
    PAGE = dmpg.DomoPage


# %% ../../nbs/classes/50_DomoPublish.ipynb 11
@dataclass
class DomoPublication_Content:
    auth : dmda.DomoAuth

    content_id: str
    entity_type: str
    entity_id: str
    entity_domain: str
    is_v2: bool
    is_direct_content: bool

    created_dt: dt.datetime
    updated_dt: dt.datetime = None

    subscriber_content_id: str = None
    subscriber_insance: str = None

    entity: Any = field(repr=False, default=None)
    parent: Any = field(repr=False, default=None)

    """the publication content is the content from the publisher instance that is being distributed to subscribers"""

    @classmethod
    def _from_json(cls, obj: dict, auth : dmda.DomoAuth, parent: Any = None):

        entity_type = obj.get("content").get("type")
        return cls(
            auth = auth,
            content_id=obj["id"],
            entity_id=obj.get("content").get("domoObjectId"),
            entity_domain=obj.get("content").get("domain"),
            is_v2=obj.get("isV2"),
            created_dt=(
                dt.datetime.fromtimestamp(obj["created"] / 1000)
                if obj["created"]
                else None
            ),
            updated_dt=(
                dt.datetime.fromtimestamp(obj.get("content").get("updated") / 1000)
                if obj.get("content").get("updated")
                else None
            ),
            is_direct_content=obj.get("useDirectContent"),
            parent=parent,
            entity_type=entity_type,
            entity=DomoPublication_Content_Enum[entity_type].value,
        )

    async def _get_entity_lineage(self, debug_api: bool = False, session: httpx.AsyncClient = None):
        if self.entity:
            self.entity = await self.entity._get_by_id(
                auth=self.auth, id=self.entity_id, debug_api=debug_api, session=session
            )

            return hasattr(self.entity, "Lineage") and await self.entity.Lineage.get()
        
        return self.entity

    def to_api_json(self):
        return {
            "domain": self.entity_domain,
            "domoObjectId": self.entity_id,
            "customerId": self.entity_domain,
            "type": self.entity_type,
        }

# %% ../../nbs/classes/50_DomoPublish.ipynb 13
class DomoPublication_UnexpectedContentType(dmde.ClassError):
    def __init__(self, cls_instance, content_type):
        super().__init__(
            cls_instance=cls_instance,
            message=f"DomoPublication_Instantiation: Unexpected content type {content_type}",
        )


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

    id: str
    name: str
    description: str
    is_v2: bool
    created_dt: dt.datetime

    updated_dt: dt.datetime = None

    subscription_authorizations: List[DomoPublication_Subscription] = None

    content: List[DomoPublication_Content] = None

    # content_page_id_ls: List[str] = default = None
    # content_dataset_id_ls: List[str] = field(default_factory=list)
    # content_data_app_id_ls: List[str] = field(default_factory=list)

    Lineage: dmdl.DomoLineage_Publication = None

    def __post_init__(self):
        self.Lineage = dmdl.DomoLineage_Publication._for_publication(parent=self, auth=self.auth)

    def _generate_subscription_authorizations(
        self, subscription_authorizations_ls, auth
    ):
        self.subscription_authorizations = [
            DomoPublication_Subscription._from_json(obj=sub, auth=auth, parent=self)
            for sub in subscription_authorizations_ls
        ]

    def _generate_content(self, children_ls):

        self.content = [
            DomoPublication_Content._from_json(child, auth=self.auth, parent=self)
            for child in children_ls
        ]

        # if dmpc.entity_type == "PAGE":
        #     domo_pub.content_page_id_ls.append(dmpc.entity_id)

        # elif dmpc.entity_type == "DATASET":
        #     domo_pub.content_dataset_id_ls.append(dmpc.entity_id)

        # elif dmpc.entity_type == "DATA_APP":
        #     domo_pub.content_data_app_id_ls.append(dmpc.entity_id)

        # else:
        #     raise DomoPublication_UnexpectedContentType(
        #         cls_instance=domo_pub,
        #         content_type=dmpc.entity_type,
        #     )

        return self.content

    @classmethod
    def _from_json(cls, obj, auth: dmda.DomoAuth):

        domo_pub = cls(
            id=obj["id"],
            name=obj["name"],
            description=obj["description"],
            created_dt=(
                dt.datetime.fromtimestamp(obj["created"] / 1000)
                if obj["created"]
                else None
            ),
            updated_dt=(
                dt.datetime.fromtimestamp(obj.get("content").get("updated") / 1000)
                if obj.get("content").get("updated")
                else None
            ),
            is_v2=obj["isV2"],
            auth=auth,
        )

        if (
            obj.get("subscriptionAuthorizations")
            and len(obj.get("subscriptionAuthorizations")) > 0
        ):
            domo_pub._generate_subscription_authorizations(
                subscription_authorizations_ls=obj["subscriptionAuthorizations"],
                auth=auth,
            )

        if obj.get("children") and len(obj.get("children")) > 0:
            domo_pub._generate_content(obj["children"])

        return domo_pub

# %% ../../nbs/classes/50_DomoPublish.ipynb 14
@patch_to(DomoPublication, cls_method=True)
async def get_by_id(
    cls,
    publication_id,
    auth: dmda.DomoAuth = None,
    return_raw: bool = False,
    timeout=10,
    debug_api: bool = False,
    debug_num_stacks_to_drop=2,
    session: httpx.AsyncClient = None,
):
    res = await publish_routes.get_publication_by_id(
        auth=auth,
        publication_id=publication_id,
        timeout=timeout,
        debug_api=debug_api,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        session=session,
        parent_class=cls.__name__,
    )

    if return_raw:
        return res

    return cls._from_json(obj=res.response, auth=auth)

# | export
@patch_to(DomoPublication)
async def get_content(
    self,
    return_raw: bool = False,
    timeout=10,
    debug_api: bool = False,
    debug_num_stacks_to_drop=2,
    session: httpx.AsyncClient = None,
):
    res = await publish_routes.get_publication_by_id(
        auth=auth,
        publication_id=self.id,
        timeout=timeout,
        debug_api=debug_api,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop,
        session=session,
        parent_class=self.__class__.__name__,
    )

    content = res.response.get('children')

    if return_raw:
        res.response = content
        return res
    

    if not content or len(content) == 0:
        return content
    
    return self._generate_content(content)


# %% ../../nbs/classes/50_DomoPublish.ipynb 22
@dataclass
class DomoPublications:
    auth: dmda.DomoAuth = field(repr = False)

    publications: List[DomoPublication] = field(default = None)

    subscriptions: List[DomoPublication_Subscription] = field(default = None)

    async def get(
        self,
        search_term: str = None,
        debug_api: bool = False,
        session: httpx.AsyncClient = None,
        return_raw: bool = False,
        debug_num_stacks_to_drop=2,
    ):

        res = await publish_routes.search_publications(
            auth=self.auth,
            debug_api=debug_api,
            session=session,
            search_term= search_term,
            debug_num_stacks_to_drop=debug_num_stacks_to_drop,
            parent_class=self.__class__.__name__,
        )

        if return_raw:
            return res

        self.publications = await dmce.gather_with_concurrency(
            n=60,
            *[
                DomoPublication.get_by_id(
                    publication_id=obj.get("id"), auth=self.auth
                )
                for obj in res.response
            ],
        )
        return self.publications

    async def get_subscribers(
        self,
        session: httpx.AsyncClient = None,
        return_raw: bool = False,
        debug_api: bool = False,
    ):
        """get instances subscription summaries"""

        res = await publish_routes.get_subscription_summaries(
            auth=self.auth, session=session, debug_api=debug_api
        )

        if return_raw:
            return res

        self.subscriptions = [
            DomoPublication_Subscription._from_json(sub, auth=self.auth)
            for sub in res.response
        ]

        return self.subscriptions

# %% ../../nbs/classes/50_DomoPublish.ipynb 26
@patch_to(DomoPublications)
async def search_publications(
    self: DomoPublications,
    search_term: str = None,
    session: httpx.AsyncClient = None,
    debug_api: bool = False,
    return_raw: bool = False,
    debug_num_stacks_to_drop = 2
):
    
    res = await self.get(
        search_term=search_term,
        session=session,
        debug_api=debug_api,
        return_raw = return_raw,
        debug_num_stacks_to_drop=debug_num_stacks_to_drop+1
    )

    return res

# %% ../../nbs/classes/50_DomoPublish.ipynb 28
@patch_to(DomoPublication)
async def report_content_as_dataframe(self, return_raw: bool = False):

    if return_raw:
        return await self.get_content()

    return pd.DataFrame(
        [
            {
                "plubication_id": self.id,
                "publication_name": self.name,
                "is_v2": self.is_v2,
                "publish_created_dt": self.created_dt,
                "entity_type": content.entity_type,
                "entity_id": content.entity_id,
                "entity_updated" : content.updated_dt
            }
            for content in self.content
        ]
    )


@patch_to(DomoPublication)
def report_lineage_as_dataframe(self, return_raw: bool = False):

    flat_lineage_ls = self.Lineage._flatten_lineage()

    output_ls = [
        {
            "plubication_id": self.id,
            "publication_name": self.name,
            "is_v2": self.is_v2,
            "publish_created_dt": self.created_dt,
            # "entity_type": row.get("entity_type"),
            "entity_id": row.get("entity_id"),
        }
        for row in flat_lineage_ls
    ]

    if return_raw:
        return output_ls

    return pd.DataFrame(output_ls)

# %% ../../nbs/classes/50_DomoPublish.ipynb 30
@patch_to(DomoPublication, cls_method=True)
async def create_publication(
    cls,
    name: str,
    content_ls: List[DomoPublication_Content],
    subscription_ls: List[DomoPublication_Subscription],
    unique_id: str = None,
    description: str = None,
    auth: dmda.DomoAuth = None,
    debug_api: bool = False,
):

    if not isinstance(subscription_ls, list):
        subscription_ls = [subscription_ls]

    auth = auth or cls.auth
    domain_ls = []
    content_json_ls = []
    for sub in subscription_ls:
        domain_ls.append(sub.domain)
    for content_item in content_ls:
        content_json_ls.append(content_item.to_api_json())

    if not unique_id:
        unique_id = str(uuid.uuid4())
    if not description:
        description = ""

    body = publish_routes.generate_publish_body(
        url=f"{auth.domo_instance}.domo.com",
        sub_domain_ls=domain_ls,
        content_ls=content_json_ls,
        name=name,
        unique_id=unique_id,
        description=description,
        is_new=True,
    )

    res = await publish_routes.create_publish_job(auth=auth, body=body)
    if debug_api:
        print("Create the new Publish job")
    if res.status != 200:
        print(res)
        await asyncio.sleep(2)
        res = await publish_routes.get_publication_by_id(
            auth=auth, publication_id=unique_id
        )
        if res.status != 200:
            return None
        else:
            return cls._from_json(obj=res.response, auth=auth)

    return cls._from_json(obj=res.response, auth=auth)

# %% ../../nbs/classes/50_DomoPublish.ipynb 32
@patch_to(DomoPublication)
async def update_publication(
    self,
    name: str,
    content_ls: List[DomoPublication_Content],
    subscription_ls: List[DomoPublication_Subscription],
    description: str = "",
    debug_api: bool = False,
):

    if not isinstance(subscription_ls, list):
        subscription_ls = [subscription_ls]

    domain_ls = [sub.domain for sub in subscription_ls]
    content_json_ls = [content_item.to_api_json() for content_item in content_ls]
        
    body = publish_routes.generate_publish_body(
        url=f"{self.auth.domo_instance}.domo.com",
        sub_domain_ls=domain_ls,
        content_ls=content_json_ls,
        name=name,
        unique_id=self.id,
        description=description,
        is_new=False,
    )

    res = await publish_routes.udpate_publish_job(
        auth=auth, publication_id=self.id, body=body
    )

    return res

# %% ../../nbs/classes/50_DomoPublish.ipynb 34
@patch_to(DomoPublication, cls_method=True)
async def get_subscription_invites_list(
    cls, auth: dmda.DomoAuth, debug_api: bool = False
):

    res = await publish_routes.get_subscription_invititations(
        auth=auth, debug_api=debug_api
    )
    if debug_api:
        print("Getting Publish subscription invites")

    if res.status == 200:
        return res.response
    else:
        return None


@patch_to(DomoPublication, cls_method=True)
async def accept_invite_by_id(
    cls, auth: dmda.DomoAuth, subscription_id: str, debug_api: bool = False
):

    res = await publish_routes.accept_invite_by_id(
        auth=auth, subscription_id=subscription_id, debug_api=debug_api
    )

    if res.status == 200:
        return res.response
    else:
        return None
