# pylint: disable=invalid-name

from typing import BinaryIO
from requests import Session

from .constants import upload_media
from .lib.util import exceptions, objects

class ACM():
    "Module for work with ACM requests."
    def __init__(self, comId: int = None, *, profile: objects.UserProfile):
        self.session: Session = profile.session
        self.profile = profile
        self.comId = comId

    # TODO : Finish the imaging sizing, might not work for every picture...
    def create_community(self, name: str, tagline: str, icon: BinaryIO,
                themeColor: str, joinType: int = 0, primaryLanguage: str = "en"):
        """
        Creates a community with the given parameters.

        **Parameters**
            - **name** (str): The name of the community.
            - **tagline** (str): The tagline of the community.
            - **icon** (BinaryIO): The icon of the community in BinaryIO format.
            - **themeColor** (str): The theme color of the community.
            - **joinType** (int, optional): The type of joining the community. Defaults to 0.
            - **primaryLanguage** (str, optional): The primary language of the community. Defaults to "en".

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        data = {
            "icon": {
                "height": 512.0,
                "imageMatrix": [1.6875, 0.0, 108.0, 0.0, 1.6875, 497.0, 0.0, 0.0, 1.0],
                "path": upload_media(self, icon),
                "width": 512.0,
                "x": 0.0,
                "y": 0.0
            },
            "joinType": joinType,
            "name": name,
            "primaryLanguage": primaryLanguage,
            "tagline": tagline,
            "templateId": 9,
            "themeColor": themeColor
        }

        response = self.session.post(f"/g/s/community", json=data)
        return response.status_code

    def delete_community(self, email: str, password: str, verificationCode: str):
        """
        Deletes a community with the given parameters.

        **Parameters**
            - **email** (str): The email address associated with the community.
            - **password** (str): The password associated with the community.
            - **verificationCode** (str): The verification code with mail.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        data = {
            "secret": f"0 {password}",
            "validationContext": {
                "data": {
                    "code": verificationCode
                },
                "type": 1,
                "identity": email
            },
            "deviceID": self.session.headers.get("NDCDEVICEID")
        }

        response = self.session.post(f"/g/s-x{self.comId}/community/delete-request", json=data)
        return response.status_code

    def list_communities(self, start: int = 0, size: int = 25):
        """
        List of Communities the account is admin.

        **Parameters**
            - *start* : Where to start the list.
            - *size* : Size of the list.

        **Returns**
            - **Success** : :meth:`Community List <AminoLightPy.lib.util.objects.CommunityList>`

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """

        response = self.session.get(f"/g/s/community/managed?start={start}&size={size}")
        return objects.CommunityList(response.json()["communityList"]).CommunityList

    def get_categories(self, start: int = 0, size: int = 25):
        """
        Gets the categories of the blog in the community.

        **Parameters**
            - *start* : Where to start the list.
            - *size* : Size of the list.

        **Returns**
            - **Success** : :meth:`dict`

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """

        response = self.session.get(f"/x{self.comId}/s/blog-category?start={start}&size={size}")
        return response.json()

    def change_sidepanel_color(self, color: str):
        """
        Changes the color of the side panel in the community.

        **Parameters**
            - *color* : The color to be applied to the side panel.

        **Returns**
            - **Success** : :meth:`dict`

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """

        data = {
            "path": "appearance.leftSidePanel.style.iconColor",
            "value": color
        }

        response = self.session.post(f"/x{self.comId}/s/community/configuration", json=data)
        return response.json()

    def promote(self, userId: str, rank: str):
        """
        Promotes a user to a specified rank in the community.

        **Parameters**
            - *userId* : The ID of the user to be promoted.
            - *rank* : The rank to which the user is to be promoted. Can be "transfer-agent", "leader", or "curator".

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        rank = rank.lower().replace("agent", "transfer-agent")

        if rank.lower() not in ("transfer-agent", "leader", "curator"):
            raise exceptions.WrongType(rank)

        response = self.session.post(f"/x{self.comId}/s/user-profile/{userId}/{rank}")
        return response.status_code

    def get_join_requests(self, start: int = 0, size: int = 25):
        """
        Retrieves the join requests for the community.

        **Parameters**
            - *start* : Where to start the list.
            - *size* : Size of the list.

        **Returns**
            - **Success** : :meth:`Join Request <AminoLightPy.lib.util.objects.JoinRequest>`

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        data = {
            "status": "pending",
            "start": start,
            "size": size
        }

        response = self.session.get(f"/x{self.comId}/s/community/membership-request", params=data)
        return objects.JoinRequest(response.json()).JoinRequest

    def accept_join_request(self, userId: str):
        """
        Accepts a join request from a user in the community.

        **Parameters**
            - *userId* : The ID of the user whose join request is to be accepted.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        data = {}
        response = self.session.post(f"/x{self.comId}/s/community/membership-request/{userId}/accept", json=data)
        return response.status_code

    def reject_join_request(self, userId: str):
        """
        Rejects a join request from a user in the community.

        **Parameters**
            - *userId* : The ID of the user whose join request is to be rejected.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        data = {}
        response = self.session.post(f"/x{self.comId}/s/community/membership-request/{userId}/reject", json=data)
        return response.status_code

    def get_community_stats(self):
        """
        Retrieves the statistics of the community.

        **Returns**
            - **Success** : :meth:`Community Stats <AminoLightPy.lib.util.objects.CommunityStats>`

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        response = self.session.get(f"/x{self.comId}/s/community/stats")
        return objects.CommunityStats(response.json()["communityStats"]).CommunityStats

    def get_community_user_stats(self, type: str, start: int = 0, size: int = 25):
        """
        Retrieves the user statistics of the community based on the specified type.

        **Parameters**
            - *type* : The type of user statistics to be retrieved. Can be "leader" or "curator".
            - *start* : Where to start the list.
            - *size* : Size of the list.

        **Returns**
            - **Success** : :meth:`User Profile List <AminoLightPy.lib.util.objects.UserProfileList>`

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        if type.lower() not in ("leader", "curator"):
            raise exceptions.WrongType(type)

        data = {
            "type": type.lower(),
            "start": start,
            "size": size
        }

        response = self.session.get(
            url=f"/x{self.comId}/s/community/stats/moderation",
            params=data
        )
        return objects.UserProfileList(response.json()["userProfileList"]).UserProfileList

    def change_welcome_message(self, message: str, isEnabled: bool = True):
        """
        Changes the welcome message of the community.

        **Parameters**
            - *message* : The new welcome message for the community.
            - *isEnabled* : Whether the welcome message is enabled or not.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        data = {
            "path": "general.welcomeMessage",
            "value": {
                "enabled": isEnabled,
                "text": message
            }
        }

        response = self.session.post(f"/x{self.comId}/s/community/configuration", json=data)
        return response.status_code

    def change_guidelines(self, message: str):
        """
        Changes the guidelines of the community.

        **Parameters**
            - *message* : The new guidelines for the community.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        data = { "content": message }

        response = self.session.post(f"/x{self.comId}/s/community/guideline", json=data)
        return response.status_code

    def edit_community(self, name: str = None, description: str = None, aminoId: str = None, primaryLanguage: str = None, themePackUrl: str = None):
        """
        Edits the community settings with the given parameters.

        **Parameters**
            - *name* : The new name of the community. If not provided, the current name will be kept.
            - *description* : The new description of the community. If not provided, the current description will be kept.
            - *aminoId* : The new Amino ID of the community. If not provided, the current Amino ID will be kept.
            - *primaryLanguage* : The new primary language of the community. If not provided, the current primary language will be kept.
            - *themePackUrl* : The new theme pack URL of the community. If not provided, the current theme pack URL will be kept.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        data = {}

        if name is not None:
            data["name"] = name
        if description is not None:
            data["content"] = description
        if aminoId is not None:
            data["endpoint"] = aminoId
        if primaryLanguage is not None:
            data["primaryLanguage"] = primaryLanguage
        if themePackUrl is not None:
            data["themePackUrl"] = themePackUrl

        response = self.session.post(f"/x{self.comId}/s/community/settings", json=data)
        return response.status_code

    def change_module(self, module: str, isEnabled: bool):
        """
        Changes the status of a specified module in the community.

        **Parameters**
            - *module* : The module to be changed. Can be one of the following: "chat", "livechat", "screeningroom", "publicchats", "posts", "ranking", "leaderboards", "featured", "featuredposts", "featuredusers", "featuredchats", "sharedfolder", "influencer", "catalog", "externalcontent", "topiccategories".
            - *isEnabled* : The status to be applied to the module. True for enabled, False for disabled.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        if module.lower() == "chat":
            mod = "module.chat.enabled"
        elif module.lower() == "livechat":
            mod = "module.chat.avChat.videoEnabled"
        elif module.lower() == "screeningroom":
            mod = "module.chat.avChat.screeningRoomEnabled"
        elif module.lower() == "publicchats":
            mod = "module.chat.publicChat.enabled"
        elif module.lower() == "posts":
            mod = "module.post.enabled"
        elif module.lower() == "ranking":
            mod = "module.ranking.enabled"
        elif module.lower() == "leaderboards":
            mod = "module.ranking.leaderboardEnabled"
        elif module.lower() == "featured":
            mod = "module.featured.enabled"
        elif module.lower() == "featuredposts":
            mod = "module.featured.postEnabled"
        elif module.lower() == "featuredusers":
            mod = "module.featured.memberEnabled"
        elif module.lower() == "featuredchats":
            mod = "module.featured.publicChatRoomEnabled"
        elif module.lower() == "sharedfolder":
            mod = "module.sharedFolder.enabled"
        elif module.lower() == "influencer":
            mod = "module.influencer.enabled"
        elif module.lower() == "catalog":
            mod = "module.catalog.enabled"
        elif module.lower() == "externalcontent":
            mod = "module.externalContent.enabled"
        elif module.lower() == "topiccategories":
            mod = "module.topicCategories.enabled"
        else:
            raise exceptions.SpecifyType()

        data = {
            "path": mod,
            "value": isEnabled
        }

        response = self.session.post(f"/x{self.comId}/s/community/configuration", json=data)
        return response.status_code

    def add_influencer(self, userId: str, monthlyFee: int):
        """
        Adds a user as an influencer in the community.

        **Parameters**
            - *userId* : The ID of the user to be added as an influencer.
            - *monthlyFee* : The monthly fee for the influencer.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        data = {
            "monthlyFee": monthlyFee
        }

        response = self.session.post(f"/x{self.comId}/s/influencer/{userId}", json=data)
        return response.status_code

    def remove_influencer(self, userId: str):
        """
        Removes a user from being an influencer in the community.

        **Parameters**
            - *userId* : The ID of the user to be removed from being an influencer.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        response = self.session.delete(f"/x{self.comId}/s/influencer/{userId}")
        return response.status_code
    
    def delete_admin(self, userId: str, type: str):
        """
        Delete admin from commnity in the community.

        **Parameters**
            - *userId* : The ID of the user to be removed from being an influencer.
            - *type* : The type of admin to be removed. Can be "leader" or "curator".

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        response = self.session.delete(f"/x{self.comId}/s/user-profile/{userId}/{type}")
        return response.status_code

    def get_notice_list(self, start: int = 0, size: int = 25):
        """
        Retrieves the list of notices in the community.

        **Parameters**
            - *start* : Where to start the list.
            - *size* : Size of the list.

        **Returns**
            - **Success** : :meth:`Notice List <AminoLightPy.lib.util.objects.NoticeList>`

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        params = {
            "type": "management",
            "status": "1",
            "start": start,
            "size": size
        }
        response = self.session.get(f"/x{self.comId}/s/notice", params=params)
        return objects.NoticeList(response.json()["noticeList"]).NoticeList

    def delete_pending_role(self, noticeId: str):
        """
        Deletes a pending role with the given notice ID.

        **Parameters**
            - *noticeId* : The ID of the notice for the pending role.

        **Returns**
            - **Success** : 200 (int)

            - **Fail** : :meth:`Exceptions <AminoLightPy.lib.util.exceptions>`
        """
        response = self.session.delete(f"/x{self.comId}/s/notice/{noticeId}")
        return response.status_code
