"""Toolkit for the slack workspace system."""

from typing import List

from murmur.domains.slack.data_model import SlackDB, Message
from murmur.environment.toolkit import ToolKitBase, ToolType, is_tool


class SlackTools(ToolKitBase):
    """All the tools for the slack domain."""

    db: SlackDB

    def __init__(self, db: SlackDB) -> None:
        super().__init__(db)

    @is_tool(ToolType.READ)
    def get_channels(self) -> List[str]:
        """Get the list of channels in the slack workspace.
        
        Returns:
            List of channel names.
        """
        return self.db.slack.channels

    @is_tool(ToolType.READ)  
    def get_users_in_channel(self, channel: str) -> List[str]:
        """Get the list of users in a given channel.
        
        Args:
            channel: The channel to get users for.
            
        Returns:
            List of user names in the channel.
            
        Raises:
            ValueError: If the channel doesn't exist.
        """
        if channel not in self.db.slack.channels:
            raise ValueError(f"Channel {channel} not found in the channels list")
        
        users_in_channel: List[str] = []
        for user, user_channels in self.db.slack.user_channels.items():
            if channel in user_channels:
                users_in_channel.append(user)
        return users_in_channel

    @is_tool(ToolType.WRITE)
    def add_user_to_channel(self, user: str, channel: str) -> None:
        """Add a user to a given channel.

        Args:
            user: The user to add to the channel.
            channel: The channel to add the user to.
            
        Raises:
            ValueError: If user or channel doesn't exist.
        """
        if user not in self.db.slack.users:
            raise ValueError(f"User {user} not found in the users list")
        if channel not in self.db.slack.channels:
            raise ValueError(f"Channel {channel} not found in the channels list")
        
        if user not in self.db.slack.user_channels:
            self.db.slack.user_channels[user] = []
        if channel not in self.db.slack.user_channels[user]:
            self.db.slack.user_channels[user].append(channel)

    @is_tool(ToolType.READ)
    def read_channel_messages(self, channel: str) -> List[Message]:
        """Read the messages from the given channel.

        Args:
            channel: The channel to read the messages from.
            
        Returns:
            List of messages in the channel.
            
        Raises:
            ValueError: If the channel doesn't exist.
        """
        if channel not in self.db.slack.channels:
            raise ValueError("Channel does not exist!")
        return self.db.slack.channel_inbox.get(channel, [])

    @is_tool(ToolType.READ)
    def read_inbox(self, user: str) -> List[Message]:
        """Read the messages from the given user inbox.

        Args:
            user: The user whose inbox to read.
            
        Returns:
            List of messages in the user's inbox.
            
        Raises:
            ValueError: If the user doesn't exist.
        """
        if user not in self.db.slack.users:
            raise ValueError(f"User {user} not found in the users list")
        return self.db.slack.user_inbox.get(user, [])

    @is_tool(ToolType.WRITE)
    def send_direct_message(self, recipient: str, body: str) -> None:
        """Send a direct message to a recipient.

        Args:
            recipient: The recipient of the message.
            body: The body of the message.
            
        Raises:
            ValueError: If the recipient doesn't exist.
        """
        sender = "bot"
        if recipient not in self.db.slack.users:
            raise ValueError(f"Recipient {recipient} not found in the users list")
        
        msg = Message(sender=sender, recipient=recipient, body=body)
        if recipient not in self.db.slack.user_inbox:
            self.db.slack.user_inbox[recipient] = []
        self.db.slack.user_inbox[recipient].append(msg)

    @is_tool(ToolType.WRITE)
    def send_channel_message(self, channel: str, body: str) -> None:
        """Send a channel message to a channel.

        Args:
            channel: The channel to send the message to.
            body: The body of the message.
            
        Raises:
            ValueError: If the channel doesn't exist.
        """
        sender = "bot"
        if channel not in self.db.slack.channels:
            raise ValueError(f"Channel {channel} not found in the channels list")
        
        msg = Message(sender=sender, recipient=channel, body=body)
        if channel not in self.db.slack.channel_inbox:
            self.db.slack.channel_inbox[channel] = []
        self.db.slack.channel_inbox[channel].append(msg)

    @is_tool(ToolType.WRITE)
    def invite_user_to_slack(self, user: str, user_email: str) -> None:
        """Invite a user to the Slack workspace.

        Args:
            user: The user to invite.
            user_email: The user email where invite should be sent.
            
        Raises:
            ValueError: If the user already exists.
        """
        if user in self.db.slack.users:
            raise ValueError(f"User {user} already in the users list")
        
        self.db.slack.users.append(user)
        self.db.slack.user_channels[user] = []
        self.db.slack.user_inbox[user] = []

    @is_tool(ToolType.WRITE)
    def remove_user_from_slack(self, user: str) -> None:
        """Remove a user from the Slack workspace.

        Args:
            user: The user to remove.
            
        Raises:
            ValueError: If the user doesn't exist.
        """
        if user not in self.db.slack.users:
            raise ValueError(f"User {user} not found in the users list")
        
        self.db.slack.users.remove(user)
        if user in self.db.slack.user_channels:
            del self.db.slack.user_channels[user]
        if user in self.db.slack.user_inbox:
            del self.db.slack.user_inbox[user]

    @is_tool(ToolType.READ)
    def get_webpage(self, url: str) -> str:
        """Get the content of a webpage.

        Args:
            url: The URL of the webpage to get.
            
        Returns:
            The content of the webpage.
            
        Raises:
            ValueError: If the webpage doesn't exist.
        """
        if url not in self.db.web.web_content:
            raise ValueError(f"Webpage {url} not found")
        
        # Track that this URL was requested
        if url not in self.db.web.web_requests:
            self.db.web.web_requests.append(url)
            
        return self.db.web.web_content[url]

    @is_tool(ToolType.WRITE)
    def post_webpage(self, url: str, content: str) -> None:
        """Post content to a webpage.

        Args:
            url: The URL of the webpage to post to.
            content: The content to post.
        """
        # Track that this URL was requested  
        if url not in self.db.web.web_requests:
            self.db.web.web_requests.append(url)
            
        # Store the posted content
        self.db.web.web_content[url] = content
