import discord

""" Declare intents that the bot will use """
intents = discord.Intents.default()
intents.emojis_and_stickers = True
intents.guilds = True
intents.integrations = True
intents.message_content = True
intents.messages = True
intents.members = True
intents.presences = True
intents.reactions = True
intents.voice_states = True

""" Load the bot token """
from decouple import config
DISCORD_TOKEN: str = config("DISCORD_BOT_TOKEN")
DISCORD_GUILD: int = config("DISCORD_GUILD_ID", cast=int)

""" Initialize the Discord bot """
from discord.ext.commands import Bot, when_mentioned_or
bot: Bot = Bot(
	command_prefix=when_mentioned_or('..', '>', '.'),
	description="A list of commands available",
	intents=intents,
	# debug_guilds=[GUILD],
	max_messages=100_000
)

@bot.event
async def on_ready():
	print(f"Logged in as {bot.user} (ID: {bot.user.id})")
	print("------")

""" Load cogs """
from os import listdir

def list_all_cogs() -> list[str]:
	return [file[:-3] for file in listdir("cogs") if file.endswith(".py")]

for cog in list_all_cogs():
	bot.load_extension(f"cogs.{cog}")

# TODO: web server for jukebox and/or soundboard?
# TODO: cog to announce when someone joins vc (maybe delete messages after some time?)
# TODO: purge messages from a user / etc? links, number, bot or human, idk
# TODO: automod? blocklist certain words or urls or whatever
# TODO: warn or kick or ban a user?
# TODO: filter the audit logs for a user? maybe?
# TODO: keep stats or levels? ehhhh

# ================================= ADMIN ======================================
from discord.commands import Option
from discord.ext.commands import Context
from discord import AutocompleteContext, ApplicationContext

async def cog_autocomplete(ctx: AutocompleteContext) -> list[str]:
	return [cog for cog in list_all_cogs() if cog.lower().startswith( ctx.value.lower() )]

ADMIN_ROLE: int = config("DISCORD_BOT_ADMIN_ROLE_ID", cast=int, default=0)
ADMIN_USER: int = config("DISCORD_BOT_ADMIN_USER_ID", cast=int)

def allowed_to_reload(ctx: Context | ApplicationContext) -> bool:
	roles: set[int] = set([role.id for role in ctx.author.roles])
	admin: bool = ADMIN_ROLE in roles
	owner: bool = ctx.author.id == ADMIN_USER
	return any([admin, owner])

from cogs.music import Music
def reload_music(ctx):
	music: Music = bot.get_cog("Music")
	
	q = music.q
	track = music.track
	repeat_mode = music.repeat_mode
	search_results = music.search_results
	
	bot.reload_extension(f"cogs.music")
	
	music = bot.get_cog("Music")
	
	music.q = q
	music.track = track
	music.repeat_mode = repeat_mode
	music.search_results = search_results

@bot.command(name='reload')
async def reload_prefix(ctx: Context, cog: str = "") -> None:
	"""Reload an extension (admin command)"""
	if not allowed_to_reload(ctx):
		return await ctx.send("You must be an admin or bot owner to use this command")
	if not cog:
		return await ctx.send("Please specify a cog to reload")
	elif cog.lower() == "music":
		reload_music(ctx)
	else:
		bot.reload_extension(f"cogs.{cog}")
	return await ctx.send(f"Reloaded `{cog}` extension")

@bot.slash_command(
	name='reload',
	guild_ids=[DISCORD_GUILD],
)
async def reload_slash(
	ctx: ApplicationContext,
	cog: Option(str, "The cog to be reloaded", autocomplete=cog_autocomplete)
):
	"""Reload an extension (admin command)"""
	if not allowed_to_reload(ctx):
		return await ctx.respond(
			"You must be an admin or bot owner to use this command",
			ephemeral=True
		)
	if cog == "music":
		reload_music(ctx)
	else:
		bot.reload_extension(f"cogs.{cog}")
	return await ctx.respond(f"Reloaded `{cog}` extension", ephemeral=True)

# ================================== END =======================================

""" Run the bot """
bot.run(DISCORD_TOKEN)