import "dotenv/config";

import {
  Client,
  Events,
  GatewayIntentBits,
  type Interaction,
  type Message,
} from "discord.js";

import { loadConfig } from "./config.js";
import { handleTeamInteraction, handleTeamMessage } from "./discord/team-command.js";
import { registerCommands } from "./discord/register-commands.js";
import {
  closeStatusServer,
  createStatusServer,
  listenStatusServer,
} from "./http/status-server.js";

async function start(): Promise<void> {
  const config = loadConfig();
  const client = new Client({
    intents: [
      GatewayIntentBits.Guilds,
      GatewayIntentBits.GuildMessages,
      GatewayIntentBits.GuildVoiceStates,
      GatewayIntentBits.MessageContent,
    ],
  });
  const statusServer = createStatusServer(() => ({
    ready: client.isReady(),
    ...(client.user ? { botTag: client.user.tag } : {}),
  }));

  client.once(Events.ClientReady, (readyClient) => {
    console.log(`[접속 완료] ${readyClient.user.tag}`);
  });

  client.on(Events.InteractionCreate, async (interaction: Interaction) => {
    if (!interaction.isChatInputCommand()) {
      return;
    }

    try {
      await handleTeamInteraction(interaction);
    } catch (error) {
      console.error("slash 명령 처리 중 오류가 발생했습니다.", error);

      const response = { content: "명령 처리 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.", ephemeral: true };
      if (interaction.replied || interaction.deferred) {
        await interaction.followUp(response).catch(console.error);
      } else {
        await interaction.reply(response).catch(console.error);
      }
    }
  });

  client.on(Events.MessageCreate, async (message: Message) => {
    if (message.author.bot || !message.inGuild()) {
      return;
    }

    try {
      await handleTeamMessage(message, config.prefix);
    } catch (error) {
      console.error("메시지 명령 처리 중 오류가 발생했습니다.", error);
      await message
        .reply({
          content: "명령 처리 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.",
          allowedMentions: { repliedUser: false },
        })
        .catch(console.error);
    }
  });

  let shuttingDown = false;
  const shutdown = async (signal: string): Promise<void> => {
    if (shuttingDown) {
      return;
    }

    shuttingDown = true;
    console.log(`[종료] ${signal} 신호를 받아 Discord 연결을 닫습니다.`);
    client.destroy();
    await closeStatusServer(statusServer).catch(console.error);
    process.exit(0);
  };

  process.once("SIGINT", () => void shutdown("SIGINT"));
  process.once("SIGTERM", () => void shutdown("SIGTERM"));

  await registerCommands(config);
  await client.login(config.token);
  await listenStatusServer(statusServer, config.httpHost, config.port);
  console.log(`[HTTP 준비] http://${config.httpHost}:${config.port}`);
  process.send?.("ready");
}

start().catch((error: unknown) => {
  console.error("봇을 시작하지 못했습니다.", error);
  process.exit(1);
});
