import { PermissionFlagsBits } from 'discord.js';
import { t, tf } from '@nexumi/shared';
import type { SlashCommand } from '../../types.js';
import { getGuildLocale } from '../../i18n.js';
import { requirePermission } from '../../permissions.js';
import { voiceCommandData } from './command-definitions.js';
import {
  claimTempChannel,
  fetchCategory,
  getTempVoiceChannelForMember,
  getTempVoiceConfig,
  hideTempChannel,
  kickFromTempChannel,
  lockTempChannel,
  renameTempChannel,
  sendControlPanelToChannel,
  setTempChannelLimit,
  transferTempChannelOwnership,
  updateTempVoiceConfig
} from './service.js';

async function requireOwnedTempChannel(
  interaction: Parameters<SlashCommand['execute']>[0],
  context: Parameters<SlashCommand['execute']>[1],
  locale: 'de' | 'en'
) {
  if (!interaction.inGuild()) {
    await interaction.reply({ content: t(locale, 'generic.guildOnly'), ephemeral: true });
    return null;
  }

  const guildMember =
    interaction.guild!.members.cache.get(interaction.user.id) ??
    (await interaction.guild!.members.fetch(interaction.user.id));
  const owned = await getTempVoiceChannelForMember(context.prisma, interaction.guildId!, guildMember);
  if (!owned || owned.record.ownerId !== interaction.user.id) {
    await interaction.reply({ content: t(locale, 'tempvoice.error.notOwner'), ephemeral: true });
    return null;
  }
  return owned;
}

const voiceCommand: SlashCommand = {
  data: voiceCommandData,
  async execute(interaction, context) {
    const locale = await getGuildLocale(context.prisma, interaction.guildId);
    if (!interaction.inGuild()) {
      await interaction.reply({ content: t(locale, 'generic.guildOnly'), ephemeral: true });
      return;
    }

    const guildId = interaction.guildId!;
    const sub = interaction.options.getSubcommand();

    if (sub === 'setup') {
      if (!(await requirePermission(interaction, PermissionFlagsBits.ManageGuild, locale))) {
        return;
      }

      const hub = interaction.options.getChannel('hub_channel', true);
      const category = interaction.options.getChannel('category', true);
      const defaultName = interaction.options.getString('default_name');
      const limit = interaction.options.getInteger('limit');

      const categoryChannel = await fetchCategory(interaction.guild!, category.id);
      if (!categoryChannel) {
        await interaction.reply({ content: t(locale, 'tempvoice.error.invalidCategory'), ephemeral: true });
        return;
      }

      await updateTempVoiceConfig(context.prisma, guildId, {
        enabled: true,
        hubChannelId: hub.id,
        categoryId: category.id,
        defaultName: defaultName ?? undefined,
        defaultLimit: limit ?? undefined
      });

      await interaction.reply({ content: t(locale, 'tempvoice.setup.done'), ephemeral: true });
      return;
    }

    const config = await getTempVoiceConfig(context.prisma, guildId);
    if (!config.enabled) {
      await interaction.reply({ content: t(locale, 'tempvoice.error.disabled'), ephemeral: true });
      return;
    }

    if (sub === 'panel') {
      const owned = await requireOwnedTempChannel(interaction, context, locale);
      if (!owned) {
        return;
      }

      await sendControlPanelToChannel(owned.channel, locale);
      await interaction.reply({ content: t(locale, 'tempvoice.panel.sent'), ephemeral: true });
      return;
    }

    if (sub === 'claim') {
      const member = await interaction.guild!.members.fetch(interaction.user.id);
      const inChannel = await getTempVoiceChannelForMember(context.prisma, guildId, member);
      if (!inChannel) {
        await interaction.reply({ content: t(locale, 'tempvoice.error.notInChannel'), ephemeral: true });
        return;
      }

      const result = await claimTempChannel(context, inChannel.record, inChannel.channel, member, locale);
      if (result === 'owner_present') {
        await interaction.reply({ content: t(locale, 'tempvoice.claim.ownerPresent'), ephemeral: true });
        return;
      }
      if (result === 'not_in_channel') {
        await interaction.reply({ content: t(locale, 'tempvoice.error.notInChannel'), ephemeral: true });
        return;
      }

      await interaction.reply({ content: t(locale, 'tempvoice.claim.success'), ephemeral: true });
      return;
    }

    const owned = await requireOwnedTempChannel(interaction, context, locale);
    if (!owned) {
      return;
    }

    if (sub === 'rename') {
      const name = interaction.options.getString('name', true);
      await renameTempChannel(owned.channel, name);
      await interaction.reply({
        content: tf(locale, 'tempvoice.rename.success', { name: name.slice(0, 100) }),
        ephemeral: true
      });
      return;
    }

    if (sub === 'limit') {
      const limit = interaction.options.getInteger('limit', true);
      await setTempChannelLimit(owned.channel, limit);
      await interaction.reply({
        content: tf(locale, 'tempvoice.limit.success', { limit }),
        ephemeral: true
      });
      return;
    }

    if (sub === 'lock') {
      await lockTempChannel(owned.channel);
      await interaction.reply({ content: t(locale, 'tempvoice.lock.success'), ephemeral: true });
      return;
    }

    if (sub === 'hide') {
      await hideTempChannel(owned.channel);
      await interaction.reply({ content: t(locale, 'tempvoice.hide.success'), ephemeral: true });
      return;
    }

    if (sub === 'kick') {
      const user = interaction.options.getUser('user', true);
      if (user.id === interaction.user.id) {
        await interaction.reply({ content: t(locale, 'tempvoice.kick.self'), ephemeral: true });
        return;
      }
      const ok = await kickFromTempChannel(owned.channel, user.id);
      if (!ok) {
        await interaction.reply({ content: t(locale, 'tempvoice.kick.notInChannel'), ephemeral: true });
        return;
      }
      await interaction.reply({
        content: tf(locale, 'tempvoice.kick.success', { user: `<@${user.id}>` }),
        ephemeral: true
      });
      return;
    }

    if (sub === 'transfer') {
      const user = interaction.options.getUser('user', true);
      if (user.id === interaction.user.id) {
        await interaction.reply({ content: t(locale, 'tempvoice.transfer.self'), ephemeral: true });
        return;
      }
      const target = await interaction.guild!.members.fetch(user.id).catch(() => null);
      if (!target || !owned.channel.members.has(target.id)) {
        await interaction.reply({ content: t(locale, 'tempvoice.transfer.notInChannel'), ephemeral: true });
        return;
      }
      await transferTempChannelOwnership(context, owned.record, owned.channel, target, locale);
      await interaction.reply({
        content: tf(locale, 'tempvoice.transfer.success', { user: `<@${user.id}>` }),
        ephemeral: true
      });
    }
  }
};

export const tempVoiceCommands: SlashCommand[] = [voiceCommand];
