import { PermissionFlagsBits, type ChatInputCommandInteraction } from 'discord.js';
import { t } from '@nexumi/shared';
import type { Locale } from '@nexumi/shared';

const PERMISSION_LABELS: Partial<Record<string, string>> = {
  [PermissionFlagsBits.Administrator.toString()]: 'Administrator',
  [PermissionFlagsBits.ManageGuild.toString()]: 'Manage Server',
  [PermissionFlagsBits.ManageChannels.toString()]: 'Manage Channels',
  [PermissionFlagsBits.ManageRoles.toString()]: 'Manage Roles',
  [PermissionFlagsBits.ManageMessages.toString()]: 'Manage Messages',
  [PermissionFlagsBits.ManageNicknames.toString()]: 'Manage Nicknames',
  [PermissionFlagsBits.ManageGuildExpressions.toString()]: 'Manage Expressions',
  [PermissionFlagsBits.KickMembers.toString()]: 'Kick Members',
  [PermissionFlagsBits.BanMembers.toString()]: 'Ban Members',
  [PermissionFlagsBits.ModerateMembers.toString()]: 'Timeout Members',
  [PermissionFlagsBits.ViewChannel.toString()]: 'View Channel',
  [PermissionFlagsBits.SendMessages.toString()]: 'Send Messages',
  [PermissionFlagsBits.EmbedLinks.toString()]: 'Embed Links',
  [PermissionFlagsBits.AttachFiles.toString()]: 'Attach Files',
  [PermissionFlagsBits.ReadMessageHistory.toString()]: 'Read Message History'
};

function permissionLabel(permission: bigint): string {
  return PERMISSION_LABELS[permission.toString()] ?? permission.toString();
}

export type RequirePermissionOptions = {
  /**
   * Discord permissions the bot itself must hold. Omit for dashboard-style
   * member gates (e.g. ManageGuild) where the bot does not need the same bit.
   */
  botPermissions?: bigint | readonly bigint[];
};

/**
 * Ensures the invoking member has `memberPermission`. Optionally also checks
 * that the bot has one or more `botPermissions` (moderation actions).
 */
export async function requirePermission(
  interaction: ChatInputCommandInteraction,
  memberPermission: bigint,
  locale: Locale,
  options?: RequirePermissionOptions
): Promise<boolean> {
  const member = interaction.memberPermissions;
  if (!member?.has(memberPermission)) {
    await interaction.reply({
      content: t(locale, 'generic.noPermission'),
      ephemeral: true
    });
    return false;
  }

  const botBits = options?.botPermissions;
  if (botBits === undefined) {
    return true;
  }

  const required = Array.isArray(botBits) ? botBits : [botBits];
  const me = interaction.guild?.members.me;
  if (!me) {
    await interaction.reply({
      content: t(locale, 'generic.botMissingPermission').replace(
        '{permission}',
        required.map(permissionLabel).join(', ')
      ),
      ephemeral: true
    });
    return false;
  }

  for (const bit of required) {
    if (!me.permissions.has(bit)) {
      await interaction.reply({
        content: t(locale, 'generic.botMissingPermission').replace(
          '{permission}',
          permissionLabel(bit)
        ),
        ephemeral: true
      });
      return false;
    }
  }

  return true;
}
