const discord = require("discord.js");
const Client = discord.Client;
const GatewayIntentBits = discord.GatewayIntentBits;
const IntentsBitField = discord.IntentsBitField;
const Intents = discord.Intents;
const Partials = discord.Partials;
const { getSetting, setSetting } = require("./settings");
const { incrementMessages } = require("./stats");
const { ensureUserForIdentity } = require("./users");

let client = null;

async function startBot({ commandRouter } = {}) {
  const token = getSetting("discord_bot_token");
  if (!token) {
    return null;
  }

  const intents = [
    resolveIntent("Guilds", "GUILDS"),
    resolveIntent("GuildMessages", "GUILD_MESSAGES"),
    resolveIntent("GuildMembers", "GUILD_MEMBERS"),
    resolveIntent("MessageContent", "MESSAGE_CONTENT"),
    resolveIntent("GuildVoiceStates", "GUILD_VOICE_STATES"),
    resolveIntent("GuildPresences", "GUILD_PRESENCES")
  ].filter(Boolean);

  const options = {};
  if (intents.length) {
    options.intents = intents;
  }
  console.log("Discord bot starting with intents", {
    intents,
    guildMembers: Boolean(resolveIntent("GuildMembers", "GUILD_MEMBERS"))
  });
  if (Partials?.Channel) {
    options.partials = [Partials.Channel];
  }

  client = new Client(options);

  client.on("ready", () => {
    console.log(`Discord bot ready: ${client.user?.tag}`);
    const avatarUrl = getBotAvatarUrl(client.user);
    if (avatarUrl) {
      setSetting("bot_avatar_url", avatarUrl);
    }
  });

  client.on("messageCreate", async (message) => {
    if (!message.guild || message.author.bot) {
      return;
    }
    const displayName =
      message.author.globalName || message.author.username || message.author.tag;
    let avatarUrl = null;
    if (typeof message.author.displayAvatarURL === "function") {
      try {
        avatarUrl = message.author.displayAvatarURL({ format: "png", size: 128 });
      } catch {
        avatarUrl = message.author.displayAvatarURL();
      }
    }
    const profile = ensureUserForIdentity({
      provider: "discord",
      providerUserId: message.author.id,
      displayName,
      avatar: avatarUrl
    });
    incrementMessages(profile.id);

    if (commandRouter) {
      await commandRouter.handleMessage({
        platform: "discord",
        raw: message.content,
        user: profile,
        platformUser: {
          id: message.author.id,
          displayName,
          username: message.author.username,
          tag: message.author.tag,
          avatar: avatarUrl
        },
        meta: { message, client },
        reply: async (content) => {
          try {
            await message.reply(content);
          } catch (error) {
            console.error("Discord command reply failed", error);
          }
        }
      });
    }
  });

  await client.login(token);
  return client;
}

function getBotAvatarUrl(user) {
  if (!user) {
    return null;
  }
  if (typeof user.displayAvatarURL === "function") {
    try {
      return user.displayAvatarURL({ format: "png", size: 128 });
    } catch {
      return user.displayAvatarURL();
    }
  }
  if (user.avatar) {
    return `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png?size=128`;
  }
  return null;
}

function resolveIntent(key, legacyKey) {
  if (GatewayIntentBits?.[key]) {
    return GatewayIntentBits[key];
  }
  if (IntentsBitField?.Flags?.[key]) {
    return IntentsBitField.Flags[key];
  }
  if (Intents?.FLAGS?.[legacyKey]) {
    return Intents.FLAGS[legacyKey];
  }
  return null;
}

async function stopBot() {
  if (client) {
    await client.destroy();
    client = null;
  }
}

function getClient() {
  return client;
}

module.exports = {
  startBot,
  stopBot,
  getClient
};
