import {
  ChannelType,
  ChatInputCommandInteraction,
  EmbedBuilder,
  SlashCommandBuilder,
} from 'discord.js';
import { prisma } from '../database';
import { SupportedLocale, t } from '../i18n';
import { FishingService } from '../services/FishingService';

export default {
  data: new SlashCommandBuilder()
    .setName('fishing')
    .setDescription('Play the fishing mini-game.')
    .setDescriptionLocalizations({
      ko: '낚시 미니게임을 플레이합니다.',
    })
    .addSubcommand((subcommand) =>
      subcommand
        .setName('enter')
        .setDescription('Create or reopen your fishing thread.')
        .setDescriptionLocalizations({
          ko: '낚시 전용 스레드를 생성하거나 다시 엽니다.',
        }),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName('cast')
        .setDescription('Start a fishing session inside your fishing thread.')
        .setDescriptionLocalizations({
          ko: '자신의 낚시 스레드 안에서 낚시 세션을 시작합니다.',
        }),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName('end')
        .setDescription('End your active fishing session and delete the thread.')
        .setDescriptionLocalizations({
          ko: '진행 중인 낚시 세션을 종료하고 스레드를 삭제합니다.',
        }),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName('status')
        .setDescription('View fishing statistics.')
        .setDescriptionLocalizations({
          ko: '낚시 통계를 확인합니다.',
        })
        .addUserOption((option) =>
          option
            .setName('user')
            .setDescription('User to view')
            .setDescriptionLocalizations({
              ko: '조회할 유저',
            }),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName('dex')
        .setDescription('View your fishing collection book.')
        .setDescriptionLocalizations({
          ko: '낚시 도감을 확인합니다.',
        })
        .addUserOption((option) =>
          option
            .setName('user')
            .setDescription('User to view')
            .setDescriptionLocalizations({
              ko: '조회할 유저',
            }),
        ),
    )
    .addSubcommand((subcommand) =>
      subcommand
        .setName('ranking')
        .setDescription('View the biggest fish size ranking in this server.')
        .setDescriptionLocalizations({
          ko: '이 서버의 물고기 크기 랭킹을 확인합니다.',
        }),
    ),

  async execute(interaction: ChatInputCommandInteraction, locale: SupportedLocale) {
    if (!interaction.guildId) return;

    const config = await prisma.miniGameConfig.findUnique({
      where: { guildId_gameKey: { guildId: interaction.guildId, gameKey: 'fishing' } },
    });
    const subcommand = interaction.options.getSubcommand();

    if (subcommand === 'enter') {
      if (!config || !config.enabled) {
        await interaction.editReply({
          content: t(locale, 'commands.fishing.disabled'),
        });
        return;
      }

      if (config.channelId && config.channelId !== interaction.channelId) {
        await interaction.editReply({
          content: t(locale, 'commands.fishing.restrictedChannel', {
            channel: `<#${config.channelId}>`,
          }),
        });
        return;
      }

      if (!interaction.channel || interaction.channel.type !== ChannelType.GuildText) {
        await interaction.editReply({
          content: t(locale, 'commands.fishing.enterTextChannelOnly'),
        });
        return;
      }

      const result = await FishingService.enterThread(interaction);
      await interaction.editReply({
        content: result.existed
          ? t(locale, 'commands.fishing.enterExistingThread', { thread: `<#${result.thread.id}>` })
          : t(locale, 'commands.fishing.enterCreated', { thread: `<#${result.thread.id}>` }),
      });
      return;
    }

    if (subcommand === 'cast') {
      if (!config || !config.enabled) {
        await interaction.editReply({
          content: t(locale, 'commands.fishing.disabled'),
        });
        return;
      }

      if (!FishingService.isOwnedFishingThread(interaction.channel, interaction.user.username)) {
        await interaction.editReply({
          content: t(locale, 'commands.fishing.castThreadOnly'),
        });
        return;
      }

      const result = await FishingService.startSessionInThread(interaction, locale);
      await interaction.editReply({
        content: result.existed
          ? t(locale, 'commands.fishing.startExistingSession', { thread: `<#${result.thread.id}>` })
          : t(locale, 'commands.fishing.startCreated', { thread: `<#${result.thread.id}>` }),
      });
      return;
    }

    if (subcommand === 'end') {
      const ended = await FishingService.endThreadByUser(interaction, locale);
      if (!ended) {
        await interaction.editReply({
          content: t(locale, 'commands.fishing.noActiveSession'),
        });
        return;
      }

      await interaction.editReply({
        content: t(locale, 'commands.fishing.endDeleted'),
      });
      return;
    }

    if (subcommand === 'status') {
      const targetUser = interaction.options.getUser('user') ?? interaction.user;
      const profile = await FishingService.getProfile(targetUser.id, interaction.guildId);

      const totalCasts = profile?.totalCastCount ?? 0;
      const successCount = profile?.successCount ?? 0;
      const failCount = profile?.failCount ?? 0;
      const totalGoldEarned = profile?.totalGoldEarned ?? 0;
      const bestCatchReward = profile?.bestCatchReward ?? 0;
      const successRate = totalCasts > 0 ? ((successCount / totalCasts) * 100).toFixed(1) : '0.0';
      const rarityBreakdown = [
        `⚪ ${profile?.commonCatchCount ?? 0}`,
        `🟢 ${profile?.uncommonCatchCount ?? 0}`,
        `🔵 ${profile?.rareCatchCount ?? 0}`,
        `🟣 ${profile?.epicCatchCount ?? 0}`,
        `🟠 ${profile?.legendaryCatchCount ?? 0}`,
      ].join('\n');

      const embed = new EmbedBuilder()
        .setColor(0x3b82f6)
        .setTitle(t(locale, 'commands.fishing.profileTitle', { user: targetUser.username }))
        .setThumbnail(targetUser.displayAvatarURL())
        .addFields(
          {
            name: t(locale, 'commands.fishing.totalCasts'),
            value: String(totalCasts),
            inline: true,
          },
          {
            name: t(locale, 'commands.fishing.successRate'),
            value: `${successRate}% (${successCount}/${successCount + failCount})`,
            inline: true,
          },
          {
            name: t(locale, 'commands.fishing.totalGoldEarned'),
            value: `${totalGoldEarned} G`,
            inline: true,
          },
          {
            name: t(locale, 'commands.fishing.bestCatchReward'),
            value: `${bestCatchReward} G`,
            inline: true,
          },
          {
            name: t(locale, 'commands.fishing.lastCastAt'),
            value: profile?.lastCastAt
              ? `<t:${Math.floor(profile.lastCastAt.getTime() / 1000)}:R>`
              : t(locale, 'commands.fishing.noRecord'),
            inline: true,
          },
          {
            name: t(locale, 'commands.fishing.rarityBreakdown'),
            value: rarityBreakdown,
            inline: false,
          },
        );

      if (!profile) {
        embed.setDescription(t(locale, 'commands.fishing.profileEmpty'));
      }

      await interaction.editReply({ embeds: [embed] });
      return;
    }

    if (subcommand === 'dex') {
      const targetUser = interaction.options.getUser('user') ?? interaction.user;
      const collection = await FishingService.getCollection(targetUser.id, interaction.guildId);

      const embed = new EmbedBuilder()
        .setColor(0x14b8a6)
        .setTitle(t(locale, 'commands.fishing.dexTitle', { user: targetUser.username }))
        .setThumbnail(targetUser.displayAvatarURL());

      if (!collection.length) {
        embed.setDescription(t(locale, 'commands.fishing.dexEmpty'));
        await interaction.editReply({ embeds: [embed] });
        return;
      }

      for (const entry of collection.slice(0, 10)) {
        const fishName = FishingService.getFishDisplayName(entry.fishId);
        const rarityName = FishingService.getRarityDisplayNameById(entry.bestRarityId, locale);
        embed.addFields({
          name: fishName,
          value: [
            `${t(locale, 'commands.fishing.catchCount')}: ${entry.catchCount}`,
            `${t(locale, 'commands.fishing.bestRarity')}: ${rarityName}`,
            `${t(locale, 'commands.fishing.bestSize')}: ${entry.bestSizeCm.toFixed(1)} cm`,
          ].join('\n'),
          inline: true,
        });
      }

      await interaction.editReply({ embeds: [embed] });
      return;
    }

    if (subcommand === 'ranking') {
      const ranking = await FishingService.getSizeRanking(interaction.guildId);

      const embed = new EmbedBuilder()
        .setColor(0xf59e0b)
        .setTitle(t(locale, 'commands.fishing.rankingTitle'));

      if (!ranking.length) {
        embed.setDescription(t(locale, 'commands.fishing.rankingEmpty'));
        await interaction.editReply({ embeds: [embed] });
        return;
      }

      for (const [index, entry] of ranking.entries()) {
        const fishName = FishingService.getFishDisplayName(entry.fishId);
        const rarityName = FishingService.getRarityDisplayNameById(entry.bestRarityId, locale);
        embed.addFields({
          name: `#${index + 1} <@${entry.userId}>`,
          value: [
            `${t(locale, 'commands.fishing.targetFish')}: ${fishName}`,
            `${t(locale, 'commands.fishing.rarity')}: ${rarityName}`,
            `${t(locale, 'commands.fishing.size')}: ${entry.bestSizeCm.toFixed(1)} cm`,
          ].join('\n'),
          inline: false,
        });
      }

      await interaction.editReply({ embeds: [embed] });
    }
  },
};
