/// <reference types="../CTAutocomplete" />
/// <reference lib="es2015" />

import Settings from "./config";
import request from "requestV2";
import { fetch } from "tska/polyfill/Fetch"
import PogObject from "PogData";

let KICKDELAY = 600;

const Pog = new PogObject('PartyFinderPremium', {
  throwers: [],
  throwernames: [],
  reasons: [],
});


ChatLib.chat("&9&m-----------------------------------------------------");
ChatLib.chat("&3PartyFinderPremium &aLoaded!");
ChatLib.chat("&7Use &3/pfp help &7- Shows all available commands");
ChatLib.chat("&9&m-----------------------------------------------------");


register("chat", (event) => {
  if (!Settings.throwerkick) return;

  let message = ChatLib.getChatMessage(event).removeFormatting();
  let splitMessage = message.split(" joined the dungeon group! ");
  
  if (splitMessage.length < 2) return;

  let user = splitMessage[0].replace("Party Finder > ", "");
  let userClass = splitMessage[1].split(" Level ")[0].split("(")[1];

  if (user === Player.getName()) return;

  fetch(`https://api.mojang.com/users/profiles/minecraft/${user}`, {json: true}).then((data) => {
    try {
      let jsonData = data;
      if (!jsonData.id) {
        throw new Error("Invalid Mojang API response");
      }
      let uuid = jsonData.id.toLowerCase();

      let throwerIndex = Pog.throwers.indexOf(uuid);
      if (throwerIndex !== -1) {
        let reason = Pog.reasons[throwerIndex] || "No reason specified";
        ChatLib.chat(`${Settings.PREFIX} &c<!> &eUser &c&l${user} &eis on your thrower list! Reason: ${reason}`);
        if (Settings.kickReason) {
          setTimeout(() => {
            let ThrowerMessage = Settings.THROWERMSG.replace("{user}", user);
            ChatLib.command(`pc ${ThrowerMessage} Reason: ${reason}`);
          }, 150);
        }
        setTimeout(() => {
          ChatLib.command(`p kick ${user}`);
        }, KICKDELAY);
      } else if (!Settings[`${userClass.toLowerCase()}Allowed`]) {
        ChatLib.chat(`${Settings.PREFIX} &c<!> &eThis user is playing the &c&l${userClass} &eclass, which you have not allowed to join your party.`);
        if (Settings.kickReason) {
          setTimeout(() => {
            let ClassKickMessage = Settings.CLASSKICKMSG.replace("{class}", userClass).replace("{user}", user);
            ChatLib.command(`pc ${ClassKickMessage}`);
          }, 150);
        }
        setTimeout(() => {
          ChatLib.command(`p kick ${user}`);
        }, KICKDELAY);
      }
    } catch (error) {
      ChatLib.chat(`${Settings.PREFIX} &cError parsing Mojang API response: ${error.message}`);
    }
  }).catch((error) => {
    if (error.message.includes("SSLHandshakeException")) {
      let throwerIndex = Pog.throwernames.indexOf(user.toLowerCase());
      if (throwerIndex !== -1) {
        let reason = Pog.reasons[throwerIndex] || "No reason specified";
        ChatLib.chat(`${Settings.PREFIX} &c<!> &eUser &c&l${user} &eis on your thrower list! Reason: ${reason}`);
        if (Settings.kickReason) {
          setTimeout(() => {
            let ThrowerMessage = Settings.THROWERMSG.replace("{user}", user);
            ChatLib.command(`pc ${ThrowerMessage} Reason: ${reason}`);
          }, 150);
        }
        setTimeout(() => {
          ChatLib.command(`p kick ${user}`);
        }, KICKDELAY);
      } else if (!Settings[`${userClass.toLowerCase()}Allowed`]) {
        ChatLib.chat(`${Settings.PREFIX} &c<!> &eThis user is playing the &c&l${userClass} &eclass, which you have not allowed to join your party.`);
        if (Settings.kickReason) {
          setTimeout(() => {
            let ClassKickMessage = Settings.CLASSKICKMSG.replace("{class}", userClass).replace("{user}", user);
            ChatLib.command(`pc ${ClassKickMessage}`);
          }, 150);
        }
        setTimeout(() => {
          ChatLib.command(`p kick ${user}`);
        }, KICKDELAY);
      }
    } else {
      ChatLib.chat(`${Settings.PREFIX} &cThere was an error retrieving user data: ${error.message}`);
    }
  });
}).setCriteria("&r&ejoined the dungeon group! ").setContains();

let syncActive = false;
let syncIndex = 0;
let syncCooldown = 0;
let updatedCount = 0;
let isProcessing = false;
let syncStartTime = 0;
let nameChanges = [];

register("command", (arg1, arg2, ...args) => {
  if (!arg1) {
    Settings.openGUI();
  } else if (arg1.toLowerCase() === "help") {
    ChatLib.chat("&9&m-----------------------------------------------------");
    ChatLib.chat("&3Usage of /pfp:");
    ChatLib.chat("&3/pfp &7- Opens the Config");
    ChatLib.chat("&3/pfp add <name> [reason] &7- Adds a user to the thrower list with an optional reason");
    ChatLib.chat("&3/pfp list &7- Shows the full thrower list");
    ChatLib.chat("&3/pfp remove <name> &7- Removes a user from the thrower list");
    ChatLib.chat("&3/pfp check <name> &7- Checks if a user is on the thrower list");
    ChatLib.chat("&3/pfp sync &7- Checks UUIDs for name changes. Req. for tooltip warnings");
    ChatLib.chat("&3/pfp import <file direction> &7- Import throwers from a downloaded ․data․json");
    ChatLib.chat("&9&m-----------------------------------------------------");
  } else if (arg1.toLowerCase() === "add") {
    if (arg2) {
      let reason = args && args.length > 0 ? args.join(" ") : "No reason specified";
      ChatLib.chat(`${Settings.PREFIX} &eWorking...`);
      fetch(`https://api.mojang.com/users/profiles/minecraft/${arg2}`, {json: true}).then((data) => {
        try {
          let jsonData = data;
          if (!jsonData.id) {
            throw new Error("Invalid Mojang API response");
          }
          let uuid = jsonData.id.toLowerCase();
  
          let throwerIndex = Pog.throwers.indexOf(uuid);
          if (throwerIndex !== -1) {
            Pog.reasons[throwerIndex] = reason;
            let addmessage = new TextComponent(`${Settings.PREFIX} &7${arg2} &eis already on your thrower list. Reason updated to: &7${reason}.`);
            let shareButton = new TextComponent(` &a&l[SHARE]`).setClick("run_command", `/pfp share ${arg2}`);
            let message = new Message(addmessage, shareButton);
            message.chat();
          } else {
            Pog.throwers.push(uuid);
            Pog.throwernames.push(arg2.toLowerCase());
            Pog.reasons.push(reason);
            let addmessage = new TextComponent(`${Settings.PREFIX} &7${arg2} &ehas been added to your thrower list. Reason: &7${reason}`);
            let shareButton = new TextComponent(` &a&l[SHARE]`).setClick("run_command", `/pfp share ${arg2}`);
            let message = new Message(addmessage, shareButton);
            message.chat();
          }
          Pog.save();
        } catch (error) {
          ChatLib.chat(`${Settings.PREFIX} &cError parsing Mojang API response: ${error.message}`);
        }
      }).catch((error) => {
        if (error.message.includes("SSLHandshakeException")) {
          ChatLib.chat(`${Settings.PREFIX} &cUnable to add &7${arg2} &cbecause of a connection issue (SSLHandshakeException). Please report this on our Discord!`);
        } else {
          ChatLib.chat(`${Settings.PREFIX} &cThere was an error adding this user to your thrower list: ${error.message}`);
        }
      });
    } else {
      ChatLib.chat(`${Settings.PREFIX} &cPlease provide a username to add to the thrower list.`);
    }
  } else if (arg1.toLowerCase() === "list") {
    let page = arg2 ? parseInt(arg2) : 1;
    let entriesPerPage = 8;
    let startIndex = (page - 1) * entriesPerPage;
    let endIndex = startIndex + entriesPerPage;
    let totalEntries = Pog.throwernames.length;

    if (startIndex >= totalEntries) {
        ChatLib.chat("&cPage " + page + " does not exist.");
        return;
    }

    let header = new Message()
        .addTextComponent("&9&m----------------&r")
        .addTextComponent(" ");

    if (page > 1) {
        header.addTextComponent(
            new TextComponent("&b&l« ").setClick("run_command", `/pfp list ${page - 1}`)
        );
    } else {
        header.addTextComponent("&7&l« ");
    }

    header.addTextComponent(`&9Thrower List (Page ${page})`);

    if (endIndex < totalEntries) {
        header.addTextComponent(
            new TextComponent(" &b&l»").setClick("run_command", `/pfp list ${page + 1}`)
        );
    } else {
        header.addTextComponent(" &7&l»");
    }

    header.addTextComponent(" &9&m----------------");
    header.chat();

    for (let i = startIndex; i < endIndex && i < totalEntries; i++) {
      let name = Pog.throwernames[i];
      let reason = Pog.reasons[i] || "No reason specified";
      let nameComponent = new TextComponent(`&7• &3${name}`).setHover("show_text", `&7Reason: ${reason}`);
      let shareComponent = new TextComponent(` &a&l[SHARE]`).setClick("run_command", `/pfp share ${name}`);
      let message = new Message(nameComponent, shareComponent);
      message.chat();
  }

    let showingStart = startIndex + 1;
    let showingEnd = Math.min(endIndex, totalEntries);
    ChatLib.chat(`&9&m------------------&r &9Showing &3${showingStart}-${showingEnd} &9of &3${totalEntries} &9&m------------------`);
  } else if (arg1.toLowerCase() === "remove") {
    if (arg2) {
      let index = Pog.throwernames.indexOf(arg2.toLowerCase());
      if (index !== -1) {
        Pog.throwernames.splice(index, 1);
        Pog.throwers.splice(index, 1);
        Pog.reasons.splice(index, 1); 
        Pog.save();
        ChatLib.chat(`${Settings.PREFIX} &eRemoved &7${arg2}&e from your thrower list!`);
      } else {
        ChatLib.chat(`${Settings.PREFIX} &cThis person isn't on your thrower list!`);
      }
    } else {
      ChatLib.chat(`${Settings.PREFIX} &cPlease state who you want to remove from your thrower list!`);
    }
  } else if (arg1.toLowerCase() === "check") { 
    if (!arg2) {
      ChatLib.chat(`${Settings.PREFIX} &cPlease provide a username to check.`);
      return;
    }

    let index = Pog.throwernames.indexOf(arg2.toLowerCase());
    if (index !== -1) {
        let reason = Pog.reasons[index] || "No reason";
        ChatLib.chat(`${Settings.PREFIX} &7${arg2} &eis on your thrower list! Reason: &7${reason}`);
    } else {
        ChatLib.chat(`${Settings.PREFIX} &7${arg2} &eis not on your thrower list!`);
    }
} else if (arg1 && arg1.toLowerCase() === "sync") {
  let throwers = Pog.throwers;
  let throwerNames = Pog.throwernames;

  if (throwers.length === 0) {
      ChatLib.chat(`${Settings.PREFIX} &cNo throwers to synchronize.`);
      return;
  }

  let estimatedTimeSecs = throwers.length * 1.2;
  let estimatedTime = estimatedTimeSecs > 60
      ? `${Math.floor(estimatedTimeSecs / 60)}m ${Math.round(estimatedTimeSecs % 60)}s`
      : `${Math.round(estimatedTimeSecs)}s`;

  ChatLib.chat(`${Settings.PREFIX} &aStarting synchronization of ${throwers.length} entries...`);
  ChatLib.chat(`${Settings.PREFIX} &aEstimated time: &e${estimatedTime}`);

  syncActive = true;
  syncIndex = 0;
  syncCooldown = 0;
  updatedCount = 0;
  isProcessing = false;
  syncStartTime = Date.now();
  nameChanges = [];

  } else if (arg1.toLowerCase() === "import") {
    if (!arg2) {
        ChatLib.chat(`${Settings.PREFIX} &cPlease enter the path to the import file. Example: /pfp import C:\\Users\\User\\Desktop\\․data․json`);
        return;
    }

    let importPath = [arg2, ...(args || [])].join(" ");

    if (!FileLib.exists(importPath)) {
        ChatLib.chat(`${Settings.PREFIX} &cFile not found at: ${importPath}`);
        return;
    }

    try {
        let importData = JSON.parse(FileLib.read(importPath));

        if (!importData.throwers || !importData.throwernames || !importData.reasons ||
            !Array.isArray(importData.throwers) || !Array.isArray(importData.throwernames) || !Array.isArray(importData.reasons) ||
            importData.throwers.length !== importData.throwernames.length || importData.throwers.length !== importData.reasons.length) {
            ChatLib.chat(`${Settings.PREFIX} &cInvalid file format. The file must contain 'Throwers', 'Throwernames' and 'Reasons' as arrays of the same length.`);
            return;
        }

        let newThrowers = importData.throwers;
        let newThrowernames = importData.throwernames;
        let newReasons = importData.reasons;

        let addedCount = 0;
        let skippedCount = 0;

        newThrowers.forEach((uuid, index) => {
            if (!Pog.throwers.includes(uuid)) {
                Pog.throwers.push(uuid);
                Pog.throwernames.push(newThrowernames[index].toLowerCase());
                Pog.reasons.push("[IMPORTED] " + (newReasons[index] || "No reason specified"));
                addedCount++;
            } else {
                skippedCount++;
            }
        });

        Pog.save();
        ChatLib.chat(`${Settings.PREFIX} &aSuccessfully imported ${addedCount} new entries! ${skippedCount} duplicates skipped.`);
    } catch (error) {
        ChatLib.chat(`${Settings.PREFIX} &cImport error: ${error.message}`);
    }
  } else if (arg1.toLowerCase() === "share") {
    if (arg2) {
        let index = Pog.throwernames.indexOf(arg2.toLowerCase());
        if (index !== -1) {
            let name = Pog.throwernames[index];
            let reason = Pog.reasons[index] || "No reason specified";
            ChatLib.command(`pc PFPSHARE > "${name}" - "${reason}"`);
        } else {
            ChatLib.chat(`${Settings.PREFIX} &cThis user is not on your list!`);
        }
    } else {
        ChatLib.chat(`${Settings.PREFIX} &cPlease provide a name to share!`);
    }
} else {
  ChatLib.chat("&cUnknown command! Use &b/pfp help &cfor a list of commands.");
}
}).setName("pfp");


register("chat", (requester, message, event) => {
  if (!message.startsWith("PFPSHARE > ")) return;

  let sender;
  if (requester.includes("[")) {
      sender = requester.split(" ")[1].trim();
  } else {
      sender = requester.trim();
  }

  if (sender.toLowerCase() === Player.getName().toLowerCase()) {
      cancel(event);
      ChatLib.chat(`${Settings.PREFIX} &aThrower shared successfully to the Party Chat!`);
      return;
  }

  cancel(event);

  let shareData = message.substring(11).split(" - ");
  if (shareData.length !== 2) return;

  let name = shareData[0].replace(/"/g, "");
  let reason = shareData[1].replace(/"/g, "");

  let addComponent = new TextComponent(`&a&l[ADD]`).setClick("run_command", `/pfp add ${name} ${reason}`);
  let shareMessage = new Message(
      `${Settings.PREFIX} &7${sender} &eshared &7${name}&e with reason: &7${reason} `,
      addComponent
  );
  let lines = new TextComponent(`&9&m-----------------------------------------------------`)
  lines.chat();
  shareMessage.chat();
  lines.chat();
}).setCriteria("Party > ${requester}: ${message}");


register("tick", () => {
  if (!syncActive || isProcessing) return;

  let throwers = Pog.throwers;
  let throwerNames = Pog.throwernames;

  if (syncCooldown > 0) {
      syncCooldown--;
      return;
  }

  if (syncIndex >= throwers.length) {
      let totalTimeSecs = Math.floor((Date.now() - syncStartTime) / 1000);
      let timeFormatted = totalTimeSecs > 60
          ? `${Math.floor(totalTimeSecs / 60)}m ${totalTimeSecs % 60}s`
          : `${totalTimeSecs}s`;

      ChatLib.chat(`${Settings.PREFIX} &aSynchronization complete!`);
      let message = new TextComponent(`${Settings.PREFIX} &a${updatedCount} names were updated in &e${timeFormatted}&a. &e&l[HOVER]`);

      if (nameChanges.length > 0) {
          let hoverText = nameChanges
              .map(n => {
                  let [oldName, newName] = n.split(" -> ");
                  return `&c${oldName} &7→ &a${newName}`;
              })
              .join("\n");

          message.setHover("show_text", `&3&lName Changes:\n${hoverText}`);
      }

      message.chat();

      syncActive = false;
      Pog.save();
      return;
  }

  let uuid = throwers[syncIndex];
  let storedName = throwerNames[syncIndex];

  isProcessing = true;

  request(`https://sessionserver.mojang.com/session/minecraft/profile/${uuid}`)
      .then((response) => {
          try {
              let jsonResponse = JSON.parse(response);
              let currentName = jsonResponse.name.toLowerCase();

              if (currentName !== storedName) {
                  nameChanges.push(`${storedName} -> ${currentName}`);
                  throwerNames[syncIndex] = currentName;
                  updatedCount++;
              }
          } catch (error) {
              ChatLib.chat(`${Settings.PREFIX} &c[ERROR] Parsing Mojang response failed: ${error.message}`);
          }
      })
      .catch((error) => {
          ChatLib.chat(`${Settings.PREFIX} &c[ERROR] Mojang API request failed: ${error.message}`);
      })
      .then(() => {
          syncIndex++;
          syncCooldown = 20;
          isProcessing = false;
      });
});
                   

register("tick", () => {
  if (!Settings.editpf) return;
  if (Player.getOpenedInventory()?.getName() === "Party Finder") {
      let inventory = Player.getOpenedInventory();

      for (let i = 0; i < inventory.getSize(); i++) {
          let item = inventory.getStackInSlot(i);

          if (item && item.getID() === 397) {
              let lore = item.getLore();
              if (!lore) continue;

              if (!lore.some(line => line.includes("Dungeon:")) || !lore.some(line => line.includes("Members:"))) {
                  continue;
              }

              lore = lore.filter(line => !line.includes("'s Party"));

              if (lore.some(line => line.includes("§4⚠ THROWER IN PARTY ⚠"))) {
                  continue;
              }

              let members = [];
              let memberSection = false;

              for (let line of lore) {
                  if (line.includes("Members:")) {
                      memberSection = true;
                      continue;
                  }
                  if (memberSection) {
                      if (line.trim() === "" || line.startsWith("§8")) {
                          break;
                      }
                      if (line.includes(":")) {
                          let memberName = line.split(":")[0].trim();
                          memberName = ChatLib.removeFormatting(memberName).trim().toLowerCase();
                          members.push(memberName);
                      }
                  }
              }

              let throwerNames = [];
              let updatedLore = false;

              lore = lore.map(line => {
                  if (line.includes(":")) {
                      let parts = line.split(":");
                      let memberName = parts[0].trim();
                      let cleanName = ChatLib.removeFormatting(memberName).trim().toLowerCase();

                      if (Pog.throwernames.includes(cleanName)) {
                          throwerNames.push(cleanName);
                          let memberClass = parts[1].trim();
                          updatedLore = true;
                          return `§4§l${ChatLib.removeFormatting(memberName)}§r: ${memberClass}`;
                      }
                  }
                  return line;
              });

              if (throwerNames.length > 0) {
                  let throwerLine = `§7Thrower: §c${throwerNames.join(", ")}`;
                  let noteIndex = lore.findIndex(line => line.includes("Note:"));
                  if (noteIndex !== -1 && !lore.some(line => line.includes("Thrower:"))) {
                      lore.splice(noteIndex + 1, 0, throwerLine);
                      updatedLore = true;
                  }
              }

              if (throwerNames.length > 0 && !lore.some(line => line.includes("⚠ THROWER IN PARTY ⚠"))) {
                let maxLength = Math.max(...lore.map(line => ChatLib.removeFormatting(line).length));
                let warning = "⚠ THROWER IN PARTY ⚠";
                let padding = Math.max(0, Math.floor((maxLength - warning.length) / 2));
                let centeredWarning = " ".repeat(padding) + `§4${warning}`;
            
                lore.push(centeredWarning);
                updatedLore = true;
            	}

              if (updatedLore) {
                  item.setLore(lore);
              }
          }
      }
  }
});

//      _ _                       _                         __                  _   _                _           _     
//     | (_)                     | |                       / /                 | | | |              (_)         | |    
//   __| |_ ___  ___ ___  _ __ __| |       __ _  __ _     / /   _ __ ___  _   _| |_| |__   ___ _ __  _  ___ __ _| |___ 
//  / _` | / __|/ __/ _ \| '__/ _` |      / _` |/ _` |   / /   | '_ ` _ \| | | | __| '_ \ / _ | '_ \| |/ __/ _` | / __|
// | (_| | \__ | (_| (_) | | | (_| |  _  | (_| | (_| |  / /    | | | | | | |_| | |_| | | |  __| | | | | (_| (_| | \__ \
//  \__,_|_|___/\___\___/|_|  \__,_| (_)  \__, |\__, | /_/     |_| |_| |_|\__, |\__|_| |_|\___|_| |_|_|\___\__,_|_|___/
//                                         __/ | __/ |                     __/ |                                       
//                                         |___/ |___/                     |___/                                        

// Thank you for checking out my code!
// If you have any improvements or feedback, feel free to reach out to me on Discord:  
// Community: discord.gg/mythenicals  
// Direct: kilianbrc  
