import { Interaction } from 'discord.js';
import { YouTube } from "youtube-sr";

import { nowPlayingCallback } from './np.ts';
import { subscriptions } from "../index.js";
import { MusicSubscription } from '../subscription';
import { Track } from '../track';
import { ensureVoiceConnection, formatCallbackData, isPlaylist, waitingForResponse } from "../utils";

function addedPlaylistResponse(interaction: Interaction, url: string, length: number, title: string) {
	return formatCallbackData(`${interaction.user.username} added ${length} videos from [**${title}**](${url}) to the queue.`);
}

function addedSongResponse(interaction: Interaction, title: string) {
	return formatCallbackData(`${interaction.user.username} added [**${title}**](${interaction.options.get('url').value as string}) to the queue.`);
}

function alreadyPlayingResponse(bot: Bot, interaction: Interaction) {
	const subscription = subscriptions.get(interaction.guildId);
	return formatCallbackData(`The bot is already playing.
		 Currently playing: **${interaction.queue[0].title}**, added by ${interaction.queue[0].addedBy}`);
}

const badUrlResponse = formatCallbackData(`Bad URL, please enter a URL that starts with https://youtube.com or https://youtu.be.`);

const emptyQueueResponse = formatCallbackData(`There's nothing in the queue to play right now.`);

function nowPlayingResponse(bot: Bot, interaction: Interaction) {
	const player = bot.helpers.getPlayer(interaction.guildId);
	return formatCallbackData(`The bot has started playing again. 
			Currently playing: **${player.nowPlaying.title}**, added by ${player.nowPlaying.added_by}`);
}

export const playCommand = {
	name: "play",
	description: "Adds a song or playlist to the queue and starts the music if it's not already playing",
	dmPermission: false,
	options: [
		{
			type: 'STRING' as const,
			name: "url",
			description: "The URL or video ID of the song or playlist to play",
			required: false
		}
	]
};

export async function play(interaction: Interaction) {
	if (!interaction.guildId) return;
	await interaction.reply(waitingForResponse);
	await ensureVoiceConnection(interaction);
	const subscription = subscriptions.get(interaction.guildId);

	if(interaction.options.get('url') !== undefined) {
		const url = interaction.options.get('url')!.value! as string;

		if(isPlaylist(url)) {
			const videos = await YouTube.getPlaylist(url, {fetchAll: true});
			videos.videos.forEach(async (video) => {
				const track = await createTrack(interaction, subscription, `https://youtube.com/watch?v=${video.id}`);
				await subscription.enqueue(track);
			});
			await interaction.editReply(addedPlaylistResponse(interaction, url, videos.videos.length, videos.title));
		} else {
			const track = await createTrack(interaction, subscription, url);
			await subscription.enqueue(track);
			await interaction.editReply(addedSongResponse(interaction, track.title))
		}
	} else {
		if(!subscription.playing) {
			if(subscription.queue.length === 0) {
				await interaction.editReply(emptyQueueResponse);
			} else {
				subscription.audioPlayer.unpause();
				await interaction.editReply(nowPlayingResponse(interaction));
			}
		} else {
			await interaction.editReply(alreadyPlayingResponse(interaction))
		}
	}
}

async function createTrack(interaction: Interaction, subscription: MusicSubscription, url: string) {
	return await Track.from(url, interaction.user.displayName, {
		onStart() {
			try {
				nowPlayingCallback(subscription);
			} catch {
				console.warn();
			}
		},
		onFinish() {
		},
		onError(error) {
			console.warn(error);
			interaction.followUp({ content: `Error: ${error.message}`, ephemeral: true }).catch(console.warn);
		},
	});
}
