import type { ButtonInteraction } from 'discord.js';
import { t } from '@nexumi/shared';
import type { BotContext } from '../../types.js';
import { getGuildLocale } from '../../i18n.js';
import {
  applyConnect4Move,
  applyHangmanGuess,
  applyTicTacToeMove,
  buildConnect4Components,
  buildConnect4Embed,
  buildHangmanComponents,
  buildHangmanEmbed,
  buildTicTacToeComponents,
  buildTicTacToeEmbed,
  currentConnect4PlayerId,
  currentTicTacToePlayerId,
  deleteConnect4State,
  deleteHangmanState,
  deleteTicTacToeState,
  deleteTriviaSession,
  FUN_BUTTON_PREFIX,
  loadConnect4State,
  loadHangmanState,
  loadTicTacToeState,
  loadTriviaSession,
  parseConnect4Button,
  parseHangmanButton,
  parseTicTacToeButton,
  parseTriviaButton,
  saveConnect4State,
  saveHangmanState,
  saveTicTacToeState
} from './games.js';

export function isFunButton(customId: string): boolean {
  return customId.startsWith(FUN_BUTTON_PREFIX);
}

async function replyNotParticipant(interaction: ButtonInteraction, locale: 'de' | 'en'): Promise<void> {
  await interaction.reply({ content: t(locale, 'fun.common.notParticipant'), ephemeral: true });
}

async function replyExpired(interaction: ButtonInteraction, locale: 'de' | 'en'): Promise<void> {
  await interaction.reply({ content: t(locale, 'fun.common.expired'), ephemeral: true });
}

async function handleTriviaButton(
  interaction: ButtonInteraction,
  context: BotContext,
  locale: 'de' | 'en'
): Promise<void> {
  const parsed = parseTriviaButton(interaction.customId);
  if (!parsed) {
    await replyExpired(interaction, locale);
    return;
  }

  if (interaction.user.id !== parsed.userId) {
    await interaction.reply({ content: t(locale, 'fun.trivia.notOwner'), ephemeral: true });
    return;
  }

  const session = await loadTriviaSession(context, parsed.userId);
  if (!session) {
    await replyExpired(interaction, locale);
    return;
  }

  const correct = parsed.answerIndex === parsed.correctIndex;
  await deleteTriviaSession(context, parsed.userId);

  await interaction.update({
    embeds: interaction.message.embeds,
    components: [],
    content: correct ? t(locale, 'fun.trivia.correct') : t(locale, 'fun.trivia.incorrect')
  });
}

async function handleTicTacToeButton(
  interaction: ButtonInteraction,
  context: BotContext,
  locale: 'de' | 'en'
): Promise<void> {
  const parsed = parseTicTacToeButton(interaction.customId);
  if (!parsed) {
    await replyExpired(interaction, locale);
    return;
  }

  const state = await loadTicTacToeState(context, parsed.gameId);
  if (!state || state.status !== 'active') {
    await replyExpired(interaction, locale);
    return;
  }

  if (interaction.user.id !== currentTicTacToePlayerId(state)) {
    await replyNotParticipant(interaction, locale);
    return;
  }

  const next = applyTicTacToeMove(state, parsed.cell);
  if (next.board[parsed.cell] === state.board[parsed.cell]) {
    await interaction.reply({ content: t(locale, 'fun.tictactoe.invalidMove'), ephemeral: true });
    return;
  }

  if (next.status !== 'active') {
    await deleteTicTacToeState(context, parsed.gameId);
  } else {
    await saveTicTacToeState(context, next);
  }

  await interaction.update({
    embeds: [buildTicTacToeEmbed(locale, next)],
    components: buildTicTacToeComponents(next)
  });
}

async function handleConnect4Button(
  interaction: ButtonInteraction,
  context: BotContext,
  locale: 'de' | 'en'
): Promise<void> {
  const parsed = parseConnect4Button(interaction.customId);
  if (!parsed) {
    await replyExpired(interaction, locale);
    return;
  }

  const state = await loadConnect4State(context, parsed.gameId);
  if (!state || state.status !== 'active') {
    await replyExpired(interaction, locale);
    return;
  }

  if (interaction.user.id !== currentConnect4PlayerId(state)) {
    await replyNotParticipant(interaction, locale);
    return;
  }

  const next = applyConnect4Move(state, parsed.col);
  const changed = next.board.some((row, rowIndex) =>
    row.some((cell, colIndex) => cell !== state.board[rowIndex]![colIndex])
  );
  if (!changed) {
    await interaction.reply({ content: t(locale, 'fun.connect4.invalidMove'), ephemeral: true });
    return;
  }

  if (next.status !== 'active') {
    await deleteConnect4State(context, parsed.gameId);
  } else {
    await saveConnect4State(context, next);
  }

  await interaction.update({
    embeds: [buildConnect4Embed(locale, next)],
    components: buildConnect4Components(next)
  });
}

async function handleHangmanButton(
  interaction: ButtonInteraction,
  context: BotContext,
  locale: 'de' | 'en'
): Promise<void> {
  const parsed = parseHangmanButton(interaction.customId);
  if (!parsed) {
    await replyExpired(interaction, locale);
    return;
  }

  const state = await loadHangmanState(context, parsed.gameId);
  if (!state) {
    await replyExpired(interaction, locale);
    return;
  }

  if (interaction.user.id !== state.userId) {
    await replyNotParticipant(interaction, locale);
    return;
  }

  if (parsed.page !== undefined) {
    const next = { ...state, letterPage: parsed.page };
    await saveHangmanState(context, next);
    await interaction.update({
      embeds: [buildHangmanEmbed(locale, next)],
      components: buildHangmanComponents(next)
    });
    return;
  }

  if (!parsed.letter || state.status !== 'active') {
    await replyExpired(interaction, locale);
    return;
  }

  const next = applyHangmanGuess(state, parsed.letter);
  if (next.status !== 'active') {
    await deleteHangmanState(context, parsed.gameId);
  } else {
    await saveHangmanState(context, next);
  }

  await interaction.update({
    embeds: [buildHangmanEmbed(locale, next)],
    components: buildHangmanComponents(next)
  });
}

export async function handleFunButton(interaction: ButtonInteraction, context: BotContext): Promise<void> {
  const locale = await getGuildLocale(context.prisma, interaction.guildId);
  const parts = interaction.customId.split(':');

  if (parts[1] === 'trivia') {
    await handleTriviaButton(interaction, context, locale);
    return;
  }
  if (parts[1] === 'ttt') {
    await handleTicTacToeButton(interaction, context, locale);
    return;
  }
  if (parts[1] === 'c4') {
    await handleConnect4Button(interaction, context, locale);
    return;
  }
  if (parts[1] === 'hm') {
    await handleHangmanButton(interaction, context, locale);
    return;
  }

  await replyExpired(interaction, locale);
}
