import typing

from bot.constants import BOT_REPO_URL
from discord import Embed
from discord.ext import commands
from discord.ext.commands.cooldowns import BucketType

from . import _issues, _profile, _source


class Github(commands.Cog):
    """
    Github Category cog, which contains commands related to github.

    Commands:
        ├ profile       Fetches a user's GitHub information.
        ├ issue         Command to retrieve issue(s) from a GitHub repository.
        └ source        Displays information about the bot's source code.
    """

    def __init__(self, bot: commands.Bot) -> None:
        self.bot = bot

    @commands.group(name="github", aliases=("gh",), invoke_without_command=True)
    async def github_group(self, ctx: commands.Context) -> None:
        """Commands for Github."""
        await ctx.send_help(ctx.command)

    @github_group.command(name="profile")
    @commands.cooldown(1, 10, BucketType.user)
    async def profile(self, ctx: commands.Context, username: str) -> None:
        """
        Fetches a user's GitHub information.

        Username is optional and sends the help command if not specified.
        """
        github_profile = _profile.GithubInfo(self.bot.http_session)
        embed = await github_profile.get_github_info(username)

        await ctx.send(embed=embed)

    @github_group.command(name="issue", aliases=("pr",))
    async def issue(
        self,
        ctx: commands.Context,
        numbers: commands.Greedy[int],
        repository: typing.Optional[str] = None,
    ) -> None:
        """Command to retrieve issue(s) from a GitHub repository."""
        github_issue = _issues.Issues(self.bot.http_session)

        if not numbers:
            raise commands.MissingRequiredArgument(ctx.command.clean_params["numbers"])

        if repository is None:
            user = "gurkult"
        else:
            user, _, repository = repository.rpartition("/")
            if user == "":
                user = "gurkult"

        embed = await github_issue.issue(ctx.message.channel, numbers, repository, user)

        await ctx.send(embed=embed)

    @github_group.command(name="source", aliases=("src", "inspect"))
    async def source_command(
        self, ctx: commands.Context, *, source_item: typing.Optional[str] = None
    ) -> None:
        """Displays information about the bot's source code."""
        if source_item is None:
            embed = Embed(title="Gurkbot's GitHub Repository")
            embed.add_field(name="Repository", value=f"[Go to GitHub]({BOT_REPO_URL})")
            embed.set_thumbnail(url=self.bot.user.avatar_url)
            await ctx.send(embed=embed)
            return
        elif not ctx.bot.get_command(source_item):
            raise commands.BadArgument(
                f"Unable to convert `{source_item}` to valid command or Cog."
            )

        github_source = _source.Source(self.bot.http_session, self.bot.user.avatar_url)
        embed = await github_source.inspect(cmd=ctx.bot.get_command(source_item))

        await ctx.send(embed=embed)


def setup(bot: commands.Bot) -> None:
    """Load the Github cog."""
    bot.add_cog(Github(bot))

[((24, 5, 24, 80), 'discord.ext.commands.group', 'commands.group', (), '', False, 'from discord.ext import commands\n'), ((30, 5, 30, 46), 'discord.ext.commands.cooldown', 'commands.cooldown', ({(30, 23, 30, 24): '(1)', (30, 26, 30, 28): '(10)', (30, 30, 30, 45): 'BucketType.user'}, {}), '(1, 10, BucketType.user)', False, 'from discord.ext import commands\n'), ((53, 18, 53, 87), 'discord.ext.commands.MissingRequiredArgument', 'commands.MissingRequiredArgument', ({(53, 51, 53, 86): "ctx.command.clean_params['numbers']"}, {}), "(ctx.command.clean_params['numbers'])", False, 'from discord.ext import commands\n'), ((72, 20, 72, 62), 'discord.Embed', 'Embed', (), '', False, 'from discord import Embed\n'), ((78, 18, 80, 13), 'discord.ext.commands.BadArgument', 'commands.BadArgument', ({(79, 16, 79, 77): 'f"""Unable to convert `{source_item}` to valid command or Cog."""'}, {}), "(\n    f'Unable to convert `{source_item}` to valid command or Cog.')", False, 'from discord.ext import commands\n')]