// Trekování statusů všech lidí o kterých bot ví
import { Client, Guild, Presence } from "discord.js";
import { FakePresence, Modul, SRecord, StatusyINaFounu, UserChange, ZmenovejObjekt } from "../utils/types";
import { adminLog, betterFetch, log } from "../utils/utils";

const statusy = { Offline: "0", Online: "1", Idle: "2", DND: "3", OnlinePhone: "11", IdlePhone: "12", DNDPhone: "13" };
const prepSend = (zmeny: UserChange[]) => {
  const changes: ZmenovejObjekt[] = [];

  zmeny.forEach(zmena => {
    const us = zmena.user;
    const objekt: ZmenovejObjekt = { id: us.id };
    if (zmena.ch === "user" || !zmena.ch) {
      objekt.nick = us.username;
      objekt.pfp = us.avatar ?? "";
    }
    if (zmena.ch === "stat" || !zmena.ch) {
      objekt.status = zmena.stat;
    }
    changes.push(objekt);
  });

  poslatData({ changes });
};

const poslatData = (data: SRecord<unknown>) => {
  data.pwd = process.env.statPass;
  betterFetch("http://deadfish.cz:4629/endpoint-pro-denimka/", { method: "POST", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) })
    .catch(err => {
      log("err:", err);
      const client: Client<boolean> = module.exports.client;
      adminLog(client, "stat nejede");
    });
};

const ziju = () => {
  poslatData({ nejsemPoslej: !0 });
  setTimeout(ziju, 60_000);
};

if (!process.env.ignorePresence) ziju();

const getRole = (status: StatusyINaFounu, server: Guild) =>
  server.roles.cache.find(role => role.name === `Status${status}`);

function statusOnFoun(bef: FakePresence | null, aft: FakePresence) {
  const role = { online: "Online", idle: "Idle", dnd: "DND", offline: "Offline" };

  if (!bef) bef = { status: 'offline', clientStatus: {} };
  const predAPo: StatusyINaFounu[] = [];

  [bef, aft].forEach((s, i) => {
    const mobile = s.clientStatus?.mobile;
    const deskotopy = s.clientStatus?.web
      ? s.clientStatus.desktop == "online" ? s.clientStatus.desktop : s.clientStatus.web
      : s.clientStatus?.desktop;

    if (mobile && mobile != deskotopy && (!deskotopy || deskotopy == "idle")) {
      predAPo[i] = `${role[mobile]}Phone` as StatusyINaFounu;
    } else {
      predAPo[i] = role[s.status] as StatusyINaFounu;
    }
  });

  return predAPo;
}


const exp: Modul = {

  // Změna rolí podle statusu a odeslání statusu
  on_presenceUpdate: (bef, aft) => {
    if (process.env.ignorePresence) return;

    const [statusPred, statusPo] = statusOnFoun(bef as FakePresence, aft as FakePresence);
    if (statusPred === statusPo) return;
    const rolePred = getRole(statusPred, aft.guild!);
    const rolePo = getRole(statusPo, aft.guild!);


    if (rolePred) aft.member!.roles.remove(rolePred);
    if (rolePo) aft.member!.roles.add(rolePo);

    prepSend([{ ch: "stat", user: aft.user!, stat: statusy[statusPo] }]);
  },

  // Odeslání statusů při startu bota
  on_clientReady: () => {
    if (process.env.ignorePresence) return;

    const client: Client = module.exports.client;
    const guildy = client.guilds.cache;
    const userove = client.users.cache.clone();
    const presence: Presence[] = [];
    const changes: UserChange[] = [];

    guildy.each(guilda => {
      guilda.presences.cache.each(pres => {
        if (!presence.filter(prs => prs.userId === pres.userId).length) presence.push(pres);
      });
    });

    presence.forEach(presenc => {
      const status = statusOnFoun(null, presenc as FakePresence)[1];
      changes.push({ user: userove.get(presenc.userId)!, stat: statusy[status] });
      userove.delete(presenc.userId);
    });

    userove.each(member => {
      changes.push({ user: member, stat: "0" });
    });

    prepSend(changes);
  },

  // Odeslání statusu při změně jména nebo profilovky
  on_userUpdate: (bef, aft) => {
    if (!process.env.ignorePresence && bef.id != aft.client.user?.id)
      prepSend([{ ch: "user", user: aft }]);
  }
};

module.exports = exp;
