import {
  ActionRowBuilder,
  ButtonBuilder,
  ButtonStyle,
  type ButtonInteraction,
  type ChatInputCommandInteraction
} from 'discord.js';
import { randomUUID } from 'node:crypto';
import { type Locale, t, tf } from '@nexumi/shared';
import type { BotContext } from '../../types.js';
import { getGuildLocale } from '../../i18n.js';
import {
  deleteConfirmation,
  getConfirmation,
  setConfirmation,
  takeConfirmation
} from '../../confirmation-store.js';
import { executeBan, executeCaseDelete, executePurge } from './actions.js';

const CONFIRM_PREFIX = 'mod:confirm:';
const CANCEL_PREFIX = 'mod:cancel:';
const NAMESPACE = 'moderation';
const TTL_SECONDS = 60;

type BanPayload = {
  userId: string;
  reason: string;
  duration: string | null;
};

type PurgePayload = {
  channelId: string;
  amount: number;
  targetUserId: string | null;
  botsOnly: boolean;
  linksOnly: boolean;
  attachmentsOnly: boolean;
  regex: string | null;
};

type CaseDeletePayload = {
  caseNumber: number;
};

type PendingConfirmation =
  | { action: 'ban'; payload: BanPayload }
  | { action: 'purge'; payload: PurgePayload }
  | { action: 'case_delete'; payload: CaseDeletePayload };

type PendingEntry = PendingConfirmation & {
  moderatorId: string;
  guildId: string;
  locale: Locale;
};

function confirmationMessage(locale: Locale, entry: PendingConfirmation): string {
  if (entry.action === 'ban') {
    return tf(locale, 'moderation.confirm.ban', {
      userId: entry.payload.userId,
      reason: entry.payload.reason,
      duration: entry.payload.duration ?? t(locale, 'moderation.confirm.permanent')
    });
  }
  if (entry.action === 'purge') {
    return tf(locale, 'moderation.confirm.purge', { amount: entry.payload.amount });
  }
  return tf(locale, 'moderation.confirm.caseDelete', { caseNumber: entry.payload.caseNumber });
}

function buildRows(token: string, locale: Locale): ActionRowBuilder<ButtonBuilder>[] {
  return [
    new ActionRowBuilder<ButtonBuilder>().addComponents(
      new ButtonBuilder()
        .setCustomId(`${CONFIRM_PREFIX}${token}`)
        .setLabel(t(locale, 'moderation.confirm.button.confirm'))
        .setStyle(ButtonStyle.Danger),
      new ButtonBuilder()
        .setCustomId(`${CANCEL_PREFIX}${token}`)
        .setLabel(t(locale, 'moderation.confirm.button.cancel'))
        .setStyle(ButtonStyle.Secondary)
    )
  ];
}

export async function promptDestructiveConfirmation(
  interaction: ChatInputCommandInteraction,
  context: BotContext,
  locale: Locale,
  entry: PendingConfirmation
): Promise<void> {
  const token = randomUUID();
  await setConfirmation(
    context.redis,
    NAMESPACE,
    token,
    {
      ...entry,
      moderatorId: interaction.user.id,
      guildId: interaction.guildId!,
      locale
    } satisfies PendingEntry,
    TTL_SECONDS
  );

  await interaction.reply({
    content: confirmationMessage(locale, entry),
    components: buildRows(token, locale),
    ephemeral: true
  });
}

export async function handleModerationConfirmation(
  interaction: ButtonInteraction,
  context: BotContext
): Promise<void> {
  const customId = interaction.customId;
  const isConfirm = customId.startsWith(CONFIRM_PREFIX);
  const isCancel = customId.startsWith(CANCEL_PREFIX);
  if (!isConfirm && !isCancel) {
    return;
  }

  const token = customId.slice(isConfirm ? CONFIRM_PREFIX.length : CANCEL_PREFIX.length);
  const peeked = await getConfirmation<PendingEntry>(context.redis, NAMESPACE, token);
  if (!peeked) {
    const locale = await getGuildLocale(context.prisma, interaction.guildId);
    await interaction.reply({ content: t(locale, 'moderation.confirm.expired'), ephemeral: true });
    return;
  }

  if (interaction.user.id !== peeked.moderatorId) {
    await interaction.reply({
      content: t(peeked.locale, 'moderation.confirm.unauthorized'),
      ephemeral: true
    });
    return;
  }

  if (isCancel) {
    await deleteConfirmation(context.redis, NAMESPACE, token);
    await interaction.update({
      content: t(peeked.locale, 'moderation.confirm.cancelled'),
      components: []
    });
    return;
  }

  const entry = await takeConfirmation<PendingEntry>(context.redis, NAMESPACE, token);
  if (!entry) {
    const locale = await getGuildLocale(context.prisma, interaction.guildId);
    await interaction.reply({ content: t(locale, 'moderation.confirm.expired'), ephemeral: true });
    return;
  }

  if (entry.action === 'ban') {
    await executeBan(interaction, context, entry.locale, entry.payload);
    return;
  }

  if (entry.action === 'purge') {
    await executePurge(interaction, context, entry.locale, entry.payload);
    return;
  }

  await executeCaseDelete(interaction, context, entry.locale, entry.payload);
}

export function isModerationConfirmation(customId: string): boolean {
  return customId.startsWith(CONFIRM_PREFIX) || customId.startsWith(CANCEL_PREFIX);
}
