import {
  PermissionFlagsBits,
  SlashCommandBuilder,
  type SlashCommandStringOption,
  type SlashCommandUserOption
} from 'discord.js';
import {
  applyCommandDescription,
  applyOptionDescription,
  localizedChoice,
  type CommandLocaleKey
} from '@nexumi/shared';

function userOpt(
  o: SlashCommandUserOption,
  key: CommandLocaleKey = 'moderation.common.options.user'
) {
  return applyOptionDescription(o.setName('user').setRequired(true), key);
}

function reasonOpt(o: SlashCommandStringOption, required = false) {
  const option = o.setName('reason');
  if (required) {
    option.setRequired(true);
  }
  return applyOptionDescription(option, 'moderation.common.options.reason');
}

export const banCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('ban')
    .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers),
  'moderation.ban.description'
)
  .addUserOption((o) => userOpt(o, 'moderation.ban.options.user'))
  .addStringOption((o) => reasonOpt(o))
  .addStringOption((o) =>
    applyOptionDescription(o.setName('duration'), 'moderation.ban.options.duration')
  );

export const unbanCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('unban')
    .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers),
  'moderation.unban.description'
)
  .addStringOption((o) =>
    applyOptionDescription(o.setName('user_id').setRequired(true), 'moderation.unban.options.user_id')
  )
  .addStringOption((o) => reasonOpt(o));

export const kickCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('kick')
    .setDefaultMemberPermissions(PermissionFlagsBits.KickMembers),
  'moderation.kick.description'
)
  .addUserOption((o) => userOpt(o, 'moderation.ban.options.user'))
  .addStringOption((o) => reasonOpt(o));

export const timeoutCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('timeout')
    .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
  'moderation.timeout.description'
)
  .addUserOption((o) => userOpt(o, 'moderation.ban.options.user'))
  .addStringOption((o) =>
    applyOptionDescription(o.setName('duration').setRequired(true), 'moderation.timeout.options.duration')
  )
  .addStringOption((o) => reasonOpt(o));

export const untimeoutCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('untimeout')
    .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
  'moderation.untimeout.description'
)
  .addUserOption((o) => userOpt(o, 'moderation.ban.options.user'))
  .addStringOption((o) => reasonOpt(o));

export const warnCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('warn')
    .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
  'moderation.warn.description'
)
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('add'), 'moderation.warn.add.description')
      .addUserOption((o) => userOpt(o, 'moderation.common.options.target'))
      .addStringOption((o) => reasonOpt(o, true))
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('list'), 'moderation.warn.list.description').addUserOption((o) =>
      userOpt(o, 'moderation.common.options.target')
    )
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('remove'), 'moderation.warn.remove.description').addStringOption(
      (o) =>
        applyOptionDescription(o.setName('warning_id').setRequired(true), 'moderation.warn.options.warning_id')
    )
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('clear'), 'moderation.warn.clear.description').addUserOption((o) =>
      userOpt(o, 'moderation.common.options.target')
    )
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('escalation-set'), 'moderation.warn.escalation_set.description')
      .addIntegerOption((o) =>
        applyOptionDescription(o.setName('count').setRequired(true).setMinValue(1).setMaxValue(50), 'moderation.warn.options.count')
      )
      .addStringOption((o) =>
        applyOptionDescription(o.setName('action').setRequired(true), 'moderation.warn.options.action').addChoices(
          localizedChoice('moderation.choice.timeout', 'TIMEOUT'),
          localizedChoice('moderation.choice.kick', 'KICK'),
          localizedChoice('moderation.choice.ban', 'BAN')
        )
      )
      .addStringOption((o) =>
        applyOptionDescription(o.setName('duration'), 'moderation.warn.options.escalation_duration')
      )
      .addStringOption((o) =>
        applyOptionDescription(o.setName('reason'), 'moderation.warn.options.escalation_reason')
      )
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('escalation-list'), 'moderation.warn.escalation_list.description')
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('escalation-remove'), 'moderation.warn.escalation_remove.description').addIntegerOption(
      (o) =>
        applyOptionDescription(o.setName('count').setRequired(true).setMinValue(1).setMaxValue(50), 'moderation.warn.options.count')
    )
  );

export const purgeCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('purge')
    .setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
  'moderation.purge.description'
)
  .addIntegerOption((o) =>
    applyOptionDescription(o.setName('amount').setRequired(true).setMinValue(2).setMaxValue(100), 'moderation.purge.options.amount')
  )
  .addUserOption((o) => applyOptionDescription(o.setName('user'), 'moderation.purge.options.user'))
  .addBooleanOption((o) => applyOptionDescription(o.setName('bots'), 'moderation.purge.options.bots'))
  .addBooleanOption((o) => applyOptionDescription(o.setName('links'), 'moderation.purge.options.links'))
  .addBooleanOption((o) =>
    applyOptionDescription(o.setName('attachments'), 'moderation.purge.options.attachments')
  )
  .addStringOption((o) => applyOptionDescription(o.setName('regex'), 'moderation.purge.options.regex'));

export const slowmodeCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('slowmode')
    .setDefaultMemberPermissions(PermissionFlagsBits.ManageChannels),
  'moderation.slowmode.description'
).addIntegerOption((o) =>
  applyOptionDescription(o.setName('seconds').setRequired(true).setMinValue(0).setMaxValue(21600), 'moderation.slowmode.options.seconds')
);

export const lockCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('lock')
    .setDefaultMemberPermissions(PermissionFlagsBits.ManageChannels)
    .addBooleanOption((o) =>
      applyOptionDescription(o.setName('server'), 'moderation.lock.options.server')
    ),
  'moderation.lock.description'
);

export const unlockCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('unlock')
    .setDefaultMemberPermissions(PermissionFlagsBits.ManageChannels)
    .addBooleanOption((o) =>
      applyOptionDescription(o.setName('server'), 'moderation.unlock.options.server')
    ),
  'moderation.unlock.description'
);

export const nickCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('nick')
    .setDefaultMemberPermissions(PermissionFlagsBits.ManageNicknames),
  'moderation.nick.description'
)
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('set'), 'moderation.nick.set.description')
      .addUserOption((o) => userOpt(o, 'moderation.common.options.target'))
      .addStringOption((o) =>
        applyOptionDescription(o.setName('nickname').setRequired(true), 'moderation.nick.options.nickname')
      )
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('reset'), 'moderation.nick.reset.description').addUserOption((o) =>
      userOpt(o, 'moderation.common.options.target')
    )
  );

export const caseCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('case')
    .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
  'moderation.case.description'
)
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('view'), 'moderation.case.view.description').addIntegerOption((o) =>
      applyOptionDescription(o.setName('id').setRequired(true), 'moderation.case.options.id')
    )
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('edit'), 'moderation.case.edit.description')
      .addIntegerOption((o) =>
        applyOptionDescription(o.setName('id').setRequired(true), 'moderation.case.options.id')
      )
      .addStringOption((o) =>
        applyOptionDescription(o.setName('reason').setRequired(true), 'moderation.case.options.reason')
      )
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('delete'), 'moderation.case.delete.description').addIntegerOption((o) =>
      applyOptionDescription(o.setName('id').setRequired(true), 'moderation.case.options.id')
    )
  );

export const modNoteCommandData = applyCommandDescription(
  new SlashCommandBuilder()
    .setName('modnote')
    .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
  'moderation.modnote.description'
)
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('add'), 'moderation.modnote.add.description')
      .addUserOption((o) => userOpt(o, 'moderation.common.options.target'))
      .addStringOption((o) =>
        applyOptionDescription(o.setName('note').setRequired(true), 'moderation.modnote.options.note')
      )
  )
  .addSubcommand((s) =>
    applyCommandDescription(s.setName('list'), 'moderation.modnote.list.description').addUserOption((o) =>
      userOpt(o, 'moderation.common.options.target')
    )
  );
