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 { backupCommandData } from './command-definitions.js';
import {
  createGuildBackup,
  ensureBotCanRestore,
  getGuildBackup,
  GuildBackupError,
  listGuildBackups,
  parseBackupPayload
} from './service.js';
import { promptDeleteConfirmation, promptRestoreConfirmation } from './confirmations.js';

async function ensureManageGuild(
  interaction: Parameters<SlashCommand['execute']>[0],
  locale: 'de' | 'en'
): Promise<boolean> {
  if (!interaction.inGuild()) {
    await interaction.reply({ content: t(locale, 'generic.guildOnly'), ephemeral: true });
    return false;
  }
  return requirePermission(interaction, PermissionFlagsBits.ManageGuild, locale);
}

function defaultBackupName(): string {
  return `backup-${new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)}`;
}

const backupCommand: SlashCommand = {
  data: backupCommandData,
  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 sub = interaction.options.getSubcommand();
    const guild = interaction.guild!;

    if (sub === 'create') {
      if (!(await ensureManageGuild(interaction, locale))) {
        return;
      }

      const name = interaction.options.getString('name')?.trim() || defaultBackupName();
      if (name.length < 1 || name.length > 100) {
        await interaction.reply({
          content: t(locale, 'guildbackup.error.invalid_name'),
          ephemeral: true
        });
        return;
      }

      await interaction.deferReply({ ephemeral: true });

      try {
        const backup = await createGuildBackup(context, guild, name, interaction.user.id);
        await interaction.editReply({
          content: tf(locale, 'guildbackup.created', { id: backup.id, name: backup.name })
        });
      } catch (error) {
        if (error instanceof GuildBackupError) {
          await interaction.editReply({
            content: t(locale, `guildbackup.error.${error.code}`)
          });
          return;
        }
        throw error;
      }
      return;
    }

    if (sub === 'list') {
      if (!(await ensureManageGuild(interaction, locale))) {
        return;
      }
      const backups = await listGuildBackups(context, guild.id);
      if (backups.length === 0) {
        await interaction.reply({
          content: t(locale, 'guildbackup.list.empty'),
          ephemeral: true
        });
        return;
      }

      const lines = backups.map((backup) =>
        tf(locale, 'guildbackup.list.line', {
          id: backup.id,
          name: backup.name,
          date: backup.createdAt.toISOString().slice(0, 10)
        })
      );

      await interaction.reply({
        content: `${t(locale, 'guildbackup.list.header')}\n${lines.join('\n')}`,
        ephemeral: true
      });
      return;
    }

    if (sub === 'info') {
      if (!(await ensureManageGuild(interaction, locale))) {
        return;
      }
      const backupId = interaction.options.getString('id', true);
      const backup = await getGuildBackup(context, guild.id, backupId);
      if (!backup) {
        await interaction.reply({
          content: t(locale, 'guildbackup.error.not_found'),
          ephemeral: true
        });
        return;
      }

      let roleCount = 0;
      let channelCount = 0;
      try {
        const payload = parseBackupPayload(backup.payload);
        roleCount = payload.roles.length;
        channelCount = payload.channels.length;
      } catch {
        await interaction.reply({
          content: t(locale, 'guildbackup.error.invalid_payload'),
          ephemeral: true
        });
        return;
      }

      await interaction.reply({
        content: [
          tf(locale, 'guildbackup.info.id', { id: backup.id }),
          tf(locale, 'guildbackup.info.name', { name: backup.name }),
          tf(locale, 'guildbackup.info.created', { date: backup.createdAt.toISOString() }),
          tf(locale, 'guildbackup.info.createdBy', { userId: backup.createdById }),
          tf(locale, 'guildbackup.info.roles', { count: roleCount }),
          tf(locale, 'guildbackup.info.channels', { count: channelCount }),
          t(locale, 'guildbackup.info.limitations')
        ].join('\n'),
        ephemeral: true
      });
      return;
    }

    if (sub === 'delete') {
      if (!(await ensureManageGuild(interaction, locale))) {
        return;
      }

      const backupId = interaction.options.getString('id', true);
      const backup = await getGuildBackup(context, guild.id, backupId);
      if (!backup) {
        await interaction.reply({
          content: t(locale, 'guildbackup.error.not_found'),
          ephemeral: true
        });
        return;
      }

      await promptDeleteConfirmation(interaction, context, locale, backupId);
      return;
    }

    if (sub === 'restore') {
      if (guild.ownerId !== interaction.user.id) {
        await interaction.reply({
          content: t(locale, 'guildbackup.error.owner_only'),
          ephemeral: true
        });
        return;
      }

      if (!ensureBotCanRestore(guild)) {
        await interaction.reply({
          content: t(locale, 'guildbackup.error.bot_missing_permissions'),
          ephemeral: true
        });
        return;
      }

      const backupId = interaction.options.getString('id', true);
      const backup = await getGuildBackup(context, guild.id, backupId);
      if (!backup) {
        await interaction.reply({
          content: t(locale, 'guildbackup.error.not_found'),
          ephemeral: true
        });
        return;
      }

      try {
        parseBackupPayload(backup.payload);
      } catch {
        await interaction.reply({
          content: t(locale, 'guildbackup.error.invalid_payload'),
          ephemeral: true
        });
        return;
      }

      await promptRestoreConfirmation(interaction, context, locale, backupId);
    }
  }
};

export const guildBackupCommands = [backupCommand];
