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 { parseDuration } from '../moderation/duration.js';
import { giveawayCommandData } from './command-definitions.js';
import {
  cancelGiveawayJob,
  deleteGiveaway,
  endGiveaway,
  GiveawayError,
  listActiveGiveaways,
  pauseGiveaway,
  rerollGiveaway,
  startGiveaway
} 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);
}

async function replyEphemeral(
  interaction: Parameters<SlashCommand['execute']>[0],
  content: string
): Promise<void> {
  if (interaction.deferred || interaction.replied) {
    await interaction.editReply({ content });
    return;
  }
  await interaction.reply({ content, ephemeral: true });
}

const giveawayCommand: SlashCommand = {
  data: giveawayCommandData,
  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();

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

      const durationInput = interaction.options.getString('duration', true);
      let durationMs: number;
      try {
        durationMs = parseDuration(durationInput);
      } catch {
        await interaction.reply({
          content: t(locale, 'giveaway.error.invalid_duration'),
          ephemeral: true
        });
        return;
      }

      if (durationMs < 60_000) {
        await interaction.reply({
          content: t(locale, 'giveaway.error.duration_too_short'),
          ephemeral: true
        });
        return;
      }

      const channel = interaction.channel;
      if (!channel?.isTextBased() || channel.isDMBased()) {
        await interaction.reply({
          content: t(locale, 'giveaway.error.invalid_channel'),
          ephemeral: true
        });
        return;
      }

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

      const giveaway = await startGiveaway(
        context,
        {
          guildId: interaction.guildId!,
          channelId: channel.id,
          hostId: interaction.user.id,
          prize: interaction.options.getString('prize', true),
          winnerCount: interaction.options.getInteger('winners', true),
          durationMs,
          requiredRoleId: interaction.options.getRole('role')?.id,
          requiredLevel: interaction.options.getInteger('level'),
          requiredMemberDays: interaction.options.getInteger('member_days')
        },
        locale
      );

      await interaction.editReply({
        content: tf(locale, 'giveaway.started', { id: giveaway.id })
      });
      return;
    }

    if (!(await ensureManageGuild(interaction, locale))) {
      return;
    }

    try {
      if (sub === 'end') {
        const id = interaction.options.getString('id', true).trim();
        const giveaway = await context.prisma.giveaway.findUnique({ where: { id } });
        if (!giveaway || giveaway.guildId !== interaction.guildId) {
          throw new GiveawayError('not_found');
        }
        await interaction.deferReply({ ephemeral: true });
        await cancelGiveawayJob(id);
        await endGiveaway(context, id);
        await interaction.editReply({ content: t(locale, 'giveaway.ended') });
        return;
      }

      if (sub === 'reroll') {
        const id = interaction.options.getString('id', true).trim();
        const existing = await context.prisma.giveaway.findUnique({ where: { id } });
        if (!existing || existing.guildId !== interaction.guildId) {
          throw new GiveawayError('not_found');
        }
        await interaction.deferReply({ ephemeral: true });
        const updated = await rerollGiveaway(context, id, locale);
        await interaction.editReply({
          content: tf(locale, 'giveaway.rerolled', {
            winners: updated.winners.map((w) => `<@${w}>`).join(', ') || '—'
          })
        });
        return;
      }

      if (sub === 'list') {
        const active = await listActiveGiveaways(context, interaction.guildId!);
        if (active.length === 0) {
          await interaction.reply({ content: t(locale, 'giveaway.list.empty'), ephemeral: true });
          return;
        }
        const lines = active.map(
          (g) =>
            `\`${g.id}\` — **${g.prize}** (${g.entrants.length} ${t(locale, 'giveaway.list.entrants')}, <t:${Math.floor(g.endsAt.getTime() / 1000)}:R>)`
        );
        await interaction.reply({
          content: `${t(locale, 'giveaway.list.header')}\n${lines.join('\n')}`,
          ephemeral: true
        });
        return;
      }

      if (sub === 'delete') {
        const id = interaction.options.getString('id', true).trim();
        const existing = await context.prisma.giveaway.findUnique({ where: { id } });
        if (!existing || existing.guildId !== interaction.guildId) {
          throw new GiveawayError('not_found');
        }
        await deleteGiveaway(context, id);
        await interaction.reply({ content: t(locale, 'giveaway.deleted'), ephemeral: true });
        return;
      }

      if (sub === 'pause') {
        const id = interaction.options.getString('id', true).trim();
        const existing = await context.prisma.giveaway.findUnique({ where: { id } });
        if (!existing || existing.guildId !== interaction.guildId) {
          throw new GiveawayError('not_found');
        }
        const updated = await pauseGiveaway(context, id, locale);
        await interaction.reply({
          content: t(locale, updated.paused ? 'giveaway.paused' : 'giveaway.resumed'),
          ephemeral: true
        });
      }
    } catch (error) {
      if (error instanceof GiveawayError) {
        await replyEphemeral(interaction, t(locale, `giveaway.error.${error.code}`));
        return;
      }
      throw error;
    }
  }
};

export const giveawayCommands = [giveawayCommand];
