import discord
from pycord.multicog import add_to_group

from services.environment_service import EnvService
from models.check_model import Check
from models.autocomplete_model import (
    Settings_autocompleter,
    File_autocompleter,
    Translations_autocompleter,
)

ALLOWED_GUILDS = EnvService.get_allowed_guilds()


class Commands(discord.Cog, name="Commands"):
    """Cog containing all slash and context commands as one-liners"""

    def __init__(
        self,
        bot,
        usage_service,
        model,
        message_queue,
        deletion_queue,
        converser_cog,
        image_draw_cog,
        image_service_cog,
        moderations_cog,
        index_cog,
        translations_cog=None,
        search_cog=None,
        transcribe_cog=None,
    ):
        super().__init__()
        self.bot = bot
        self.usage_service = usage_service
        self.model = model
        self.message_queue = message_queue
        self.deletion_queue = deletion_queue
        self.converser_cog = converser_cog
        self.image_draw_cog = image_draw_cog
        self.image_service_cog = image_service_cog
        self.moderations_cog = moderations_cog
        self.index_cog = index_cog
        self.translations_cog = translations_cog
        self.search_cog = search_cog
        self.transcribe_cog = transcribe_cog

    # Create slash command groups
    dalle = discord.SlashCommandGroup(
        name="dalle",
        description="Dalle related commands",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_dalle_roles()],
    )
    gpt = discord.SlashCommandGroup(
        name="gpt",
        description="GPT related commands",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_gpt_roles()],
    )
    system = discord.SlashCommandGroup(
        name="system",
        description="Admin/System settings for the bot",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_admin_roles()],
    )
    mod = discord.SlashCommandGroup(
        name="mod",
        description="AI-Moderation commands for the bot",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_admin_roles()],
    )
    index = discord.SlashCommandGroup(
        name="index",
        description="Custom index commands for the bot",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_index_roles()],
    )
    transcribe = discord.SlashCommandGroup(
        name="transcribe",
        description="Transcription services using OpenAI Whisper",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_index_roles()],  # TODO new role checker for transcribe
    )

    #
    # System commands
    #

    @add_to_group("system")
    @discord.slash_command(
        name="settings",
        description="Get settings for GPT3Discord",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="parameter",
        description="The setting to change",
        required=False,
        autocomplete=Settings_autocompleter.get_settings,
    )
    @discord.option(
        name="value",
        description="The value to set the setting to",
        required=False,
        autocomplete=Settings_autocompleter.get_value,
    )
    @discord.guild_only()
    async def settings(
        self, ctx: discord.ApplicationContext, parameter: str = None, value: str = None
    ):
        await self.converser_cog.settings_command(ctx, parameter, value)

    @add_to_group("system")
    @discord.slash_command(
        name="settings-reset",
        description="Reset all settings for GPT3Discord",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    async def settings_reset(self, ctx: discord.ApplicationContext):
        await self.converser_cog.settings_reset_command(ctx)

    @add_to_group("system")
    @discord.slash_command(
        name="local-size",
        description="Get the size of the dall-e images folder that we have on the current system",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    async def local_size(self, ctx: discord.ApplicationContext):
        await self.image_draw_cog.local_size_command(ctx)

    @add_to_group("system")
    @discord.slash_command(
        name="clear-local",
        description="Clear the local dalleimages folder on system.",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    async def clear_local(self, ctx: discord.ApplicationContext):
        await self.image_draw_cog.clear_local_command(ctx)

    @add_to_group("system")
    @discord.slash_command(
        name="usage",
        description="Get usage statistics for GPT3Discord",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    async def usage(self, ctx: discord.ApplicationContext):
        await self.converser_cog.usage_command(ctx)

    @add_to_group("system")
    @discord.slash_command(
        name="set-usage",
        description="Set the current OpenAI usage (in dollars)",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="usage_amount",
        description="The current usage amount in dollars and cents (e.g 10.24)",
        type=float,
    )
    async def set_usage(self, ctx: discord.ApplicationContext, usage_amount: float):
        await self.converser_cog.set_usage_command(ctx, usage_amount)

    @add_to_group("system")
    @discord.slash_command(
        name="delete-conversation-threads",
        description="Delete all conversation threads across the bot servers.",
        guild_ids=ALLOWED_GUILDS,
    )
    async def delete_all_conversation_threads(self, ctx: discord.ApplicationContext):
        await self.converser_cog.delete_all_conversation_threads_command(ctx)

    # """
    # Moderation commands
    # """

    @add_to_group("mod")
    @discord.slash_command(
        name="test",
        description="Used to test a prompt and see what threshold values are returned by the moderations endpoint",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="prompt",
        description="The prompt to test",
        required=True,
    )
    @discord.guild_only()
    async def moderations_test(self, ctx: discord.ApplicationContext, prompt: str):
        await self.moderations_cog.moderations_test_command(ctx, prompt)

    @add_to_group("mod")
    @discord.slash_command(
        name="set",
        description="Turn the moderations service on and off",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="status",
        description="Enable or disable the moderations service for the current guild (on/off)",
        required=True,
        choices=["on", "off"],
    )
    @discord.option(
        name="alert_channel_id",
        description="The channel ID to send moderation alerts to",
        required=False,
        autocomplete=Settings_autocompleter.get_value_alert_id_channel,
    )
    @discord.guild_only()
    async def moderations(
        self, ctx: discord.ApplicationContext, status: str, alert_channel_id: str
    ):
        await self.moderations_cog.moderations_command(ctx, status, alert_channel_id)

    @add_to_group("mod")
    @discord.slash_command(
        name="config",
        description="Configure the moderations service for the current guild. Lower # = more strict",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="type",
        description="The type of moderation to configure",
        required=True,
        autocomplete=Settings_autocompleter.get_value_moderations,
    )
    @discord.option(
        name="hate",
        description="The threshold for hate speech",
        required=False,
        min_value=0,
        max_value=1,
    )
    @discord.option(
        name="hate_threatening",
        description="The threshold for hate/threatening speech",
        required=False,
        min_value=0,
        max_value=1,
    )
    @discord.option(
        name="self_harm",
        description="The threshold for self_harm speech",
        required=False,
        min_value=0,
        max_value=1,
    )
    @discord.option(
        name="sexual",
        description="The threshold for sexual speech",
        required=False,
        min_value=0,
        max_value=1,
    )
    @discord.option(
        name="sexual_minors",
        description="The threshold for sexual speech with minors in context",
        required=False,
        min_value=0,
        max_value=1,
    )
    @discord.option(
        name="violence",
        description="The threshold for violent speech",
        required=False,
        min_value=0,
        max_value=1,
    )
    @discord.option(
        name="violence_graphic",
        description="The threshold for violent and graphic speech",
        required=False,
        min_value=0,
        max_value=1,
    )
    @discord.guild_only()
    async def config(
        self,
        ctx: discord.ApplicationContext,
        type: str,
        hate: float,
        hate_threatening: float,
        self_harm: float,
        sexual: float,
        sexual_minors: float,
        violence: float,
        violence_graphic: float,
    ):
        await self.moderations_cog.config_command(
            ctx,
            type,
            hate,
            hate_threatening,
            self_harm,
            sexual,
            sexual_minors,
            violence,
            violence_graphic,
        )

    #
    # GPT commands
    #

    @add_to_group("gpt")
    @discord.slash_command(
        name="ask",
        description="Ask GPT3 something!",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="prompt", description="The prompt to send to GPT3", required=True
    )
    @discord.option(
        name="model",
        description="The model to use for the request",
        required=False,
        autocomplete=Settings_autocompleter.get_models,
    )
    @discord.option(
        name="private", description="Will only be visible to you", required=False
    )
    @discord.option(
        name="temperature",
        description="Higher values means the model will take more risks",
        required=False,
        min_value=0,
        max_value=2,
    )
    @discord.option(
        name="top_p",
        description="1 is greedy sampling, 0.1 means only considering the top 10% of probability distribution",
        required=False,
        min_value=0,
        max_value=1,
    )
    @discord.option(
        name="frequency_penalty",
        description="Decreasing the model's likelihood to repeat the same line verbatim",
        required=False,
        min_value=-2,
        max_value=2,
    )
    @discord.option(
        name="presence_penalty",
        description="Increasing the model's likelihood to talk about new topics",
        required=False,
        min_value=-2,
        max_value=2,
    )
    @discord.guild_only()
    async def ask(
        self,
        ctx: discord.ApplicationContext,
        prompt: str,
        model: str,
        private: bool,
        temperature: float,
        top_p: float,
        frequency_penalty: float,
        presence_penalty: float,
    ):
        await self.converser_cog.ask_command(
            ctx,
            prompt,
            private,
            temperature,
            top_p,
            frequency_penalty,
            presence_penalty,
            model=model,
        )

    @add_to_group("gpt")
    @discord.slash_command(
        name="edit",
        description="Ask GPT3 to edit some text!",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="instruction",
        description="How you want GPT3 to edit the text",
        required=True,
    )
    @discord.option(
        name="text",
        description="The text you want to edit, can be empty",
        required=False,
        default="",
    )
    @discord.option(
        name="private", description="Will only be visible to you", required=False
    )
    @discord.option(
        name="temperature",
        description="Higher values means the model will take more risks",
        required=False,
        input_type=float,
        min_value=0,
        max_value=2,
    )
    @discord.option(
        name="top_p",
        description="1 is greedy sampling, 0.1 means only considering the top 10% of probability distribution",
        required=False,
        input_type=float,
        min_value=0,
        max_value=1,
    )
    @discord.option(
        name="codex", description="Enable codex version", required=False, default=False
    )
    @discord.guild_only()
    async def edit(
        self,
        ctx: discord.ApplicationContext,
        instruction: str,
        text: str,
        private: bool,
        temperature: float,
        top_p: float,
        codex: bool,
    ):
        await self.converser_cog.edit_command(
            ctx, instruction, text, private, temperature, top_p, codex
        )

    @add_to_group("gpt")
    @discord.slash_command(
        name="converse",
        description="Have a conversation with GPT3",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="opener",
        description="Which sentence to start with, added after the file",
        required=False,
    )
    @discord.option(
        name="opener_file",
        description="Which file to start with, added before the opener, sets minimal starter",
        required=False,
        autocomplete=File_autocompleter.get_openers,
    )
    @discord.option(
        name="private",
        description="Converse in a private thread",
        required=False,
        default=False,
    )
    @discord.option(
        name="minimal",
        description="Use minimal starter text, saves tokens and has a more open personality",
        required=False,
        default=False,
    )
    @discord.option(
        name="model",
        description="Which model to use with the bot",
        required=False,
        default=False,
        autocomplete=Settings_autocompleter.get_converse_models,
    )
    @discord.option(
        name="temperature",
        description="Higher values means the model will take more risks",
        required=False,
        input_type=float,
        min_value=0,
        max_value=2,
    )
    @discord.option(
        name="top_p",
        description="1 is greedy sampling, 0.1 means only top 10%",
        required=False,
        input_type=float,
        min_value=0,
        max_value=1,
    )
    @discord.option(
        name="frequency_penalty",
        description="Decreasing the model's likelihood to repeat the same line verbatim",
        required=False,
        input_type=float,
        min_value=-2,
        max_value=2,
    )
    @discord.option(
        name="presence_penalty",
        description="Increasing the model's likelihood to talk about new topics",
        required=False,
        input_type=float,
        min_value=-2,
        max_value=2,
    )
    @discord.option(
        name="use_threads",
        description="Set this to false to start a channel conversation",
        required=False,
        default=True,
    )
    @discord.guild_only()
    async def converse(
        self,
        ctx: discord.ApplicationContext,
        opener: str,
        opener_file: str,
        private: bool,
        minimal: bool,
        model: str,
        temperature: float,
        top_p: float,
        frequency_penalty: float,
        presence_penalty: float,
        use_threads: bool,
    ):
        await self.converser_cog.converse_command(
            ctx,
            opener,
            opener_file,
            private,
            minimal,
            model,
            temperature,
            top_p,
            frequency_penalty,
            presence_penalty,
            use_threads=use_threads,
        )

    @add_to_group("gpt")
    @discord.slash_command(
        name="end",
        description="End a conversation with GPT3",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    async def end(self, ctx: discord.ApplicationContext):
        await self.converser_cog.end_command(ctx)

    #
    # Index commands
    #
    @add_to_group("index")
    @discord.slash_command(
        name="rename-user",
        description="Select one of your saved indexes to rename",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    @discord.option(
        name="user_index",
        description="Which user index to rename",
        required=True,
        autocomplete=File_autocompleter.get_user_indexes,
    )
    @discord.option(
        name="new_name",
        description="The new name",
        required=True,
        type=discord.SlashCommandOptionType.string,
    )
    async def rename_user_index(
        self,
        ctx: discord.ApplicationContext,
        user_index: str,
        new_name: str,
    ):
        await ctx.defer()
        await self.index_cog.rename_user_index_command(ctx, user_index, new_name)

    @add_to_group("index")
    @discord.slash_command(
        name="rename-server",
        description="Select one of your saved server indexes to rename",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    @discord.option(
        name="server_index",
        description="Which server index to rename",
        required=True,
        autocomplete=File_autocompleter.get_server_indexes,
    )
    @discord.option(
        name="new_name",
        description="The new name",
        required=True,
        type=discord.SlashCommandOptionType.string,
    )
    async def rename_server_index(
        self,
        ctx: discord.ApplicationContext,
        server_index: str,
        new_name: str,
    ):
        await ctx.defer()
        await self.index_cog.rename_server_index_command(ctx, server_index, new_name)

    @add_to_group("index")
    @discord.slash_command(
        name="rename-search",
        description="Select one of your saved search indexes to rename",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    @discord.option(
        name="search_index",
        description="Which search index to rename",
        required=True,
        autocomplete=File_autocompleter.get_user_search_indexes,
    )
    @discord.option(
        name="new_name",
        description="The new name",
        required=True,
        type=discord.SlashCommandOptionType.string,
    )
    async def rename_search_index(
        self,
        ctx: discord.ApplicationContext,
        search_index: str,
        new_name: str,
    ):
        await ctx.defer()
        await self.index_cog.rename_search_index_command(ctx, search_index, new_name)

    @add_to_group("index")
    @discord.slash_command(
        name="load",
        description="Select one of your saved indexes to query from",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    @discord.option(
        name="user_index",
        description="Which user file to load the index from",
        required=False,
        autocomplete=File_autocompleter.get_user_indexes,
    )
    @discord.option(
        name="server_index",
        description="Which server file to load the index from",
        required=False,
        autocomplete=File_autocompleter.get_server_indexes,
    )
    @discord.option(
        name="search_index",
        description="Which search index file to load the index from",
        required=False,
        autocomplete=File_autocompleter.get_user_search_indexes,
    )
    async def load_index(
        self,
        ctx: discord.ApplicationContext,
        user_index: str,
        server_index: str,
        search_index: str,
    ):
        await ctx.defer()
        await self.index_cog.load_index_command(
            ctx, user_index, server_index, search_index
        )

    @add_to_group("index")
    @discord.slash_command(
        name="add", description="Add an index to query from", guild_ids=ALLOWED_GUILDS
    )
    @discord.guild_only()
    @discord.option(
        name="file",
        description="A file to create the index from",
        required=False,
        input_type=discord.SlashCommandOptionType.attachment,
    )
    @discord.option(
        name="link",
        description="A link to a file to a webpage ",
        required=False,
        input_type=str,
    )
    async def set_file(
        self, ctx: discord.ApplicationContext, file: discord.Attachment, link: str
    ):
        await self.index_cog.set_index_command(ctx, file, link)

    @add_to_group("index")
    @discord.slash_command(
        name="recurse-link",
        description="Recursively index a link",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    @discord.option(
        name="link",
        description="A link to create the index from",
        required=True,
        input_type=discord.SlashCommandOptionType.string,
    )
    @discord.option(
        name="depth",
        description="How deep to recurse",
        required=False,
        input_type=discord.SlashCommandOptionType.integer,
        min_value=1,
        max_value=5,
    )
    async def set_recurse_link(
        self, ctx: discord.ApplicationContext, link: str, depth: int
    ):
        await self.index_cog.set_index_link_recurse_command(ctx, link, depth)

    @add_to_group("index")
    @discord.slash_command(
        name="reset",
        description="Reset (delete) all of your saved indexes",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    async def reset(self, ctx: discord.ApplicationContext):
        await self.index_cog.reset_command(ctx)

    @add_to_group("index")
    @discord.slash_command(
        name="compose",
        description="Combine multiple indexes together",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="name",
        description="The name of the new index",
        required=False,
        input_type=discord.SlashCommandOptionType.string,
    )
    @discord.guild_only()
    async def compose(self, ctx: discord.ApplicationContext, name: str):
        await self.index_cog.compose_command(ctx, name)

    @add_to_group("index")
    @discord.slash_command(
        name="add_discord",
        description="Set a index from a discord channel",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    @discord.option(
        name="channel",
        description="A channel to create the index from",
        required=False,
        input_type=discord.SlashCommandOptionType.channel,
    )
    @discord.option(
        name="message_limit",
        description="The number of messages to index",
        required=False,
        input_type=discord.SlashCommandOptionType.integer,
    )
    async def set_discord(
        self,
        ctx: discord.ApplicationContext,
        channel: discord.TextChannel,
        message_limit: int,
    ):
        await self.index_cog.set_discord_command(
            ctx, channel, message_limit=message_limit
        )

    @add_to_group("index")
    @discord.slash_command(
        name="discord_backup",
        description="Save an index made from the whole server",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_admin_roles(), Check.check_index_roles()],
    )
    @discord.option(
        name="message_limit",
        description="The number of messages to index per channel",
        required=False,
        input_type=discord.SlashCommandOptionType.integer,
    )
    @discord.guild_only()
    async def discord_backup(self, ctx: discord.ApplicationContext, message_limit: int):
        await self.index_cog.discord_backup_command(ctx, message_limit=message_limit)

    @add_to_group("index")
    @discord.slash_command(
        name="query", description="Query from your index", guild_ids=ALLOWED_GUILDS
    )
    @discord.guild_only()
    @discord.option(name="query", description="What to query the index", required=True)
    @discord.option(
        name="nodes",
        description="How many nodes should the response be queried from, only non-deep indexes",
        required=False,
        default=1,
        min_value=1,
        max_value=5,
        input_type=discord.SlashCommandOptionType.integer,
    )
    @discord.option(
        name="response_mode",
        description="Response mode, doesn't work on deep composed indexes",
        guild_ids=ALLOWED_GUILDS,
        required=False,
        default="default",
        choices=["default", "compact", "tree_summarize"],
    )
    @discord.option(
        name="child_branch_factor",
        description="Only for deep indexes, how deep to go, higher is expensive.",
        required=False,
        default=1,
        min_value=1,
        max_value=3,
        input_type=discord.SlashCommandOptionType.integer,
    )
    async def query(
        self,
        ctx: discord.ApplicationContext,
        query: str,
        nodes: int,
        response_mode: str,
        child_branch_factor: int,
    ):
        await ctx.defer()
        await self.index_cog.query_command(
            ctx, query, nodes, response_mode, child_branch_factor
        )

    #
    # DALLE commands
    #

    @add_to_group("dalle")
    @discord.slash_command(
        name="draw",
        description="Draw an image from a prompt",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(name="prompt", description="The prompt to draw from", required=True)
    async def draw(self, ctx: discord.ApplicationContext, prompt: str):
        await self.image_draw_cog.draw_command(ctx, prompt)

    @add_to_group("dalle")
    @discord.slash_command(
        name="optimize",
        description="Optimize a text prompt for DALL-E/MJ/SD image generation.",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.option(
        name="prompt", description="The text prompt to optimize.", required=True
    )
    @discord.guild_only()
    async def optimize(self, ctx: discord.ApplicationContext, prompt: str):
        await self.image_service_cog.optimize_command(ctx, prompt)

    #
    # Other commands
    #

    @discord.slash_command(
        name="private-test",
        description="Private thread for testing. Only visible to you and server admins.",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    async def private_test(self, ctx: discord.ApplicationContext):
        await self.converser_cog.private_test_command(ctx)

    @discord.slash_command(
        name="help", description="Get help for GPT3Discord", guild_ids=ALLOWED_GUILDS
    )
    @discord.guild_only()
    async def help(self, ctx: discord.ApplicationContext):
        await self.converser_cog.help_command(ctx)

    @discord.slash_command(
        name="setup",
        description="Setup your API key for use with GPT3Discord",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    async def setup(self, ctx: discord.ApplicationContext):
        await self.converser_cog.setup_command(ctx)

    #
    # Text-based context menu commands from here
    #

    @discord.message_command(
        name="Ask GPT", guild_ids=ALLOWED_GUILDS, checks=[Check.check_gpt_roles()]
    )
    async def ask_gpt_action(self, ctx, message: discord.Message):
        await self.converser_cog.ask_gpt_action(ctx, message)

    #
    # Image-based context menu commands from here
    #

    @discord.message_command(
        name="Draw", guild_ids=ALLOWED_GUILDS, checks=[Check.check_dalle_roles()]
    )
    async def draw_action(self, ctx, message: discord.Message):
        await self.image_draw_cog.draw_action(ctx, message)

    """
    Translation commands and actions
    """

    @discord.slash_command(
        name="translate",
        description="Translate text to a given language",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_translator_roles()],
    )
    @discord.option(name="text", description="The text to translate", required=True)
    @discord.option(
        name="target_language",
        description="The language to translate to",
        required=True,
        autocomplete=Translations_autocompleter.get_languages,
    )
    @discord.option(
        name="formality",
        description="Formal/Informal tone of translation",
        required=False,
        autocomplete=Translations_autocompleter.get_formality_values,
    )
    @discord.guild_only()
    async def translate(
        self,
        ctx: discord.ApplicationContext,
        text: str,
        target_language: str,
        formality: str,
    ):
        if self.translations_cog:
            await self.translations_cog.translate_command(
                ctx, text, target_language, formality
            )
        else:
            await ctx.respond(
                "Translations are disabled on this server.", ephemeral=True
            )

    @discord.slash_command(
        name="languages",
        description="View the supported languages for translation",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_translator_roles()],
    )
    @discord.guild_only()
    async def languages(self, ctx: discord.ApplicationContext):
        if self.translations_cog:
            await self.translations_cog.languages_command(ctx)
        else:
            await ctx.respond(
                "Translations are disabled on this server.", ephemeral=True
            )

    @discord.message_command(
        name="Translate",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_translator_roles()],
    )
    async def translate_action(self, ctx, message: discord.Message):
        if self.translations_cog:
            await self.translations_cog.translate_action(ctx, message)
        else:
            await ctx.respond(
                "Translations are disabled on this server.", ephemeral=True
            )

    # @discord.message_command(
    #     name="Paraphrase",
    #     guild_ids=ALLOWED_GUILDS,
    #     checks=[Check.check_gpt_roles()],
    # )
    # async def paraphrase_action(self, ctx, message: discord.Message):
    #     await self.converser_cog.paraphrase_action(ctx, message)

    @discord.message_command(
        name="Elaborate",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_gpt_roles()],
    )
    async def elaborate_action(self, ctx, message: discord.Message):
        await self.converser_cog.elaborate_action(ctx, message)

    @discord.message_command(
        name="Summarize",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_gpt_roles()],
    )
    async def summarize_action(self, ctx, message: discord.Message):
        await self.converser_cog.summarize_action(ctx, message)

    # Search slash commands
    @discord.slash_command(
        name="search",
        description="Search google alongside GPT3 for something",
        guild_ids=ALLOWED_GUILDS,
        checks=[Check.check_search_roles()],
    )
    @discord.option(name="query", description="The query to search", required=True)
    @discord.option(
        name="scope",
        description="How many top links to use for context",
        required=False,
        input_type=discord.SlashCommandOptionType.integer,
        max_value=16,
        min_value=1,
    )
    @discord.option(
        name="nodes",
        description="The higher the number, the more accurate the results, but more expensive",
        required=False,
        input_type=discord.SlashCommandOptionType.integer,
        max_value=8,
        min_value=1,
    )
    @discord.option(
        name="deep",
        description="Do a more intensive, long-running search",
        required=False,
        input_type=discord.SlashCommandOptionType.boolean,
    )
    @discord.option(
        name="response_mode",
        description="Response mode, doesn't work on deep searches",
        guild_ids=ALLOWED_GUILDS,
        required=False,
        default="default",
        choices=["default", "compact", "tree_summarize"],
    )
    @discord.guild_only()
    async def search(
        self,
        ctx: discord.ApplicationContext,
        query: str,
        scope: int,
        nodes: int,
        deep: bool,
        response_mode: str,
    ):
        await self.search_cog.search_command(
            ctx, query, scope, nodes, deep, response_mode
        )

    # Transcribe commands
    @add_to_group("transcribe")
    @discord.slash_command(
        name="file",
        description="Transcribe an audio or video file",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    @discord.option(
        name="file",
        description="A file to transcribe",
        required=True,
        input_type=discord.SlashCommandOptionType.attachment,
    )
    @discord.option(
        name="temperature",
        description="The higher the value, the riskier the model will be",
        required=False,
        input_type=discord.SlashCommandOptionType.number,
        max_value=1,
        min_value=0,
    )
    async def transcribe_file(
        self,
        ctx: discord.ApplicationContext,
        file: discord.Attachment,
        temperature: float,
    ):
        await self.transcribe_cog.transcribe_file_command(ctx, file, temperature)

    @add_to_group("transcribe")
    @discord.slash_command(
        name="link",
        description="Transcribe a file link or youtube link",
        guild_ids=ALLOWED_GUILDS,
    )
    @discord.guild_only()
    @discord.option(
        name="link",
        description="A link to transcribe",
        required=True,
        input_type=discord.SlashCommandOptionType.string,
    )
    @discord.option(
        name="temperature",
        description="The higher the value, the riskier the model will be",
        required=False,
        input_type=discord.SlashCommandOptionType.number,
        max_value=1,
        min_value=0,
    )
    async def transcribe_link(
        self, ctx: discord.ApplicationContext, link: str, temperature: float
    ):
        await self.transcribe_cog.transcribe_link_command(ctx, link, temperature)
