import {
	type APIEmbed,
	ActionRowBuilder,
	ButtonBuilder,
	ButtonStyle,
	ChannelType,
	Client,
	EmbedBuilder,
	GatewayIntentBits,
	type Message,
	SlashCommandBuilder,
} from "discord.js";

import { Connectors, Track } from "shoukaku";

import { Kazagumo, type KazagumoPlayer, type KazagumoTrack, type Payload } from "kazagumo";

import KazagumoPlugin from "kazagumo-spotify";
import prettyMilliseconds from 'pretty-ms';

const { Guilds, GuildVoiceStates, GuildMessages, MessageContent } = GatewayIntentBits;

import * as dotenv from "dotenv";
dotenv.config();

if (!process.env.SPOTIFY_ID || !process.env.SPOTIFY_SECRET) {
	throw "Spotfiy Credentials missing";
}

const Nodes = [
	{
		name: "lavalink",
		url: "localhost:2333",
		auth: "youshallnotpass",
		secure: false,
	},
];

const client = new Client({
	intents: [Guilds, GuildVoiceStates, GuildMessages, MessageContent],
});

const kazagumo = new Kazagumo(
	{
		defaultSearchEngine: "youtube",
		send: (guildId: string, payload:Payload) => {
			const guild = client.guilds.cache.get(guildId);
			if (guild) guild.shard.send(payload);
		},
		plugins: [
			new KazagumoPlugin({
				clientId: process.env.SPOTIFY_ID,
				clientSecret: process.env.SPOTIFY_SECRET,
				playlistPageLimit: 1, // optional ( 100 tracks per page )
				albumPageLimit: 1, // optional ( 50 tracks per page )
				searchLimit: 10, // optional ( track search limit. Max 50 )
				searchMarket: "US", // optional || default: US ( Enter the country you live in. [ Can only be of 2 letters. For eg: US, IN, EN ] )//
			}),
		],
	},
	new Connectors.DiscordJS(client),
	Nodes,
);

client.on("ready", () => console.log(`${client.user!.tag}·Ready!`));


kazagumo.shoukaku.on("ready", (name:string) =>
	console.log(`Lavalink ${name}: Ready!`),
);
kazagumo.shoukaku.on("error", (name:string, error:Error) =>
	console.error(`Lavalink ${name}: Error Caught,`, error),
);
kazagumo.shoukaku.on("close", (name:string, code:unknown, reason:unknown) =>
	console.warn(
		`Lavalink ${name}: Closed, Code ${code}, Reason ${reason || "No reason"}`,
	),
);
kazagumo.shoukaku.on("debug", (name:string, info:string) =>
	console.debug(`Lavalink ${name}: Debug,`, info),
);

kazagumo.shoukaku.on("disconnect", (name:string, count:number) => {
	// if (moved) return;
	// players.map((player:any) => player.connection.disconnect());
	console.warn(`Lavalink ${name}: Disconnected`);
});

kazagumo.on("playerStart", (player:KazagumoPlayer, track:KazagumoTrack) => {
	if (!player.textId) return;
	const channel = client.channels.cache.get(player.textId) 
	if (!channel) return;
	if (channel.type === ChannelType.GuildText)
		{ channel.send({ content: `Now playing **${track.title}** by **${track.author}**` })
		.then((x:any) => player.data.set("message", x));}
});

kazagumo.on("playerEnd", (player:KazagumoPlayer) => {
	player.data.get("message")?.edit({ content: "Finished playing" });
});

kazagumo.on("playerEmpty", (player:KazagumoPlayer) => {
	if (!player.textId) return;
	const channel = client.channels.cache.get(player.textId) 
	if (!channel) return;
	if (channel.type === ChannelType.GuildText)
		{ channel.send({ content: "Destroyed player due to inactivity." })
		.then((x:any) => player.data.set("message", x));}
	player.destroy();
});

client.on("messageCreate", async (msg:Message) => {
	if (msg.author.bot) return;
	if (!msg.guild) return;
	if (!msg.member) return;
	if (msg.channel.type !== ChannelType.GuildText) return;
	if (msg.channel.name === "moe-song-requests") {
		const query = msg.content;
		
		const { channel } = msg.member.voice;
		if (!channel){
			msg.reply(
				"You need to be in a voice channel to use this command!",
			);
			return;
		}
		// if (channel.type !== ChannelType.GuildVoice) {return;}

		const player = await kazagumo.createPlayer({
			guildId: msg.guild.id,
			textId: msg.channel.id,
			voiceId: channel.id,
			volume: 40,
		});
		console.log("Player created")
		const result = await kazagumo.search(query, { requester: msg.author });
		if (!result.tracks.length) msg.reply("No results found!");

		if (result.type === "PLAYLIST")
			for (const track of result.tracks) player.queue.add(track);
		else player.queue.add(result.tracks[0]);

		const play = new ButtonBuilder()
			.setCustomId("play")
			.setLabel("Play/Pause")
			.setStyle(ButtonStyle.Secondary)
			.setEmoji("889943073793122355");

		const stop = new ButtonBuilder()
			.setCustomId("stop")
			.setLabel("Stop Playing")
			.setStyle(ButtonStyle.Secondary)
			.setEmoji("889943074258694184");

		const skip = new ButtonBuilder()
			.setCustomId("skip")
			.setLabel("Skip Song")
			.setStyle(ButtonStyle.Secondary)
			.setEmoji("889943074233516072");

		const loop = new ButtonBuilder()
			.setCustomId("loop")
			.setLabel("Loop Song")
			.setStyle(ButtonStyle.Secondary)
			.setEmoji("889943073667289099");

		const shuffle = new ButtonBuilder()
			.setCustomId("shuffle")
			.setLabel("Shuffle Queue")
			.setStyle(ButtonStyle.Secondary)
			.setEmoji("890325437962678352");

		const seek = new ButtonBuilder()
			.setCustomId("seek")
			.setLabel("Seek Forward")
			.setStyle(ButtonStyle.Secondary)
			.setEmoji("890325511878889504");

		const previous = new ButtonBuilder()
			.setCustomId("previous")
			.setLabel("Previous Song")
			.setStyle(ButtonStyle.Secondary)
			.setEmoji("890325512071831562");

		const row = new ActionRowBuilder<ButtonBuilder>().addComponents(play, stop, skip, loop);
		const row2 = new ActionRowBuilder<ButtonBuilder>().addComponents(shuffle, seek, previous);
		
		let track_author:string
		if (result.tracks[0].author) {
			track_author = result.tracks[0].author
		} else {
			track_author = ""
		}
		let track_duration:string
		if (result.tracks[0].length) {
			track_duration = prettyMilliseconds(result.tracks[0].length)
		} else {
			track_duration = "NaN:NaN"
		}
		let track_thumbnail:string
		if (result.tracks[0].thumbnail) {
			track_thumbnail = result.tracks[0].thumbnail.toString()
		} else {
			track_thumbnail = "NaN:NaN"
		}
		const embed = new EmbedBuilder()
			.setAuthor({
				name: "Added to queue",
				iconURL: "https://cdn.m3.fyi/MoeLogo.gif",
			})
			.setTitle(
				result.type === "PLAYLIST"
					? `Queued ${result.tracks.length} from ${result.playlistName}`
					: `Queued ${result.tracks[0].title}`,
			)
			.setDescription(`[${result.tracks[0].title}](${result.tracks[0].uri})`)
			.addFields(
				{
					name: "Author",
					value: track_author,
					inline: true,
				},
				{
					name: "Duration",
					value: track_duration,
					inline: true,
				},
			)
			.setThumbnail(track_thumbnail)
			.setColor("#ff0047");

		if (!player.playing && !player.paused) player.play();

		const response = msg.channel.send({
			embeds: [embed],
			components: [row, row2],
		})
		
		return;
	}
	})

client.login(process.env.TOKEN);
