import { Events, Interaction, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, ChannelType, VoiceChannel, PermissionFlagsBits, UserSelectMenuBuilder, GuildMember } from 'discord.js';
import { KordClient } from '../client/KordClient';
import { logger } from '../utils/logger';
import { prisma } from '../database';
import { BotError } from '../errors/BotError';
import { ErrorDefs, createBotError } from '../errors/ErrorCodes';
import { ErrorReporter, withErrorHandler } from '../errors/ErrorReporter';
import { t } from '../i18n';
import { getInteractionLocale } from '../i18n/localeHelper';
import { handleSetupWizardInteraction } from '../interactions/handlers/setupWizardHandler';
import { MusicService } from '../services/MusicService';

export default {
  name: Events.InteractionCreate,
  once: false,
  async execute(interaction: Interaction, client: KordClient) {
    if (interaction.isChatInputCommand()) {
      const command = client.commands.get(interaction.commandName);
      if (!command) return;

      // Acknowledge before locale DB reads so Discord's ~3s interaction window is never missed.
      await interaction.deferReply({ ephemeral: true });
      const locale = await getInteractionLocale(interaction);
      await withErrorHandler(interaction, async () => {
        await command.execute(interaction, locale);
      }, locale);
    } 
    else if (interaction.isButton() && interaction.customId.startsWith('music_')) {
      const locale = await getInteractionLocale(interaction);
      await withErrorHandler(interaction, async () => {
        await MusicService.handleControlInteraction(interaction, locale);
      }, locale);
    }
    else if (interaction.isButton() && interaction.customId.startsWith('fishing_')) {
      const { FishingService } = require('../services/FishingService');
      const locale = await getInteractionLocale(interaction);
      await withErrorHandler(interaction, async () => {
        await FishingService.handleButton(interaction, locale);
      }, locale);
    }
    else if (interaction.isMessageComponent() && interaction.customId.startsWith('setup_')) {
      const locale = await getInteractionLocale(interaction);
      await withErrorHandler(interaction, async () => {
        await handleSetupWizardInteraction(interaction, locale);
      }, locale);
    }
    else if (interaction.isButton() && interaction.customId.startsWith('refine_')) {
      const { handleRefinementInteraction } = require('../interactions/handlers/refinementHandler');
      const locale = await getInteractionLocale(interaction);
      await withErrorHandler(interaction, async () => {
        await handleRefinementInteraction(interaction, locale);
      }, locale);
    }
    else if (interaction.isStringSelectMenu()) {
      const customId = interaction.customId;
      
      if (customId.startsWith('vc_control_')) {
        const locale = await getInteractionLocale(interaction);
        await withErrorHandler(interaction, async () => {
          const parts = customId.split('_');
          const ownerId = parts[2];
          const action = interaction.values[0];

          if (interaction.user.id !== ownerId) {
            throw createBotError(ErrorDefs.NOT_CHANNEL_OWNER);
          }

          const member = interaction.member as GuildMember;
          const voiceChannel = member?.voice?.channel as VoiceChannel;
          
          if (!voiceChannel || interaction.channelId !== voiceChannel.id) {
            const tempDb = await prisma.tempVoiceChannel.findUnique({ where: { channelId: voiceChannel?.id || '' }});
            if (!tempDb || tempDb.ownerId !== ownerId) {
              throw createBotError(ErrorDefs.MUST_BE_IN_VOICE_CHANNEL);
            }
          }

          if (action === 'rename') {
            const modal = new ModalBuilder()
              .setCustomId(`modal_vc_rename_${ownerId}`)
              .setTitle(t(locale, 'modals.renameTitle'));
            
            const nameInput = new TextInputBuilder()
              .setCustomId('newName')
              .setLabel(t(locale, 'modals.renameLabel'))
              .setStyle(TextInputStyle.Short)
              .setValue(voiceChannel.name)
              .setRequired(true)
              .setMaxLength(100);

            modal.addComponents(new ActionRowBuilder<TextInputBuilder>().addComponents(nameInput));
            await interaction.showModal(modal);
          } 
          else if (action === 'limit') {
            const modal = new ModalBuilder()
              .setCustomId(`modal_vc_limit_${ownerId}`)
              .setTitle(t(locale, 'modals.limitTitle'));

            const limitInput = new TextInputBuilder()
              .setCustomId('limit')
              .setLabel(t(locale, 'modals.limitLabel'))
              .setStyle(TextInputStyle.Short)
              .setValue(voiceChannel.userLimit.toString())
              .setRequired(true)
              .setMaxLength(2);

            modal.addComponents(new ActionRowBuilder<TextInputBuilder>().addComponents(limitInput));
            await interaction.showModal(modal);
          }
          else if (action === 'lock') {
            const everyonePerms = voiceChannel.permissionOverwrites.cache.get(voiceChannel.guild.id);
            const isLocked = everyonePerms?.deny.has(PermissionFlagsBits.Connect);
            if (isLocked) {
              await voiceChannel.permissionOverwrites.edit(voiceChannel.guild.id, { Connect: null });
              await interaction.reply({ content: t(locale, 'voice.responses.channelUnlocked'), ephemeral: true });
            } else {
              await voiceChannel.permissionOverwrites.edit(voiceChannel.guild.id, { Connect: false });
              await interaction.reply({ content: t(locale, 'voice.responses.channelLocked'), ephemeral: true });
            }
          }
          else if (action === 'kick') {
            const select = new UserSelectMenuBuilder()
              .setCustomId(`select_vc_kick_${ownerId}`)
              .setPlaceholder(t(locale, 'selects.kickUser'))
              .setMinValues(1)
              .setMaxValues(1);
            await interaction.reply({ components: [new ActionRowBuilder<UserSelectMenuBuilder>().addComponents(select)], ephemeral: true });
          }
          else if (action === 'ban') {
            const select = new UserSelectMenuBuilder()
              .setCustomId(`select_vc_ban_${ownerId}`)
              .setPlaceholder(t(locale, 'selects.banUser'))
              .setMinValues(1)
              .setMaxValues(1);
            await interaction.reply({ content: t(locale, 'voice.responses.banPrompt'), components: [new ActionRowBuilder<UserSelectMenuBuilder>().addComponents(select)], ephemeral: true });
          }
          else if (action === 'transfer') {
            const select = new UserSelectMenuBuilder()
              .setCustomId(`select_vc_transfer_${ownerId}`)
              .setPlaceholder(t(locale, 'selects.transferOwner'))
              .setMinValues(1)
              .setMaxValues(1);
            await interaction.reply({ content: t(locale, 'voice.responses.transferPrompt'), components: [new ActionRowBuilder<UserSelectMenuBuilder>().addComponents(select)], ephemeral: true });
          }
        }, locale);
      }
    }
    else if (interaction.isButton() && interaction.customId.startsWith('autorole_')) {
      const locale = await getInteractionLocale(interaction);
      const { autoRoleService } = require('../services/AutoRoleService');
      await withErrorHandler(interaction, async () => {
        // 타임아웃 방지를 위해 즉시 승인
        await interaction.deferUpdate();
        
        // 나머지 버튼 처리 (현재 사용 안함)
      }, locale);
    }
    else if (interaction.isRoleSelectMenu() && interaction.customId.startsWith('autorole_select_')) {
      const locale = await getInteractionLocale(interaction);
      const { autoRoleService } = require('../services/AutoRoleService');
      await withErrorHandler(interaction, async () => {
        // 타임아웃 방지를 위해 즉시 승인
        await interaction.deferUpdate();

        const guild = interaction.guild!;
        const isBot = interaction.customId.includes('bot');
        const roleIds = interaction.values;
        
        await autoRoleService.updateConfig(guild.id, {
          [isBot ? 'botRoleIds' : 'userRoleIds']: roleIds
        });

        const { generateAutoRoleDashboard } = require('../commands/autorole');
        const dashboard = await generateAutoRoleDashboard(guild, locale);

        await interaction.editReply({ 
          content: '', 
          ...dashboard
        });
      }, locale);
    }
    else if (interaction.isModalSubmit()) {
      const customId = interaction.customId;
      if (customId.startsWith('modal_vc_')) {
        const locale = await getInteractionLocale(interaction);
        await withErrorHandler(interaction, async () => {
          const parts = customId.split('_');
          const action = parts[2];
          const ownerId = parts[3];

          if (interaction.user.id !== ownerId) {
            throw createBotError(ErrorDefs.NOT_CHANNEL_OWNER);
          }

          const member = interaction.member as GuildMember;
          const voiceChannel = member?.voice?.channel as VoiceChannel;
          if (!voiceChannel) {
            throw createBotError(ErrorDefs.MUST_BE_IN_VOICE_CHANNEL);
          }

          if (action === 'rename') {
            const newName = interaction.fields.getTextInputValue('newName');
            await voiceChannel.setName(newName);
            
            await prisma.userVoiceProfile.upsert({
              where: { userId_guildId: { userId: ownerId, guildId: interaction.guildId! } },
              update: { customName: newName },
              create: { userId: ownerId, guildId: interaction.guildId!, customName: newName }
            });

            await interaction.reply({ content: t(locale, 'voice.responses.channelRenamed', { name: newName }), ephemeral: true });
          }
          else if (action === 'limit') {
            const limitStr = interaction.fields.getTextInputValue('limit');
            const limit = parseInt(limitStr);
            if (isNaN(limit) || limit < 0 || limit > 99) {
              throw createBotError(ErrorDefs.INVALID_USER_LIMIT);
            }
            await voiceChannel.setUserLimit(limit);

            await prisma.userVoiceProfile.upsert({
              where: { userId_guildId: { userId: ownerId, guildId: interaction.guildId! } },
              update: { userLimit: limit },
              create: { userId: ownerId, guildId: interaction.guildId!, userLimit: limit }
            });

            const limitDisplay = limit === 0 ? t(locale, 'voice.responses.limitUnlimited') : String(limit);
            await interaction.reply({ content: t(locale, 'voice.responses.limitSet', { limit: limitDisplay }), ephemeral: true });
          }
        }, locale);
      }
    }
    else if (interaction.isUserSelectMenu()) {
      const customId = interaction.customId;
      if (customId.startsWith('select_vc_')) {
        const locale = await getInteractionLocale(interaction);
        await withErrorHandler(interaction, async () => {
          const parts = customId.split('_');
          const action = parts[2];
          const ownerId = parts[3];

          if (interaction.user.id !== ownerId) {
            throw createBotError(ErrorDefs.NOT_CHANNEL_OWNER);
          }
          
          const member = interaction.member as GuildMember;
          const voiceChannel = member?.voice?.channel as VoiceChannel;
          if (!voiceChannel) {
            throw createBotError(ErrorDefs.MUST_BE_IN_VOICE_CHANNEL);
          }

          const targetUserId = interaction.values[0];
          if (targetUserId === ownerId) {
            throw createBotError(ErrorDefs.SELF_TARGET_NOT_ALLOWED);
          }

          if (action === 'kick') {
            const targetMember = await interaction.guild?.members.fetch(targetUserId);
            if (targetMember && targetMember.voice.channelId === voiceChannel.id) {
              await targetMember.voice.disconnect('Kicked by channel owner');
              await interaction.reply({ content: t(locale, 'voice.responses.kicked', { user: `<@${targetUserId}>` }), ephemeral: true });
            } else {
              throw createBotError(ErrorDefs.USER_NOT_IN_CHANNEL);
            }
          }
          else if (action === 'ban') {
            await voiceChannel.permissionOverwrites.edit(targetUserId, {
              ViewChannel: false,
              Connect: false
            });
            
            const targetMember = await interaction.guild?.members.fetch(targetUserId);
            if (targetMember && targetMember.voice.channelId === voiceChannel.id) {
              await targetMember.voice.disconnect('Banned by channel owner');
            }

            await interaction.reply({ content: t(locale, 'voice.responses.banned', { user: `<@${targetUserId}>` }), ephemeral: true });
          }
          else if (action === 'transfer') {
            const targetMember = await interaction.guild?.members.fetch(targetUserId);
            if (targetMember && targetMember.voice.channelId === voiceChannel.id) {
              await prisma.tempVoiceChannel.update({
                where: { channelId: voiceChannel.id },
                data: { ownerId: targetUserId }
              });

              const { VoiceService } = require('../services/VoiceService');
              await VoiceService.applyOwnershipTransfer(voiceChannel, ownerId, targetUserId);
              await interaction.reply({ content: t(locale, 'voice.responses.transferDone', { user: `<@${targetUserId}>` }), ephemeral: true });
            } else {
              throw createBotError(ErrorDefs.USER_NOT_IN_CHANNEL);
            }
          }
        }, locale);
      }
    }
  },
};
