const tmi = require("tmi.js");
const { getSetting } = require("./settings");
const { incrementMessages } = require("./stats");
const { ensureUserForIdentity } = require("./users");
const { createLogger } = require("./logger");
const { publishOverlayChatMessage } = require("./overlay-chat");
const { resolveBetterTtvEmotes, resolveTwitchAvatar, resolveTwitchBadges } = require("./twitch-chat-assets");

const twitchLog = createLogger("platform:twitch", { category: "integration" });

let client = null;

function parseChannels(raw) {
  return (raw || "")
    .split(/[,\s]+/)
    .map((entry) => entry.trim())
    .filter(Boolean)
    .map((entry) => (entry.startsWith("#") ? entry : `#${entry}`));
}

async function startTwitchBot({ commandRouter } = {}) {
  const username = getSetting("twitch_bot_username");
  const oauth = getSetting("twitch_bot_oauth");
  const channels = parseChannels(getSetting("twitch_channels"));
  if (!username || !oauth || !channels.length) {
    return null;
  }

  const password = oauth.startsWith("oauth:") ? oauth : `oauth:${oauth}`;
  client = new tmi.Client({
    options: { debug: false },
    identity: {
      username,
      password
    },
    channels
  });

  client.on("connected", (address, port) => {
    twitchLog.info("Twitch bot connected", { address, port, channels }, { event: "platform_ready" });
  });

  client.on("message", async (channel, tags, message, self) => {
    const userId = tags["user-id"] || (self ? `lumi:${username.toLowerCase()}` : "");
    if (!userId) {
      return;
    }
    const displayName = tags["display-name"] || tags.username || username;
    const [badges, avatar, betterTtvEmotes] = await Promise.all([
      resolveTwitchBadges(tags["room-id"], tags.badges || {}),
      resolveTwitchAvatar(tags["user-id"], tags.username || username),
      resolveBetterTtvEmotes(tags["room-id"], message)
    ]);
    const profile = self ? null : ensureUserForIdentity({
      provider: "twitch",
      providerUserId: userId,
      displayName,
      avatar
    });
    publishOverlayChatMessage({
      id: tags.id,
      platform: "twitch",
      text: message,
      timestamp: Number(tags["tmi-sent-ts"]) || Date.now(),
      channel: { id: String(tags["room-id"] || ""), name: channel, key: channel },
      author: {
        id: userId,
        name: displayName,
        username: tags.username,
        avatar,
        color: tags.color,
        badges,
        lumi: profile ? { id: profile.id, username: profile.internal_username } : null
      },
      emotes: [
        ...Object.entries(tags.emotes || {}).flatMap(([id, positions]) => (positions || []).map((position) => {
          const [start, end] = String(position).split("-").map(Number);
          return { start, end, image: `https://static-cdn.jtvnw.net/emoticons/v2/${encodeURIComponent(id)}/default/dark/3.0` };
        })),
        ...betterTtvEmotes
      ]
    });
    if (self) return;
    incrementMessages(profile.id);

    if (commandRouter) {
      await commandRouter.handleMessage({
        platform: "twitch",
        raw: message,
        user: profile,
        platformUser: {
          id: userId,
          displayName,
          username: tags.username
        },
        meta: { channel, tags, client },
        reply: async (content) => {
          try {
            await client.say(channel, content);
          } catch (error) {
            twitchLog.error("Twitch command reply failed", error, { event: "reply_failed" });
          }
        }
      });
    }
  });

  await client.connect();
  return client;
}

async function stopTwitchBot() {
  if (client) {
    await client.disconnect();
    client = null;
  }
}

function getClient() {
  return client;
}

module.exports = {
  startTwitchBot,
  stopTwitchBot,
  getClient
};
