// Komandy nebo handelery který se nikam jinam nehodí

import { getVoiceConnections } from "@discordjs/voice";
import { Client } from "discord.js";
import { createServer } from "http";
import { Modul } from "../utils/types";
import { adminLog, formatCas, log, nabidni, messageReply, sendDM, sendWithoutReply, betterFetch } from "../utils/utils";
import { emouty } from "../utils/emotes";
import { readFileSync } from "fs";

const zpravy = new Map<string, Map<string, number[]>>();
const dobaOmezení = 20_000;
let client: Client;

const exp: Modul = {
  more_komandy: {

    debug_log: {
      hidden: true,
      run: (_, arg) => {
        log("log:", arg);
        return "je to v konzoli";
      }
    },

    update: {
      als: ["apdejt"],
      run: async mes => {
        const sudo = mes.channel.id == process.env.adminChannel || mes.author.id == process.env.adminID;
        if (!sudo) {
          const verze = await betterFetch("https://gitea.deadfish.cz/Histmy/Denim-Bot/raw/branch/main/package.json")
            .then(r => r.json())
            .then(d => d.version)
            .catch(e => {
              log("nepodařilo se zjistit nejnovější verzi", e);
              return false;
            });

          if (verze === false) {
            return "nevim estli se muzu neco naucit";
          }

          if (verze == require("../../package.json").version) return `ale ja se nemam co priucit vole kkte ${mes.author}`;
        }

        getVoiceConnections().forEach(con => con.destroy());
        client.user?.setStatus("invisible");
        mes.react("👋")
          .then(() => process.exit());
      }
    },

    restartujsetykurvozasrana: {
      als: ["restart"],
      run: mes => {
        const sudo = mes.channel.id == process.env.adminChannel || mes.author.id == process.env.adminID;

        function udelat() {
          getVoiceConnections().forEach(con => con.destroy());
          client.user?.setStatus("invisible");
          mes.react("👋")
            .then(() => process.exit(69));
        }

        if (!sudo) {
          const souhlasatori: string[] = [mes.author.id];

          nabidni({
            channel: mes.channel,
            nabidka: ["souhlasim"],
            zpravec: { content: "jelikoz nesi hlava zpravne namazana musi se z tebou zhotnout jeste 2 hajzlaty do 60 se kund" },
            onCollect: i => {
              if (souhlasatori.includes(i.member!.user.id)) return i.reply({
                ephemeral: true,
                content: "ti us sy na to klyknul ti suraku"
              });

              souhlasatori.push(i.member!.user.id);

              if (souhlasatori.length == 3) udelat();
              else i.update({ content: "heste jeden" });
            },
            konecnaZprava: "restart se nekona, ste kundi so se neumy dohodnout",
            timeout: 6e4,
            stejne: true
          });
          return;
        }

        udelat();
      }
    },

    lastuptime: () => {
      const sekundy = Number(process.argv[3]);
      if (!sekundy) return "aj forgor 💀";
      return `naposled jsem jel ${formatCas(sekundy)}`;
    },

    davajlogec: mes => {
      if (mes.author.id != process.env.adminID) return "ty si kdo";

      const log = readFileSync("statlog.dlog");

      return {
        files: [{
          attachment: log,
          name: "statlog.dlog"
        }]
      };
    }
  },

  super_on_messageCreate: {
    pos: 1,
    fun: mes => {
      const ted = Date.now();
      const autor = mes.author.id;

      if (!zpravy.has(autor)) {
        zpravy.set(autor, new Map());
      }

      const uzivatel = zpravy.get(mes.author.id)!;
      const timestampy = uzivatel.get(mes.content) ?? [];

      const aktualni = timestampy.filter(timestamp => ted - timestamp < dobaOmezení);
      aktualni.push(ted);
      uzivatel.set(mes.content, aktualni);

      const pocet = aktualni.length;
      if (pocet < 7) return false;

      (async () => {
        if (mes.author.id == client.user?.id)
          return mes.content != "uz nechci" ? messageReply(mes, "uz nechci") : "";
        const adminRole = mes.member?.roles.cache.find(r => r.name == "admin");
        if (adminRole) {
          await mes.member?.roles.remove(adminRole).catch(e => log(mes.author.displayName, "nejde odebrat admin", e));
        }

        await mes.member?.timeout(60_000, "spamer zasranej").catch(e => log(mes.author.displayName, "nejde timeoutnout zmrd", e));
        if (adminRole) setTimeout(() => {
          mes.member?.roles.add(adminRole);
        }, 60_000);
        messageReply(mes, emouty.fu);
      })();

      return true;
    }
  },

  on_clientReady: () => {
    // Nastavení clienta
    client = module.exports.client;

    // OG onReady++
    log("A jedeš!");
    if (process.argv[2] == "1") {
      const duvod = readFileSync("logs/recent.txt").toString();
      adminLog(client, "pošel jsem", duvod);
    }

    // Server na navrhy
    createServer((req, res) => {
      res.statusCode = 400;
      if (req.socket.remoteAddress != "::1") return res.end("di doprdele dyk ne more");

      const sp = new URL(req.url!, `http://${req.headers.host}`).searchParams;
      const { userID, content } = Object.fromEntries(sp.entries());
      if (!userID || !content) return res.end("gde mas userID a content????");

      const user = client.users.cache.get(userID);
      if (!user) return res.end("takovyho kkta neznam");

      user.createDM().then(async dm => {
        await sendWithoutReply(dm, content);
        res.statusCode = 200;
        res.end("OK");
      }).catch((e: Error) => {
        if (e.message.search("2000 or fewer")) return res.end("content je moc dlouhej");
        log("error pri posilani upozorneni", e);
        res.statusCode = 500;
        res.end("neco se posralo");
      });
    }).listen(1298);

    // Garbage-colector na `zpravy`
    setInterval(() => {
      const ted = Date.now();
      zpravy.forEach((mapa, uzivatel) => {
        mapa.forEach((pocet, zprava) => {
          const aktualni = pocet.filter(timestamp => ted - timestamp < dobaOmezení);
          if (!aktualni.length) mapa.delete(zprava);
        });
        if (!mapa.size) zpravy.delete(uzivatel);
      });
    }, 60_000);
  },

  on_userUpdate: (bef, aft) => {
    if (bef.avatar == aft.avatar) return;

    sendDM(aft, "cus bracho vydim ze sis zmenim profilofku na dalsi mrdku estli chces abi se ukazovala na na v3ech sr4kach kterz sou na dedfis.cy tak se tam prosymte prihlas haby se mohla zmnenit syk");
  },

  on_userPresenceUpdate: (bef, aft) => {
    if (aft.user?.id != "355053867265818635" || bef?.status == "online" || aft.status != "online") return;

    const channel = client.channels.cache.get("555779161067749448");

    if (!channel || !channel.isSendable()) {
      log("nelze poslat zpravu o Pavelovi, kanal nenalezen");
      return;
    }

    sendWithoutReply(channel, "https://tenor.com/view/pavel-is-online-gif-21604335");
  }
};

module.exports = exp;
