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

# %% auto 0
__all__ = ['Breadcrumb', 'UrlSrcSet', 'Category', 'User', 'Image', 'QuestionStatusEnum', 'Attribute', 'Question', 'Discussion',
           'VanillaForums']

# %% ../../nbs/vanilla/classes.ipynb 7
@dataclass
class Breadcrumb:
    name: str
    url: str

    @classmethod
    def _from_json(cls, json_obj):

        return cls(name=json_obj["name"], url=json_obj["url"])


@dataclass
class UrlSrcSet:

    urls: Dict[str, str]

    @classmethod
    def _from_json(cls, data):

        return cls(urls=data)


@dataclass
class Category:
    base_url: str

    category_id: int
    name: str

    description: str

    parent_category_id: int

    # custom_permissions: bool

    # is_archived: bool

    # urlcode: str
    url: str

    display_as: str

    # icon_url: str

    date_inserted: datetime

    # banner_url: str

    # banner_url_src_set: UrlSrcSet

    count_categories: int
    count_discussions: int
    count_comments: int
    count_all_discussions: int
    count_all_comments: int

    count_followers: int

    # followed: bool

    # featured: bool

    allowed_discussion_types: List[str]

    sort: int = None

    depth: int = None

    # icon_url_src_set: UrlSrcSet

    breadcrumbs: List[Breadcrumb] = None

    @classmethod
    def _from_json(cls, json_obj, base_url):

        category = cls(
            base_url=base_url,
            category_id=json_obj["categoryID"],
            name=json_obj["name"],
            description=json_obj["description"],
            parent_category_id=json_obj["parentCategoryID"],
            url=json_obj["url"],
            display_as=json_obj["displayAs"],
            date_inserted=deuc.convert_str_to_date(json_obj["dateInserted"]),
            # urlcode=json_obj['urlcode'],
            # banner_url=json_obj['bannerUrl'],
            # banner_url_src_set=UrlSrcSet._from_json(json_obj['bannerUrlSrcSet']),
            count_categories=json_obj["countCategories"],
            count_discussions=json_obj["countDiscussions"],
            count_comments=json_obj["countComments"],
            count_all_discussions=json_obj["countAllDiscussions"],
            count_all_comments=json_obj["countAllComments"],
            count_followers=json_obj["countFollowers"],
            allowed_discussion_types=json_obj["allowedDiscussionTypes"],
            depth=json_obj.get("depth"),
            sort=json_obj.get("sort"),
        )

        category.breadcrumbs = [
            Breadcrumb._from_json(breadcrumb) for breadcrumb in json_obj["breadcrumbs"]
        ]

        return category

    @classmethod
    def get_by_id(cls, base_url, category_id, return_raw: bool = False):

        url = f"https://{base_url}/api/v2/categories/{category_id}"

        res = requests.get(url)

        if res.status_code != 200:

            raise Exception(f"unable to retrieve category {category_id}")

        if return_raw:
            return res

        json_obj = res.json()

        return Category._from_json(json_obj, base_url=base_url)

# %% ../../nbs/vanilla/classes.ipynb 9
@dataclass
class User:
    user_id: int
    name: str
    url: str
    photo_url: str
    date_last_active: str
    banned: int
    punished: int
    private: bool
    label: str

    @classmethod
    def _from_json(cls, json_obj):
        return cls(
            user_id=json_obj["userID"],
            name=json_obj["name"],
            url=json_obj["url"],
            photo_url=json_obj["photoUrl"],
            date_last_active=deuc.convert_str_to_date(json_obj["dateLastActive"]),
            banned=json_obj["banned"],
            punished=json_obj["punished"],
            private=json_obj["private"],
            label=json_obj["label"],
        )

# %% ../../nbs/vanilla/classes.ipynb 11
@dataclass
class Image:
    url: str
    urlSrcSet: Dict[str, str]
    alt: str


class QuestionStatusEnum(Enum):
    ANSWERED = auto()
    UNANSWERED = auto()


@dataclass
class Attribute:
    pass


@dataclass
class Question(Attribute):
    status: QuestionStatusEnum = None
    date_accepted: Optional[datetime] = None
    date_answered: datetime = None
    accepted_answers: List[str] = None

    @classmethod
    def _from_json(cls, json_obj):
        """
        Create a Question object from a JSON object.

        Args:
            json_obj (dict): The JSON object.

        Returns:
            Question: The created Question object.
        """
        status = (
            QuestionStatusEnum[json_obj["status"].upper()]
            if json_obj["status"].upper() in QuestionStatusEnum.__members__
            else None
        )
        date_accepted = deuc.convert_str_to_date(json_obj.get("dateAccepted"))

        date_answered = deuc.convert_str_to_date(json_obj.get("dateAnswered"))
        return cls(
            status=status,
            date_accepted=date_accepted,
            date_answered=date_answered,
            accepted_answers=json_obj.get("acceptedAnswers"),
        )

# %% ../../nbs/vanilla/classes.ipynb 13
@dataclass
class Discussion:
    base_url: str
    discussion_id: int
    type: str
    name: str
    body: str
    category_id: int
    date_inserted: datetime
    date_updated: Optional[datetime]
    date_last_comment: str
    insert_user_id: int
    insert_user: User
    closed: bool
    url: str
    canonical_url: str
    status_id: int
    score: Optional[int]

    # count_comments: int
    # count_views: int

    category: Optional[Category] = None
    body_clean: Optional[str] = None
    attributes: Optional[List[Question]] = field(default_factory=dict)

    def _attributes_from_json(self, attributes_dict: dict) -> Attribute:
        """
        Convert a list of attribute dictionaries to a list of Question objects.
        """
        if "question" in attributes_dict:
            self.attributes.update(
                {"question": Question._from_json(attributes_dict["question"])}
            )

        return self.attributes

    @classmethod
    def _from_json(cls, json_obj, base_url):
        discussion = cls(
            base_url=base_url,
            discussion_id=json_obj["discussionID"],
            type=json_obj["type"],
            name=json_obj["name"],
            body=json_obj["body"],
            category_id=json_obj["categoryID"],
            date_inserted=deuc.convert_str_to_date(json_obj.get("dateInserted")),
            date_updated=deuc.convert_str_to_date(json_obj.get("dateUpdated")),
            date_last_comment=deuc.convert_str_to_date(json_obj.get("dateLastComment")),
            insert_user_id=json_obj["insertUserID"],
            insert_user=User._from_json(json_obj["insertUser"]),
            closed=json_obj["closed"],
            # count_comments=json_obj["countComments"],
            # count_views=json_obj["countViews"],
            score=json_obj["score"],
            url=json_obj["url"],
            canonical_url=json_obj["canonicalUrl"],
            status_id=json_obj["statusID"],
        )

        discussion.body_clean = dewb.convert_remove_html_tags(discussion.body)

        if "attributes" in json_obj:
            discussion._attributes_from_json(json_obj["attributes"])

        if "categoryID" in json_obj:
            discussion.category = Category.get_by_id(
                base_url=base_url, category_id=json_obj["categoryID"]
            )

        return discussion

    def to_dict(self) -> dict:
        """
        Convert a Discussion object to a dictionary.

        Returns:
            dict: The dictionary representation of the Discussion object.
        """
        s = {
            "discussion_id": self.discussion_id,
            "discussion_type": self.type,
            "discussion_title": self.name,
            "discussion_body": self.body_clean,
            "category_id": self.category_id,
            "date_inserted": deuc.convert_datetime_to_str(self.date_inserted),
            "date_updated": deuc.convert_datetime_to_str(self.date_updated),
            "date_last_comment": deuc.convert_datetime_to_str(self.date_last_comment),
            "insert_user_id": self.insert_user_id,
            "closed": self.closed,
            # "count_comments": self.count_comments,
            # "count_views": self.count_views,
            "score": self.score,
            "url": self.url,
            "canonical_url": self.canonical_url,
            "status_id": self.status_id,
        }

        if self.category:
            s.update(
                {
                    "category_name": self.category.name,
                    "category_description": self.category.description,
                }
            )

        if self.insert_user:
            s.update(
                {
                    "insert_user_name": self.insert_user.name,
                    "insert_user_profile": self.insert_user.url,
                }
            )

        return deuc.sort_dictionary(s)

# %% ../../nbs/vanilla/classes.ipynb 15
@dataclass
class VanillaForums:
    base_url: str

    discussions: List[Discussion] = None

    def get_all_categories(self, page=1, return_raw: bool = False):
        url = f"https://{self.base_url}/api/v2/categories"
        params = {"page": page}

        res = requests.get(url, params=params)

        if res.status_code != 200:
            raise Exception("unable to retrieve categories")

        if return_raw:
            return res

        categories = res.json()
        self.categories = [
            Category._from_json(category, base_url=self.base_url)
            for category in categories
        ]
        return self.categories

    def get_all_discussions(
        self,
        return_raw: bool = False,
        page: int = 1,
        is_only_unanswered: bool = False,
    ):

        params = {"sort": "-dateInserted", "page": page}

        if is_only_unanswered:
            params.update({"status": "unanswered"})

        url = f"https://{self.base_url}/api/v2/discussions"

        res = requests.get(url, params=params)

        if return_raw:
            return res

        if not res.status_code == 200:
            raise Exception("unable to retrieve discussions")

        discussions = res.json()

        self.discussions = [
            Discussion._from_json(discussion, base_url=self.base_url)
            for discussion in discussions
        ]
        return self.discussions

    def generate_discussion_report(self):
        if not self.discussions:
            self.get_all_discussions()

        return pd.DataFrame([discussion.to_dict() for discussion in self.discussions])
