import {
  ActionRowBuilder,
  ButtonBuilder,
  ButtonStyle,
  EmbedBuilder,
  PermissionFlagsBits,
  type ButtonInteraction,
  type GuildMember
} from 'discord.js';
import { t, tf } from '@nexumi/shared';
import type { BotContext } from '../../types.js';
import { getGuildLocale } from '../../i18n.js';
import {
  accountAgeDays,
  createCaptchaChallenge,
  getVerificationConfig,
  parseVerificationButton,
  verificationButtonId,
  verificationCaptchaButtonId
} from './service.js';
import { env } from '../../env.js';
import { logger } from '../../logger.js';

async function applyFailAction(
  member: GuildMember,
  failAction: string,
  reason: string
): Promise<void> {
  const me = member.guild.members.me;
  if (failAction === 'KICK' && me?.permissions.has(PermissionFlagsBits.KickMembers)) {
    await member.kick(reason);
    return;
  }
  if (failAction === 'BAN' && me?.permissions.has(PermissionFlagsBits.BanMembers)) {
    await member.guild.members.ban(member.id, { reason });
  }
}

export async function completeVerification(
  context: BotContext,
  guildId: string,
  userId: string
): Promise<{ ok: boolean; reason?: string }> {
  const config = await getVerificationConfig(context.prisma, guildId);
  if (!config.enabled || !config.verifiedRoleId) {
    return { ok: false, reason: 'not_configured' };
  }

  const guild = await context.client.guilds.fetch(guildId);
  const member = await guild.members.fetch(userId).catch(() => null);
  if (!member) {
    return { ok: false, reason: 'member_not_found' };
  }

  const ageDays = accountAgeDays(member.user.createdAt);
  if (config.minAccountAgeDays > 0 && ageDays < config.minAccountAgeDays) {
    await applyFailAction(
      member,
      config.failAction,
      `Verification failed: account too young (${ageDays}d)`
    );
    return { ok: false, reason: 'account_too_young' };
  }

  const me = guild.members.me;
  if (!me?.permissions.has(PermissionFlagsBits.ManageRoles)) {
    return { ok: false, reason: 'missing_permissions' };
  }

  const verifiedRole = guild.roles.cache.get(config.verifiedRoleId);
  if (!verifiedRole || verifiedRole.position >= me.roles.highest.position) {
    return { ok: false, reason: 'invalid_role' };
  }

  if (config.unverifiedRoleId && member.roles.cache.has(config.unverifiedRoleId)) {
    await member.roles.remove(config.unverifiedRoleId).catch((error) => {
      logger.warn({ error }, 'Failed to remove unverified role');
    });
  }

  if (!member.roles.cache.has(config.verifiedRoleId)) {
    await member.roles.add(config.verifiedRoleId);
  }

  return { ok: true };
}

export function buildVerificationPanel(config: Awaited<ReturnType<typeof getVerificationConfig>>) {
  const embed = new EmbedBuilder()
    .setTitle('Verification')
    .setDescription('Click the button below to verify and gain access to the server.')
    .setColor(0x6366f1);

  const customId =
    config.mode === 'CAPTCHA'
      ? verificationCaptchaButtonId(config.guildId)
      : verificationButtonId(config.guildId);

  const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
    new ButtonBuilder()
      .setCustomId(customId)
      .setLabel(config.mode === 'CAPTCHA' ? 'Verify (Captcha)' : 'Verify')
      .setStyle(ButtonStyle.Success)
  );

  return { embeds: [embed], components: [row] };
}

export async function handleVerificationButton(
  interaction: ButtonInteraction,
  context: BotContext
): Promise<void> {
  const parsed = parseVerificationButton(interaction.customId);
  if (!parsed || !interaction.guild) {
    return;
  }

  const locale = await getGuildLocale(context.prisma, interaction.guild.id);
  const config = await getVerificationConfig(context.prisma, parsed.guildId);

  if (!config.enabled) {
    await interaction.reply({ content: t(locale, 'verification.disabled'), ephemeral: true });
    return;
  }

  if (parsed.mode === 'captcha') {
    const challenge = await createCaptchaChallenge(
      context.redis,
      parsed.guildId,
      interaction.user.id
    );
    const url = `${env.PUBLIC_BASE_URL}/verify/captcha?token=${challenge.token}`;
    await interaction.reply({
      content: tf(locale, 'verification.captchaLink', { url }),
      ephemeral: true
    });
    return;
  }

  await interaction.deferReply({ ephemeral: true });
  const result = await completeVerification(context, parsed.guildId, interaction.user.id);
  if (result.ok) {
    await interaction.editReply({ content: t(locale, 'verification.success') });
    return;
  }

  const key = `verification.error.${result.reason ?? 'generic'}`;
  await interaction.editReply({ content: t(locale, key) });
}
