"""
Message - Read and send messages

TODO: Support group messaging
"""
from xbox.webapi.api.provider.baseprovider import BaseProvider
from xbox.webapi.api.provider.message.models import (
    ConversationResponse,
    InboxResponse,
    SendMessageResponse,
)


class MessageProvider(BaseProvider):
    MSG_URL = "https://xblmessaging.xboxlive.com"
    HEADERS_MESSAGE = {"x-xbl-contract-version": "1"}
    HEADERS_HORIZON = {"x-xbl-contract-version": "2"}

    async def get_inbox(self, max_items: int = 100, **kwargs) -> InboxResponse:
        """
        Get messages

        Returns:
            :class:`InboxResponse`: Inbox Response
        """
        url = f"{self.MSG_URL}/network/Xbox/users/me/inbox"
        params = {"maxItems": max_items}
        resp = await self.client.session.get(
            url, params=params, headers=self.HEADERS_MESSAGE, **kwargs
        )
        resp.raise_for_status()
        return InboxResponse(**resp.json())

    async def get_conversation(
        self, xuid: str, max_items: int = 100, **kwargs
    ) -> ConversationResponse:
        """
        Get detailed conversation info

        Args:
            xuid: Xuid of user having a conversation with

        Returns:
            :class:`ConversationResponse`: Conversation Response
        """
        url = f"{self.MSG_URL}/network/Xbox/users/me/conversations/users/xuid({xuid})"
        params = {"maxItems": max_items}
        resp = await self.client.session.get(
            url, params=params, headers=self.HEADERS_MESSAGE, **kwargs
        )
        resp.raise_for_status()
        return ConversationResponse(**resp.json())

    async def delete_conversation(
        self, conversation_id: str, horizon: str, **kwargs
    ) -> bool:
        """
        Delete message

        **NOTE**: Returns HTTP Status Code **200** on success

        Args:
            conversation_id: Message Id
            horizon: Delete horizon from get conversation response

        Returns: True on success, False otherwise
        """
        url = f"{self.MSG_URL}/network/Xbox/users/me/conversations/horizon"
        post_data = {
            "conversations": [
                {
                    "conversationId": conversation_id,
                    "conversationType": "OneToOne",
                    "horizonType": "Delete",
                    "horizon": horizon,
                }
            ]
        }
        resp = await self.client.session.put(
            url, json=post_data, headers=self.HEADERS_HORIZON, **kwargs
        )
        return resp.status_code == 200

    async def delete_message(
        self, conversation_id: str, message_id: str, **kwargs
    ) -> bool:
        """
        Delete message

        **NOTE**: Returns HTTP Status Code **200** on success

        Args:
            conversation_id: Conversation Id
            message_id: Message Id

        Returns: True on success, False otherwise
        """
        url = f"{self.MSG_URL}/network/Xbox/users/me/conversations/{conversation_id}/messages/{message_id}"
        resp = await self.client.session.delete(
            url, headers=self.HEADERS_MESSAGE, **kwargs
        )
        return resp.status_code == 200

    async def send_message(
        self, xuid: str, message_text: str, **kwargs
    ) -> SendMessageResponse:
        """
        Send message to an xuid

        Args:
            xuid: Xuid
            message_text: Message text

        Returns:
            :class:`SendMessageResponse`: Send Message Response
        """
        if len(message_text) > 256:
            raise ValueError("Message text exceeds max length of 256 chars")

        url = f"{self.MSG_URL}/network/Xbox/users/me/conversations/users/xuid({xuid})"
        post_data = {
            "parts": [
                {
                    "contentType": "text",
                    "version": 0,
                    "text": message_text,
                }
            ]
        }
        resp = await self.client.session.post(
            url, json=post_data, headers=self.HEADERS_MESSAGE, **kwargs
        )
        resp.raise_for_status()
        return SendMessageResponse(**resp.json())
