import { ChannelType, 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 { announceCommandData, scheduleCommandData } from './command-definitions.js';
import {
  createScheduledMessage,
  deleteScheduledMessage,
  listScheduledMessages,
  SchedulerError,
  sendAnnouncement
} from './service.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 readAnnouncementOptions(
  interaction: Parameters<SlashCommand['execute']>[0]
): {
  channelId: string;
  content: string;
  embedTitle: string | null;
  embedDescription: string | null;
  embedColor: number | null;
  rolePingId: string | null;
} {
  const channel = interaction.options.getChannel('channel', true, [ChannelType.GuildText]);
  return {
    channelId: channel.id,
    content: interaction.options.getString('content', true),
    embedTitle: interaction.options.getString('embed_title'),
    embedDescription: interaction.options.getString('embed_description'),
    embedColor: interaction.options.getInteger('embed_color'),
    rolePingId: interaction.options.getRole('role')?.id ?? null
  };
}

const scheduleCommand: SlashCommand = {
  data: scheduleCommandData,
  async execute(interaction, context) {
    const locale = await getGuildLocale(context.prisma, interaction.guildId);
    if (!(await ensureManageGuild(interaction, locale))) {
      return;
    }

    const sub = interaction.options.getSubcommand();

    try {
      if (sub === 'create') {
        const options = readAnnouncementOptions(interaction);
        const schedule = await createScheduledMessage(context, {
          guildId: interaction.guildId!,
          creatorId: interaction.user.id,
          ...options,
          whenInput: interaction.options.getString('when'),
          cron: interaction.options.getString('cron')
        });

        const timing = schedule.cron
          ? tf(locale, 'scheduler.created.cron', { cron: schedule.cron })
          : schedule.runAt
            ? tf(locale, 'scheduler.created.at', {
                time: `<t:${Math.floor(schedule.runAt.getTime() / 1000)}:F>`
              })
            : '';

        await interaction.reply({
          content: tf(locale, 'scheduler.created', { id: schedule.id, timing }),
          ephemeral: true
        });
        return;
      }

      if (sub === 'list') {
        const body = await listScheduledMessages(context, interaction.guildId!, locale);
        await interaction.reply({
          content: `${t(locale, 'scheduler.list.header')}\n${body}`,
          ephemeral: true
        });
        return;
      }

      if (sub === 'delete') {
        const id = interaction.options.getString('id', true);
        const deleted = await deleteScheduledMessage(context, interaction.guildId!, id);
        if (!deleted) {
          await interaction.reply({
            content: t(locale, 'scheduler.error.not_found'),
            ephemeral: true
          });
          return;
        }
        await interaction.reply({
          content: t(locale, 'scheduler.deleted'),
          ephemeral: true
        });
      }
    } catch (error) {
      if (error instanceof SchedulerError) {
        await interaction.reply({
          content: t(locale, `scheduler.error.${error.code}`),
          ephemeral: true
        });
        return;
      }
      throw error;
    }
  }
};

const announceCommand: SlashCommand = {
  data: announceCommandData,
  async execute(interaction, context) {
    const locale = await getGuildLocale(context.prisma, interaction.guildId);
    if (!(await ensureManageGuild(interaction, locale))) {
      return;
    }

    try {
      const options = readAnnouncementOptions(interaction);
      await sendAnnouncement(context, {
        guildId: interaction.guildId!,
        creatorId: interaction.user.id,
        ...options
      });
      await interaction.reply({
        content: t(locale, 'scheduler.announce.sent'),
        ephemeral: true
      });
    } catch (error) {
      if (error instanceof SchedulerError) {
        await interaction.reply({
          content: t(locale, `scheduler.error.${error.code}`),
          ephemeral: true
        });
        return;
      }
      throw error;
    }
  }
};

export const scheduleCommands = [scheduleCommand, announceCommand];
