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");
const { createLogger } = require("./logger");
const { publishOverlayChatMessage } = require("./overlay-chat");
const { discordOverlayContent } = require("./discord-chat-content");
const { emitLumiEvent } = require("./lumi-events");

const discordLog = createLogger("platform:discord", { category: "integration" });

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;
  }
  discordLog.info("Discord bot starting", {
    intents,
    guildMembers: Boolean(resolveIntent("GuildMembers", "GUILD_MEMBERS"))
  }, { event: "platform_starting" });
  if (Partials?.Channel) {
    options.partials = [Partials.Channel];
  }

  client = new Client(options);

  client.on("ready", () => {
    discordLog.info("Discord bot ready", { account: client.user?.tag || null }, { event: "platform_ready" });
    const avatarUrl = getBotAvatarUrl(client.user);
    if (avatarUrl) {
      setSetting("bot_avatar_url", avatarUrl);
    }
  });

  client.on("messageCreate", async (message) => {
    if (!message.guild) return;
    const overlayContent = discordOverlayContent(message);
    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 = message.author.bot ? null : ensureUserForIdentity({
      provider: "discord",
      providerUserId: message.author.id,
      displayName,
      avatar: avatarUrl
    });
    publishOverlayChatMessage({
      id: message.id,
      platform: "discord",
      text: overlayContent.text,
      emotes: overlayContent.emotes,
      media: overlayContent.media,
      timestamp: message.createdTimestamp,
      channel: {
        id: message.channel?.id,
        name: message.channel?.name ? `#${message.channel.name}` : message.channel?.id,
        key: `${message.guild.id}/${message.channel?.id || ""}`
      },
      author: {
        id: message.author.id,
        name: message.member?.displayName || displayName,
        username: message.author.username,
        avatar: avatarUrl,
        color: message.member?.displayHexColor === "#000000" ? null : message.member?.displayHexColor,
        badges: [],
        lumi: profile ? { id: profile.id, username: profile.internal_username } : null
      }
    });
    if (message.author.bot) return;
    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) {
            discordLog.error("Discord command reply failed", error, { event: "reply_failed" });
          }
        }
      });
    }
  });

  client.on("guildMemberAdd", (member) => {
    if (!member?.user || member.user.bot) return;
    const configuredGuildId = String(getSetting("discord_guild_id", "") || "");
    if (configuredGuildId && member.guild?.id !== configuredGuildId) return;
    emitLumiEvent("discord.member_join", {
      guild_id: member.guild?.id || null,
      guild_name: member.guild?.name || null,
      user_id: member.user.id,
      user_name: member.user.globalName || member.user.username || member.user.tag,
      joined_at: member.joinedTimestamp || Date.now()
    }, {
      id: `${member.guild?.id || "guild"}:${member.user.id}:${member.joinedTimestamp || Date.now()}`,
      source: "discord-gateway",
      occurredAt: member.joinedTimestamp || Date.now()
    });
  });

  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
};
