const { SlashCommandBuilder } = require('discord.js');
const { QueryType } = require('discord-player');

module.exports = {
  data: new SlashCommandBuilder()
    .setName('music')
    .setDescription('Play and configure music')
    .addSubcommand(subcommand => subcommand
      .setName('play')
      .setDescription('Play music')
      .addStringOption(option => option
        .setName('link-or-query')
        .setDescription('The song or link you want to play')
        .setRequired(true)))
    .addSubcommand(subcommand => subcommand
      .setName('skip')
      .setDescription('Skip current song'))
    .addSubcommand(subcommand => subcommand
      .setName('stop')
      .setDescription('Stop current queue'))
    .addSubcommand(subcommand => subcommand
      .setName('pause')
      .setDescription('Pause the current song'))
    .addSubcommand(subcommand => subcommand
      .setName('shuffle')
      .setDescription('Shuffle the queue'))
    .addSubcommand(subcommand => subcommand
      .setName('resume')
      .setDescription('Resume the current song'))
    .addSubcommand(subcommand => subcommand
      .setName('filter')
      .setDescription('Apply a filter')
      .addStringOption(option => option
        .setName('type')
        .setDescription('Type of filter')
        .setRequired(true)
        .addChoices(
          { name: 'Bassboost', value: 'bassboost_low' },
          { name: 'Nightcore', value: 'nightcore' },
        )))
    .addSubcommand(subcommand => subcommand
      .setName('volume')
      .setDescription('Set volume')
      .addNumberOption(option => option
        .setName('percentage')
        .setDescription('The percentage of the volume between 1 and 100')
        .setRequired(true))),

  async execute({ interaction, createEmbed, client }) {
    if (!interaction.member.voice.channelId) return await interaction.reply({ embeds: [createEmbed.basic('You are not in a voice channel!')], ephemeral: true });
    if (interaction.guild.members.me.voice.channelId && interaction.member.voice.channelId !== interaction.guild.members.me.voice.channelId) {
      return await interaction.reply({ embeds: [createEmbed.basic('You are not in my voice channel!')], ephemeral: true });
    }


    if (interaction.options.getSubcommand() === 'play') {
      const query = interaction.options.getString('link-or-query');

      const queue = client.player.createQueue(interaction.guild, {
        ytdlOptions: {
          filter: 'audioonly',
          highWaterMark: 1 << 30,
          dlChunkSize: 0,
        },
        metadata: {
          channel: interaction.channel,
        },
      });

      // verify vc connection
      try {
        if (!queue.connection) await queue.connect(interaction.member.voice.channel);
      } catch {
        queue.destroy();
        return await interaction.reply({ embeds: [createEmbed.basic('Could not join your voice channel!')], ephemeral: true });
      }

      await interaction.reply({ embeds: [createEmbed.basic('Searching...')], ephemeral: true });

      const searchResult = await client.player.search(query, {
        requestedBy: interaction.user,
        searchEngine: QueryType.AUTO,
      });
      if (!searchResult || !searchResult.tracks[0]) return await interaction.editReply({ embeds: [createEmbed.basic(`Track or playlist **${query}** not found!`)], ephemeral: true });

      searchResult.playlist ? queue.addTracks(searchResult.tracks) : queue.addTrack(searchResult.tracks[0]);
      if (!queue.playing) await queue.play();

      if (!searchResult.playlist) await interaction.editReply({ embeds: [createEmbed.basic(`Adding track **${searchResult.tracks[0].title}**`)], ephemeral: false });
      else await interaction.editReply({ embeds: [createEmbed.basic(`Adding **${searchResult.playlist.tracks.length}** tracks from playlist **${searchResult.playlist.title}**`)], ephemeral: false });

    } else if (interaction.options.getSubcommand() === 'skip') {

      const queue = client.player.getQueue(interaction.guild);

      if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });

      const currentTrack = queue.nowPlaying();
      const success = queue.skip();

      await interaction.reply({ embeds: [createEmbed.basic(success ? `Skipped **${currentTrack.title}**` : 'Something went wrong')] });
    } else if (interaction.options.getSubcommand() === 'volume') {
      const vol = interaction.options.getNumber('percentage');

      const queue = client.player.getQueue(interaction.guild);

      if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });

      if (vol < 1 || vol > 100) return interaction.reply({ embeds: [createEmbed.basic('Volume must be between 1 and 100')] });

      const success = queue.setVolume(vol);

      await interaction.reply({ embeds: [createEmbed.basic(success ? `Volume set to **${vol}%**` : 'Something went wrong')] });
    } else if (interaction.options.getSubcommand() === 'stop') {

      const queue = client.player.getQueue(interaction.guild);

      if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });

      queue.destroy();

      await interaction.reply({ embeds: [createEmbed.basic('Stopped the player')] });
    } else if (interaction.options.getSubcommand() === 'pause') {

      const queue = client.player.getQueue(interaction.guild);

      if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });

      queue.setPaused(true);

      await interaction.reply({ embeds: [createEmbed.basic('Paused the player')] });
    } else if (interaction.options.getSubcommand() === 'resume') {

      const queue = client.player.getQueue(interaction.guild);

      if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });

      queue.setPaused(false);

      await interaction.reply({ embeds: [createEmbed.basic('Resumed the player')] });
    } else if (interaction.options.getSubcommand() === 'filter') {
      const filter = interaction.options.getString('type');

      const queue = client.player.getQueue(interaction.guild);

      if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });

      if (filter === 'bassboost_low') {
        await queue.setFilters({
          bassboost_low: !queue.getFiltersEnabled().includes('bassboost_low'),
          normalizer2: !queue.getFiltersEnabled().includes('bassboost_low'),
        });
      }

      if (filter === 'nightcore') {
        await queue.setFilters({
          nightcore: !queue.getFiltersEnabled().includes('nightcore'),
        });
      }

      await interaction.reply({ embeds: [createEmbed.basic(queue.getFiltersEnabled().includes(filter) ? `Applied **${filter}** filter` : `Removed **${filter}** filter`)] });
    } else if (interaction.options.getSubcommand() === 'shuffle') {

      const queue = client.player.getQueue(interaction.guild);

      if (!queue || !queue.playing) return await interaction.reply({ embeds: [createEmbed.basic('No music is being played')] });

      const success = queue.shuffle();

      await interaction.reply({ embeds: [createEmbed.basic(success ? 'The queue has been shuffled' : 'Something went wrong')] });
    }
  },
};
