"""

MYLLM Main 🤖

"""

import asyncio
import importlib

import g4f

from g4f import Provider
from loguru import logger

from myllm import __version__
from myllm.config import settings


class MyLLM:
    """

    MyLLM class use to initiate a LLM client
    with a given model and a given provider

    Attributes:
        logger (Logger): Logger
        enabled (bool): Whether MyLLM is enabled
        commands (str): MyLLM commands
        llm (LLM): LLM
        conversation (ConversationChain): Conversation

    Methods:
        get_myllm_info(self)
        get_myllm_help(self)
        chat(self, prompt)
        clear_chat_history(self)

    """

    def __init__(self):
        """
        Initialize the MyLLM object

        Args:
            None
        """

        self.enabled = settings.llm_enabled
        if not self.enabled:
            return
        self.commands = settings.llm_commands
        self.llm_ai_mode = settings.llm_ai_mode
        provider_module_name = settings.llm_provider
        provider_module = importlib.import_module(provider_module_name)
        provider_class = getattr(provider_module, provider_module_name.split(".")[-1])
        self.provider = provider_class()
        self.conversation = Conversation()

    async def get_myllm_info(self):
        """
        Get MyLLM information.

        Returns:
            str: A string containing the MyLLM version, model, and provider.
        """
        return (
            f"ℹ️ MyLLM v{__version__}\n {settings.llm_model}\n{settings.llm_provider}"
        )

    async def get_myllm_help(self):
        """
        Get the help message for MyLLM.

        Returns:
            str: The help message for the `myllm` command.
        """
        return f"{self.commands}\n"

    async def chat(self, prompt):
        """
        Asynchronously chats with the user.

        Args:
            prompt (str): The prompt message from the user.

        Returns:
            str: The predicted response from the conversation model.
        """
        logger.debug("chat {}", prompt)
        self.conversation.add_message("user", prompt)
        logger.debug("conversation {}", self.conversation.get_messages())
        response = await self.provider.create_async(
            model=settings.llm_model,
            messages=self.conversation.get_messages(),
        )
        logger.debug("response {}", response)
        self.conversation.add_message("ai", response)
        logger.debug("conversation {}", self.conversation.get_messages())
        return response

    async def clear_chat_history(self):
        """
        Clears the chat history by setting the `conversation`
        attribute to an empty string.
        """
        self.conversation = Conversation()

    async def switch_continous_mode(self):
        """ """
        self.llm_ai_mode = not self.llm_ai_mode
        return f"Continous mode {'enabled' if self.llm_ai_mode else 'disabled'}."


class Conversation:
    def __init__(self, max_memory=5):
        self.messages = []
        self.max_memory = max_memory

    def add_message(self, role: str, content: str):
        if len(self.messages) >= self.max_memory:
            self.messages.pop(0)  # Remove the oldest message
        self.messages.append({"role": role, "content": content})

    def get_messages(self):
        logger.debug("messages {}", self.messages)
        return self.messages
