import client, { createUeuse } from "@/lib/client";
import Memory from "@/lib/memory";
import ueuseModule from "better-uwuzu-sdk/types/1.6.8/types/modules/ueuse";
import i18next from "i18next";
import weatherCommand from "@/feature/command/weather";
import helpCommand from "@/feature/command/help";
import followCommand from "@/feature/command/follow";
import unfollowCommand from "@/feature/command/unfollow";
import miqCommand from "@/feature/command/miq";
import initI18n from "@/lib/i18n";
import config from "@/lib/config";

await initI18n();

console.log("コマンドの処理を行います");

try {
  let ueuses: ueuseModule[] = [];

  const mem = Memory.memory;
  let newLastReadReply = mem.lastReadReply;
  let newLastReadMention = mem.lastReadMention;

  {
    const response = await client.request("me/notification/", {
      page: 1,
      limit: 20,
    });

    if (response.success) {
      const notifications = response.data.filter(n => n.category === "reply" && typeof n.valueid === "string");

      for (const [index, notification] of notifications.entries()) {
        const ueuseResponse = await client.request("ueuse/get", { uniqid: notification.valueid });

        if (!ueuseResponse.success || !ueuseResponse.data[0]) {
          console.warn("返信通知からユーズを参照できないため、スキップします");
          continue;
        }

        const ueuseData = ueuseResponse.data[0];
        const time = new Date(ueuseData.datetime).getTime();

        if (mem.lastReadReply >= time)
          break;

        if (index === 0)
          newLastReadReply = time;

        ueuses.push(ueuseData);
      }
    } else {
      console.warn("返信通知の取得に失敗しましたが、続行します");
    }
  }

  {
    const response = await client.request("ueuse/mentions", {
      page: 1,
      limit: 20,
    });

    if (response.success) {
      const mentions = response.data;

      for (const [index, mention] of mentions.entries()) {
        const time = new Date(mention.datetime).getTime();

        if (mem.lastReadMention >= time)
          break;

        if (index === 0)
          newLastReadMention = time;

        ueuses.push(mention);
      }
    } else {
      console.warn("メンションの取得に失敗しましたが、続行します");
    }
  }

  mem.lastReadReply = newLastReadReply;
  mem.lastReadMention = newLastReadMention;
  Memory.memory = mem;

  const seenIds = new Set();
  ueuses = ueuses.filter(ueuse => {
    if (seenIds.has(ueuse.uniqid))
      return false;
    seenIds.add(ueuse.uniqid);
    return true;
  });

  for (let i = 0; i < ueuses.length; i += config.command.maxParallels) {
    const chunk = ueuses.slice(i, i + config.command.maxParallels);
    
    await Promise.all(chunk.map(async (ueuse) => {
      const mem = Memory.memory;
      let text = ueuse.text;
      text = text.replace(`@${mem.userid}`, "");
      text = text.trim();

      const rows = text.split(/\r\n|\r|\n/).map(row => row.trim());
      const commandRow = rows.filter(row => row.startsWith("/"))[0];

      if (!commandRow || commandRow === "") {
        console.warn("コマンドが本文から参照できません");

        await createUeuse({
          text: i18next.t("commandNotFound"),
          replyid: ueuse.uniqid,
        }, "コマンドが見つからない旨");

        return;
      }

      const args = commandRow.replace("/", "").split(" ");
      
      switch (args[0]) {
        case "help":
          await helpCommand(ueuse, args);
          break;
        case "weather":
          await weatherCommand(ueuse);
          break;
        case "follow":
          await followCommand(ueuse);
          break;
        case "unfollow":
          await unfollowCommand(ueuse);
          break;
        case "miq":
          await miqCommand(ueuse, args);
          break;
        default:
          console.warn("不明なコマンドが入力されました:", args[0]);

          await createUeuse({
            text: i18next.t("unknownCommand", { command: args[0] }),
            replyid: ueuse.uniqid,
          }, "コマンドが不明である旨");

          break;
      }
    }));
  }

  process.exit(0);
} catch (err: any) {
  console.error("message" in err
    ? err.message
    : err);
  process.exit(1);
}