package de.hessj.environmentex;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import de.hessj.helper.Helper.Type;

public class EnvironmentExCommands implements CommandExecutor, Listener {
    public de.hessj.helper.Helper helper = new de.hessj.helper.Helper();
    private final Map<UUID, Map<String, Location>> playerPins = new HashMap<>();
    private HashMap<UUID, BossBar> bossBars = new HashMap<>();

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (sender instanceof Player) {
            if (EnvironmentExListeners.voteIsGoing) {
                if (label.equalsIgnoreCase("y")) {
                    if (!EnvironmentExListeners.hasVoted.contains(((Player) sender).getUniqueId())) {
                        EnvironmentExListeners.voteForYes++;
                        ((Player) sender).sendMessage(helper.R3SMessage(Type.INFO, "Du hast für Ja gevotet."));
                        EnvironmentExListeners.hasVoted.add(((Player) sender).getUniqueId());
                    }
                } else if (label.equalsIgnoreCase("n")) {
                    if (!EnvironmentExListeners.hasVoted.contains(((Player) sender).getUniqueId())) {
                        EnvironmentExListeners.voteForNo++;
                        ((Player) sender).sendMessage(helper.R3SMessage(Type.INFO, "Du hast für Nein gevotet."));
                        EnvironmentExListeners.hasVoted.add(((Player) sender).getUniqueId());
                    }
                }
            }

            if (label.equalsIgnoreCase("afk")) {
                Player p = (Player) sender;
                p.playerListName(App.helper.R3SMessage(Type.ERROR, "[AFK] " + p.getName()));
            }

            if (label.equalsIgnoreCase("pin")) {
                Player p = (Player) sender;
                UUID playerId = p.getUniqueId();
                playerPins.putIfAbsent(playerId, new HashMap<>());

                if (args.length < 1) {
                    p.sendMessage(helper.R3SMessage(Type.ERROR,
                            "Benutzung: /pin <set | list | remove | follow | unfollow> [name | id]"));
                    return true;
                }

                String subCommand = args[0].toLowerCase();
                Map<String, Location> pins = playerPins.get(playerId);

                switch (subCommand) {
                    case "set":
                        if (args.length < 2) {
                            p.sendMessage(helper.R3SMessage(Type.ERROR, "Benutzung: /pin set <name>"));
                            return true;
                        }

                        // **Nimmt den gesamten Text nach "/pin set" als Namen**
                        String pinName = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
                        Location playerLocation = p.getLocation();

                        // **Kleinste verfügbare ID suchen**
                        int nextId = 1;
                        ConfigurationSection playerSection = PinFeature.pinConfig
                                .getConfigurationSection(playerId.toString());
                        if (playerSection != null) {
                            Set<Integer> existingIds = playerSection.getKeys(false).stream()
                                    .map(Integer::parseInt)
                                    .collect(Collectors.toSet());

                            while (existingIds.contains(nextId)) {
                                nextId++;
                            }
                        }

                        pins.put(pinName, playerLocation);
                        String locationString = playerLocation.getWorld().getName() + ", " +
                                playerLocation.getBlockX() + ", " +
                                playerLocation.getBlockY() + ", " +
                                playerLocation.getBlockZ();

                        PinFeature.pinConfig.set(playerId + "." + nextId + ".name", pinName);
                        PinFeature.pinConfig.set(playerId + "." + nextId + ".loc", locationString);
                        savePins();

                        p.sendMessage(helper.R3SMessage(Type.SUCCESS,
                                "Pin '" + pinName + "' wurde mit der ID " + nextId + " erstellt."));
                        break;

                    case "list":
                        loadPinsFromConfig(playerId);

                        if (pins.isEmpty()) {
                            p.sendMessage(helper.R3SMessage(Type.ERROR, "Du hast keine Pins."));
                            return true;
                        }
                        p.sendMessage(helper.R3SMessage(Type.OK, "Deine Pins:"));

                        ConfigurationSection ps = PinFeature.pinConfig.getConfigurationSection(playerId.toString());
                        if (ps != null) {
                            List<Integer> sortedIds = ps.getKeys(false).stream()
                                    .map(Integer::parseInt)
                                    .sorted()
                                    .collect(Collectors.toList());

                            for (int id : sortedIds) {
                                String name = PinFeature.pinConfig.getString(playerId + "." + id + ".name");
                                String locString = PinFeature.pinConfig.getString(playerId + "." + id + ".loc");
                                if (name == null || locString == null)
                                    continue;

                                String[] locParts = locString.split(", ");
                                int x = Integer.parseInt(locParts[1]);
                                int y = Integer.parseInt(locParts[2]);
                                int z = Integer.parseInt(locParts[3]);
                                String worldLabel = "Overworld";

                                if (locParts[0].endsWith("_nether")) {
                                    worldLabel = "Nether";
                                } else if (locParts[0].endsWith("_end")) {
                                    worldLabel = "End";
                                }

                                p.sendMessage("   [" + id + "] " + worldLabel + ": " + name + " (" + x + ", " + y + ", "
                                        + z + ")");
                            }
                        }
                        break;

                    case "remove":
                        if (args.length < 2) {
                            p.sendMessage(helper.R3SMessage(Type.ERROR, "Benutzung: /pin remove <id>"));
                            return true;
                        }
                        String pinId = args[1];

                        if (PinFeature.pinConfig.contains(playerId + "." + pinId)) {
                            String pinName1 = PinFeature.pinConfig.getString(playerId + "." + pinId + ".name");
                            PinFeature.pinConfig.set(playerId + "." + pinId, null);
                            savePins();
                            p.sendMessage(
                                    helper.R3SMessage(Type.SUCCESS, "Dein Pin '" + pinName1 + "' wurde entfernt."));
                        } else {
                            p.sendMessage(helper.R3SMessage(Type.ERROR, "Kein Pin mit dieser ID gefunden."));
                        }
                        break;

                    case "follow":
                        if (args.length < 2) {
                            p.sendMessage(helper.R3SMessage(Type.ERROR, "Benutzung: /pin follow <id>"));
                            return true;
                        }

                        try {
                            int pinId1 = Integer.parseInt(args[1]);
                            String pinName1 = PinFeature.pinConfig.getString(playerId + "." + pinId1 + ".name");
                            String locationString1 = PinFeature.pinConfig.getString(playerId + "." + pinId1 + ".loc");

                            if (pinName1 == null || locationString1 == null) {
                                p.sendMessage(helper.R3SMessage(Type.ERROR, "Kein Pin mit dieser ID gefunden."));
                                return true;
                            }

                            // Standort aus der YML auslesen
                            String[] locParts = locationString1.split(", ");
                            String worldName = locParts[0];
                            int x = Integer.parseInt(locParts[1]);
                            int y = Integer.parseInt(locParts[2]);
                            int z = Integer.parseInt(locParts[3]);

                            String worldLabel = "Overworld";
                            if (worldName.endsWith("_nether"))
                                worldLabel = "Nether";
                            if (worldName.endsWith("_end"))
                                worldLabel = "End";

                            // BossBar erstellen/aktualisieren
                            BossBar bossBar = Bukkit.createBossBar(worldLabel + ": " + x + ", " + y + ", " + z,
                                    BarColor.WHITE, BarStyle.SOLID);
                            bossBar.setProgress(0.0);

                            if (bossBars.containsKey(p.getUniqueId())) {
                                bossBars.get(p.getUniqueId()).removeAll();
                                bossBars.remove(p.getUniqueId());
                            }
                            bossBar.addPlayer(p);
                            bossBars.put(p.getUniqueId(), bossBar);

                            p.sendMessage(helper.R3SMessage(Type.SUCCESS, "Du folgst nun dem Pin '" + pinName1 + "'"));

                        } catch (NumberFormatException e) {
                            p.sendMessage(helper.R3SMessage(Type.ERROR, "Kein Pin mit dieser ID gefunden."));
                        }
                        break;

                    case "unfollow":
                        if (bossBars.containsKey(p.getUniqueId())) {
                            bossBars.get(p.getUniqueId()).removeAll();
                            bossBars.remove(p.getUniqueId());
                            p.sendMessage(helper.R3SMessage(Type.ERROR, "Du folgst nun keinem Pin mehr."));
                        }
                        break;

                    default:
                        p.sendMessage(helper.R3SMessage(Type.ERROR,
                                "Benutzung: /pin <set | list | remove | follow | unfollow> [name | id]"));
                }
            }

        } else {

            if (label.equalsIgnoreCase("add") && args.length == 1) {
                UUID uuid;
                try {
                    uuid = UUID.fromString(args[0].toString());
                    if (LoginListener.customConfig.contains("players." + Bukkit.getOfflinePlayer(uuid).getUniqueId())) {
                        LoginListener.customConfig
                                .set("players." + Bukkit.getOfflinePlayer(uuid).getUniqueId() + ".whitelisted", true);
                        App.main.getLogger().info(args[0].toString() + " wurde auf die Whitelist gesetzt!");
                        LoginListener.saveCustomYml(LoginListener.customConfig, LoginListener.customYml);
                    } else {
                        App.main.getLogger().info("Diese UUID ist dem Server unbekannt!");
                    }
                } catch (Exception ex) {
                    App.main.getLogger().info("Die angegebene UUID ist inkorrekt!");
                }
            }
            if (label.equalsIgnoreCase("infbucket")) {
                try {
                    Player p = (Player) sender;
                    ItemStack testEnchant = new ItemStack(Material.BOW, 1);
                    ItemMeta testEnchantMeta = testEnchant.getItemMeta();
                    testEnchantMeta.addEnchant(Enchantment.INFINITY, 1, false);
                    testEnchant.setItemMeta(testEnchantMeta);
                    p.getWorld().dropItemNaturally(p.getLocation(), testEnchant);
                } catch (Exception ex) {
                    App.main.getLogger().info("Die angegebene UUID ist inkorrekt!");
                }
            }

        }
        return true;
    }

    private void savePins() {
        try {
            PinFeature.pinConfig.save(PinFeature.pinYml);
        } catch (IOException e) {
            Bukkit.getLogger().severe("Could not save pins.yml!");
        }
    }

    private void loadPinsFromConfig(UUID playerId) {
        // Clear the current player's pins map before loading new data
        playerPins.putIfAbsent(playerId, new HashMap<>());
        Map<String, Location> pins = playerPins.get(playerId);

        // Get the pin configuration for this player
        if (PinFeature.pinConfig.contains(playerId.toString())) {
            for (String pinName : PinFeature.pinConfig.getConfigurationSection(playerId.toString()).getKeys(false)) {
                String locationString = PinFeature.pinConfig.getString(playerId + "." + pinName + ".loc");
                if (locationString != null) {
                    String[] locParts = locationString.split(", ");
                    if (locParts.length == 4) {
                        String worldName = locParts[0];
                        int x = Integer.parseInt(locParts[1]);
                        int y = Integer.parseInt(locParts[2]);
                        int z = Integer.parseInt(locParts[3]);

                        Location location = new Location(Bukkit.getWorld(worldName), x, y, z);
                        pins.put(pinName, location);
                    }
                }
            }
        }
    }
}
