// ENVIRONMENT VARIABLES
import "dotenv/config"

const appId = process.env.DISCORD_APP_ID
const token = process.env.DISCORD_TOKEN
if (!appId || !token) {
	console.warn(chalk.red("[DiscordJS] Missing DISCORD_APP_ID or DISCORD_TOKEN in environment variables!"))
	process.exit(1)
}

// PACKAGES
import { Client, GatewayIntentBits, REST, Routes } from "discord.js"
import { Player } from "discord-player"
import { connection } from "mongoose"
import type { GuildQueueEvents } from "discord-player"
import chalk from "chalk"
import { commandFolders } from "./commands"
import clientEvents from "./events/client"
import mongoEvents from "./events/mongo"
import playerEvents from "./events/player"
import { logConsole, logConsoleDev } from "@/utils/console"

// CLIENT INITIALIZATION
const client = new Client({
	intents: [
		GatewayIntentBits.AutoModerationConfiguration,
		GatewayIntentBits.AutoModerationExecution,
		GatewayIntentBits.DirectMessageReactions,
		GatewayIntentBits.DirectMessageTyping,
		GatewayIntentBits.DirectMessages,
		GatewayIntentBits.GuildExpressions,
		GatewayIntentBits.GuildIntegrations,
		GatewayIntentBits.GuildInvites,
		GatewayIntentBits.GuildMembers,
		GatewayIntentBits.GuildMessageReactions,
		GatewayIntentBits.GuildMessageTyping,
		GatewayIntentBits.GuildMessages,
		GatewayIntentBits.GuildModeration,
		GatewayIntentBits.GuildPresences,
		GatewayIntentBits.GuildScheduledEvents,
		GatewayIntentBits.GuildVoiceStates,
		GatewayIntentBits.GuildWebhooks,
		GatewayIntentBits.Guilds,
		GatewayIntentBits.MessageContent
	],
	allowedMentions: { parse: ["roles", "users", "everyone"] }
})

// PLAYER INITIALIZATION
const player = new Player(client)

// COMMANDS REGISTRATION
const rest = new REST({ version: "10" }).setToken(token)
void (async () => {
	try {
		const commands = commandFolders.flatMap(folder => folder.name !== "salonpostam" ? folder.commands.map(command => command.data) : [])
		logConsole('discordjs', 'commands_registered', { count: commands.length.toString() })
		await rest.put(Routes.applicationCommands(process.env.DISCORD_APP_ID ?? ""), { body: commands })

		const sptGuildId = process.env.DISCORD_SPT_GUILD_ID
		if (!sptGuildId) return

		const commandsSpt = commandFolders.flatMap(folder => folder.name === "salonpostam" ? folder.commands.map(command => command.data) : [])
		logConsole('discordjs', 'commands_registered_guild', { count: commandsSpt.length.toString(), guild: 'salonpostam' })
		await rest.put(Routes.applicationGuildCommands(appId, sptGuildId), { body: commandsSpt })
	}
	catch (error) { console.error(error) }
})()

// CLIENT EVENTS REGISTRATION
clientEvents.forEach(event => {
	const callback = (...args: unknown[]) => {
		logConsoleDev('discordjs', 'event_triggered', { event: event.name.toString() })
		event.execute(...args)
	}
	if (event.once) client.once(event.name, callback)
	else client.on(event.name, callback)
})
// MONGO EVENTS REGISTRATION
mongoEvents.forEach(event => {
	const callback = (...args: unknown[]) => {
		logConsoleDev('mongoose', 'event_triggered', { event: event.name.toString() })
		event.execute(...args)
	}
	if (event.once) connection.once(event.name, callback)
	else connection.on(event.name, callback)
})
// PLAYER EVENTS REGISTRATION
playerEvents.forEach(event => {
	if (event.name === "debug") return
	const callback = (...args: unknown[]) => {
		logConsoleDev('discord_player', 'event_triggered', { event: event.name.toString() })
		event.execute(...args)
	}
	player.events.on(event.name as keyof GuildQueueEvents, callback)
})

// LAUNCH
void client.login()

export default client
