package de.viper.survivalplus;

import de.viper.survivalplus.commands.*;
import de.viper.survivalplus.listeners.*;
import de.viper.survivalplus.report.ReportManager;
import de.viper.survivalplus.trade.TradeManager;
import de.viper.survivalplus.listeners.DebugArmorStandListener;
import de.viper.survivalplus.listeners.ArmorStandDestroyListener;
import de.viper.survivalplus.tasks.AutoClearTask;
import de.viper.survivalplus.recipe.BackpackRecipe;
import de.viper.survivalplus.Manager.StatsManager;
import de.viper.survivalplus.Manager.BlockManager;
import de.viper.survivalplus.util.LockSystem;
import de.viper.survivalplus.util.Claim;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.ArmorStand;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.event.HandlerList;
import de.viper.survivalplus.listeners.RepairSignListener;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bstats.charts.SingleLineChart;
import de.viper.survivalplus.listeners.NickLoadListener;
import de.viper.survivalplus.Manager.LootChestManager;
import de.viper.survivalplus.commands.DayCommand;
import de.viper.survivalplus.commands.NightCommand;
import de.viper.survivalplus.commands.TradeCommand;
import de.viper.survivalplus.commands.ReportCommand;
import de.viper.survivalplus.Manager.ShopManager;
import de.viper.survivalplus.commands.ShopCommand;
import de.viper.survivalplus.commands.HealCommand;
import de.viper.survivalplus.Manager.TablistManager;
import de.viper.survivalplus.Manager.CommandBlocker;
import de.viper.survivalplus.Manager.WarpManager;
import de.viper.survivalplus.commands.SetWarpCommand;
import de.viper.survivalplus.commands.WarpsCommand;
import de.viper.survivalplus.fun.FunChallengeManager;
import de.viper.survivalplus.listeners.ChallengeCollectListener;
import de.viper.survivalplus.commands.StartFunChallengeCommand;
import de.viper.survivalplus.commands.SurvivalPlusTabCompleter;

// --- NEU: Imports für Heads, Vanish & Shops ---
import de.viper.survivalplus.commands.HeadCommand;
import de.viper.survivalplus.listeners.HeadDropListener;
import de.viper.survivalplus.listeners.VanishListener;
import de.viper.survivalplus.listeners.SignShopListener;

import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;

import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;

import java.util.Map;
import java.util.UUID;
import java.util.HashMap;
import org.bukkit.NamespacedKey;
import org.bukkit.plugin.PluginManager;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.logging.Level;
import org.bukkit.GameRule;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import java.util.ArrayList;
import java.util.List;
import de.viper.survivalplus.util.BannerManager;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.charset.StandardCharsets;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.RegisteredServiceProvider;

public class SurvivalPlus extends JavaPlugin {

    private File langFile;
    private FileConfiguration langConfig;
    private File homesFile;
    private FileConfiguration homesConfig;
    private File gravesFile;
    private FileConfiguration gravesConfig;
    private File helpFile;
    private FileConfiguration helpConfig;
    private File backpackFile;
    private FileConfiguration backpackConfig;
    private File friendsFile;
    private FileConfiguration friendsConfig;
    private File leashesFile;
    private FileConfiguration leashesConfig;
    private File mobCapFile;
    private FileConfiguration mobCapConfig;
    
    // --- NEU: Adaptive Mob System ---
    private File mobAdaptFile;
    private FileConfiguration mobAdaptConfig;
    private AdaptiveMobListener adaptiveMobListener;
    // --------------------------------

    private FileConfiguration tablistConfig;
    private File tablistFile;
    private File nicknamesFile;
    private FileConfiguration nicknamesConfig;
    private SpawnProtectionListener spawnProtectionListener;
    private int autoClearTaskId = -1;
    private StatsManager statsManager;
    private NewbieProtectionListener newbieListener;
    private MobLeashLimitListener mobLeashLimitListener;
    private MobCapListener mobCapListener;
    private SleepListener sleepListener;
    private OreAlarmListener oreAlarmListener;
    private AFKListener afkListener;
    private GraveListener graveListener;
    private SitListener sitListener;
    private PlayerJoinListener playerJoinListener;
    private FunChallengeManager challengeManager;
    private NamespacedKey droppedKey;
    private Map<UUID, Integer> progressMap = new HashMap<>();
    private WarpManager warpManager;
    private FunChallengeManager funChallengeManager;
    private File blockedCommandsFile;
    private FileConfiguration blockedCommandsConfig;
    private LockSystem lockSystem;
    private PluginCommand pluginCommand;
    private Map<String, Claim> claims = new HashMap<>();
    private File claimsFile;
    private FileConfiguration claimsConfig;
    private Map<UUID, Integer> playerClaimCounts = new HashMap<>();
    private Map<UUID, Location> point1Selections = new HashMap<>();
    private Map<UUID, Location> point2Selections = new HashMap<>();
    private BannerManager bannerManager;
    private File debugFile;
    private PrintWriter debugWriter;
    private File consoleFile;
    private PrintWriter consoleWriter;

    // --- NEU: Vanish & Economy Support ---
    private Map<UUID, Boolean> vanishedPlayers = new HashMap<>();
    private Economy economy = null;
    private final String VANISH_META_KEY = "vanished";
    // ---------------------------------------

    public void reloadTablistConfig() {
        if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
        if (!tablistFile.exists()) {
            saveResource("tablist.yml", false);
        }
        tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
    }

    public FileConfiguration getTablistConfig() {
        if (tablistConfig == null) {
            reloadTablistConfig();
        }
        return tablistConfig;
    }

    public void reloadBlockedCommandsConfig() {
        if (blockedCommandsFile == null) blockedCommandsFile = new File(getDataFolder(), "blockedcommands.yml");
        if (!blockedCommandsFile.exists()) {
            try {
                saveResource("blockedcommands.yml", false);
            } catch (IllegalArgumentException e) {
                getLogger().warning("Die Ressource 'blockedcommands.yml' wurde nicht gefunden. Erstelle eine leere Konfiguration.");
                blockedCommandsConfig = new YamlConfiguration();
                blockedCommandsConfig.createSection("blocked-commands");
                try {
                    blockedCommandsConfig.save(blockedCommandsFile);
                } catch (IOException ex) {
                    getLogger().log(Level.SEVERE, "Fehler beim Speichern der blockedcommands.yml", ex);
                }
                return;
            }
        }
        blockedCommandsConfig = YamlConfiguration.loadConfiguration(blockedCommandsFile);
    }

    public FileConfiguration getBlockedCommandsConfig() {
        if (blockedCommandsConfig == null) {
            reloadBlockedCommandsConfig();
        }
        return blockedCommandsConfig;
    }

    public void saveBlockedCommandsConfig() {
        try {
            blockedCommandsConfig.save(blockedCommandsFile);
        } catch (IOException ignored) {}
    }

    @Override
    public void onEnable() {
        saveDefaultConfig();

        // Version aus plugin.yml
        String pluginVersion = getDescription().getVersion();

        // Sicherstellen, dass 'version:' ganz oben steht
        ensureConfigVersion(getConfig(), new File(getDataFolder(), "config.yml"), pluginVersion);
        ensureVersionAtTop(new File(getDataFolder(), "lang.yml"), pluginVersion);
        ensureVersionAtTop(new File(getDataFolder(), "help.yml"), pluginVersion);
        ensureVersionAtTop(new File(getDataFolder(), "tablist.yml"), pluginVersion);

        // Debug-Logging initialisieren
        if (getConfig().getBoolean("debug-logging", false)) {
            try {
                // Ordner erstellen
                File debugFolder = new File(getDataFolder(), "Debug");
                if (!debugFolder.exists()) {
                    debugFolder.mkdirs();
                }

                // debug.log für Fehler
                debugFile = new File(debugFolder, "debug.log");
                if (!debugFile.exists()) debugFile.createNewFile();
                debugWriter = new PrintWriter(new FileWriter(debugFile, true), true);

                // console.log für komplette Plugin-Infos
                consoleFile = new File(debugFolder, "console.log");
                if (!consoleFile.exists()) consoleFile.createNewFile();
                consoleWriter = new PrintWriter(new FileWriter(consoleFile, true), true);

                logConsole("Debug-Logging ist aktiviert. Alle Plugin-Logs werden in Debug/console.log gespeichert.");
            } catch (IOException e) {
                getLogger().warning("Konnte Debug-Dateien nicht erstellen: " + e.getMessage());
            }
        }

        int pluginId = 26886;
        Metrics metrics = new Metrics(this, pluginId);
        metrics.addCustomChart(new SimplePie(
                "default_gamemode",
                () -> Bukkit.getDefaultGameMode().toString()
        ));
        metrics.addCustomChart(new SingleLineChart(
                "online_players",
                () -> Bukkit.getOnlinePlayers().size()
        ));
        metrics.addCustomChart(new SimplePie(
                "plugin_language",
                () -> getConfig().getString("language", "default")
        ));

        bannerManager = new BannerManager(this);
        bannerManager.displayConsoleBanner(); // Banner beim Serverstart

        updateConfigFiles();
        createHomesFile();
        createGravesFile();
        createBackpackFile();
        createFriendsFile();
        createLeashesFile();
        createMobCapFile();
        createMobAdaptFile(); // NEU: Adaptive Mob File erstellen
        createNicknamesFile();
        reloadBlockedCommandsConfig();
        loadClaims();
        
        // --- NEU: Vault Economy Setup ---
        if (Bukkit.getPluginManager().getPlugin("Vault") != null) {
            RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
            if (rsp != null) {
                economy = rsp.getProvider();
                getLogger().info("Vault Economy erfolgreich verbunden.");
            } else {
                getLogger().warning("Vault Plugin gefunden, aber kein Economy Provider!");
            }
        }
        // -------------------------------------------------

        PluginManager pluginManager = getServer().getPluginManager();
        try {
            Permission notifyPerm = new Permission("survivalplus.notify", PermissionDefault.OP);
            if (pluginManager.getPermission("survivalplus.notify") == null) {
                pluginManager.addPermission(notifyPerm);
                getLogger().info("Permission survivalplus.notify erfolgreich registriert.");
            }
        } catch (Exception e) {
            getLogger().warning("Fehler beim Registrieren der Permission survivalplus.notify: " + e.getMessage());
        }
        try {
            Permission claimPerm = new Permission("survivalplus.claim.use", PermissionDefault.TRUE);
            Permission trustPerm = new Permission("survivalplus.claim.trust", PermissionDefault.TRUE);
            if (pluginManager.getPermission("survivalplus.claim.use") == null) {
                pluginManager.addPermission(claimPerm);
                getLogger().info("Permission survivalplus.claim.use erfolgreich registriert.");
            }
            if (pluginManager.getPermission("survivalplus.claim.trust") == null) {
                pluginManager.addPermission(trustPerm);
                getLogger().info("Permission survivalplus.claim.trust erfolgreich registriert.");
            }
        } catch (Exception e) {
            getLogger().warning("Fehler beim Registrieren der Claim-Permissions: " + e.getMessage());
        }
        droppedKey = new NamespacedKey(this, "droppedItem");
        funChallengeManager = new FunChallengeManager();
        funChallengeManager.load(getConfig());
        pluginManager.registerEvents(new ChallengeCollectListener(funChallengeManager, droppedKey), this);
        pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
        FriendCommand friendCommand = new FriendCommand(this, friendsConfig, langConfig, getLogger());
        getCommand("day").setExecutor(new DayCommand(this));
        getCommand("night").setExecutor(new NightCommand(this));
        CommandBlocker commandBlocker = new CommandBlocker(this);
        pluginCommand = new PluginCommand(this);
        getCommand("sp").setExecutor(pluginCommand);
        TradeManager tradeManager = new TradeManager(this);
        ReportManager reportManager = new ReportManager(this);
        getCommand("report").setExecutor(new ReportCommand(this, reportManager));
        getCommand("showreport").setExecutor(new ShowReportCommand(this, reportManager));
        getCommand("clearreport").setExecutor(new ClearReportCommand(this, reportManager));
        getCommand("trade").setExecutor(new TradeCommand(this, tradeManager));
        getCommand("tradeaccept").setExecutor(new TradeAcceptCommand(this, tradeManager));
        statsManager = new StatsManager(this);
        warpManager = new WarpManager(this);
        TablistManager tablistManager = new TablistManager(this);
        sitListener = new SitListener(this);
        afkListener = new AFKListener(this);
        graveListener = new GraveListener(this);
        playerJoinListener = new PlayerJoinListener(friendCommand);
        getCommand("gm").setExecutor(new GamemodeCommand(this));
        getCommand("sp").setExecutor(new PluginCommand(this));
        getCommand("sethome").setExecutor(new HomeCommand(this));
        getCommand("delhome").setExecutor(new HomeCommand(this));
        getCommand("homelist").setExecutor(new HomeCommand(this));
        getCommand("home").setExecutor(new HomeCommand(this));
        getCommand("inv").setExecutor(new InventoryCommand(this));
        getCommand("ec").setExecutor(new EnderchestCommand(this));
        getCommand("setspawn").setExecutor(new SetSpawnCommand(this));
        getCommand("setworldspawn").setExecutor(new SetWorldSpawnCommand(this));
        getCommand("clearchat").setExecutor(new ClearChatCommand());
        getCommand("clearitems").setExecutor(new ClearItemsCommand(this));
        getCommand("closedoors").setExecutor(new CloseDoorsCommand(this));
        getCommand("sit").setExecutor(new SitCommand(this, sitListener));
        getCommand("back").setExecutor(new BackCommand(this));
        getCommand("friend").setExecutor(friendCommand);
        getCommand("ir").setExecutor(new ItemRenameCommand(this));
        getCommand("showarmorstands").setExecutor(new ShowArmorStandsCommand(this));
        getCommand("cleardebugarmorstands").setExecutor(new ClearDebugArmorStandsCommand(this));
        getCommand("trash").setExecutor(new TrashCommand());
        getCommand("workbench").setExecutor(new WorkbenchCommand());
        getCommand("anvil").setExecutor(new AnvilCommand());
        getCommand("nick").setExecutor(new NickCommand(this));
        getCommand("shop").setExecutor(new ShopCommand(this));
        getCommand("stats").setExecutor(new StatsCommand(this, statsManager));
        getCommand("spawn").setExecutor(new SpawnCommand(this));
        getCommand("setwarp").setExecutor(new SetWarpCommand(this, warpManager));
        getCommand("warps").setExecutor(new WarpsCommand(this, warpManager));
        getCommand("delwarp").setExecutor(new DelWarpCommand(this, warpManager));
        TeleportCommands teleportCommands = new TeleportCommands(this);
        getCommand("tp").setExecutor(teleportCommands);
        getCommand("tphere").setExecutor(teleportCommands);
        getCommand("tpa").setExecutor(teleportCommands);
        getCommand("tpaccept").setExecutor(teleportCommands);
        getCommand("tpdeny").setExecutor(teleportCommands);
        getCommand("startchallenge").setExecutor(new StartFunChallengeCommand(this, funChallengeManager));
        getCommand("kit").setExecutor(new KitCommand(this));
        getCommand("heal").setExecutor(new HealCommand(this));
        getCommand("sp").setExecutor(commandBlocker);
        LootChestManager lootChestManager = new LootChestManager(this);
        pluginManager.registerEvents(lootChestManager, this);
        getCommand("lootchests").setExecutor(lootChestManager);
        getCommand("tploot").setExecutor(lootChestManager);
        getCommand("vanish").setExecutor(new AdminToolsCommand(this));
        getCommand("freeze").setExecutor(new AdminToolsCommand(this));
        getCommand("ride").setExecutor(new RideCommand(this));
        getCommand("claim").setExecutor(new ClaimCommand(this));
        
        BlockManager blockManager = new BlockManager(this);
        FileConfiguration config = getConfig();
        BackpackRecipe.register(this, langConfig);

        // NEU: Befehle registrieren
        getCommand("block").setExecutor(new BlockCommand(blockManager, getConfig()));
        getCommand("unblock").setExecutor(new UnblockCommand(blockManager, getConfig()));
        getCommand("blocklist").setExecutor(new BlockListCommand(blockManager, getConfig()));

        // --- NEU: NEUE LISTENER & COMMANDS ---
        getCommand("head").setExecutor(new HeadCommand(this));
        pluginManager.registerEvents(new HeadDropListener(this), this);
        pluginManager.registerEvents(new VanishListener(this), this);
        // ------------------------------------

        pluginManager.registerEvents(new ChatBlockListener(blockManager), this);
        pluginManager.registerEvents(new InventoryClickListener(this), this);
        pluginManager.registerEvents(sitListener, this);
        pluginManager.registerEvents(afkListener, this);
        pluginManager.registerEvents(graveListener, this);
        pluginManager.registerEvents(new BackpackListener(backpackConfig, langConfig, getLogger(), backpackFile), this);
        pluginManager.registerEvents(new StatsListener(this, statsManager), this);
        pluginManager.registerEvents(new LoginListener(this), this);
        pluginManager.registerEvents(new DebugArmorStandListener(), this);
        pluginManager.registerEvents(new ArmorStandDestroyListener(), this);
        pluginManager.registerEvents(new FirstJoinListener(), this);
        pluginManager.registerEvents(playerJoinListener, this);
        pluginManager.registerEvents(new SignColorListener(this), this);
        pluginManager.registerEvents(new SignShopListener(this), this);
        pluginManager.registerEvents(new SleepListener(this), this);
        pluginManager.registerEvents(new OreAlarmListener(this), this);
        pluginManager.registerEvents(new MobLeashLimitListener(this, getConfig()), this);
        pluginManager.registerEvents(new MobCapListener(this, getConfig()), this);
        pluginManager.registerEvents(new SpawnProtectionListener(this), this);
        pluginManager.registerEvents(new NewbieProtectionListener(this), this);
        pluginManager.registerEvents(new WarpInventoryListener(this, warpManager), this);
        pluginManager.registerEvents(new ChallengeSmeltListener(funChallengeManager), this);
        pluginManager.registerEvents(new BlockDetectionListener(this), this);
        pluginManager.registerEvents(new NickLoadListener(this), this);
        pluginManager.registerEvents(new ClaimListener(this), this);
        
        // --- NEU: Adaptive Mob Listener registrieren ---
        adaptiveMobListener = new AdaptiveMobListener(this);
        pluginManager.registerEvents(adaptiveMobListener, this);
        // -----------------------------------------

        lockSystem = new LockSystem(this);
        pluginManager.registerEvents(lockSystem, this);
        getCommand("splock").setExecutor(lockSystem);
        getCommand("sp").setExecutor(new CommandExecutor() {
            @Override
            public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
                if (!command.getName().equalsIgnoreCase("sp")) {
                    return false;
                }
                if (args.length == 0) {
                    return pluginCommand.onCommand(sender, command, label, args);
                }
                String subCommand = args[0].toLowerCase();
                if (subCommand.equals("cb")) {
                    return commandBlocker.onCommand(sender, command, label, args);
                } else if (subCommand.equals("lock") || subCommand.equals("unlock") || 
                           subCommand.equals("friendadd") || subCommand.equals("friendremove")) {
                    return lockSystem.onCommand(sender, command, label, args);
                }
                return pluginCommand.onCommand(sender, command, label, args);
            }
        });
        pluginManager.registerEvents(new RepairSignListener(getConfig(), getLangConfig()), this);
        pluginManager.registerEvents(new ToolUpgradeListener(this), this);
        registerTabCompleters();
        startAutoClearTask();
        spawnArmorStandExample();
        getLogger().info(getMessage("plugin.enabled"));
        if (getConfig().getBoolean("set-keepinventory", true)) {
            Bukkit.getScheduler().runTaskLater(this, () -> {
                if (Bukkit.getWorlds().isEmpty()) return;
                Bukkit.getWorlds().forEach(world -> {
                    world.setGameRule(GameRule.KEEP_INVENTORY, false);
                    logDebug("Gamerule keepInventory in Welt '" + world.getName() + "' wurde auf false gesetzt.");
                });
            }, 20L);
        }
        if (getConfig().getBoolean("force-survival", true)) {
            pluginManager.registerEvents(new ForceSurvivalListener(this), this);
            logDebug("Force-Survival ist aktiv. Spieler werden beim Joinen in Survival gesetzt.");
        }
        try {
            if (tablistFile == null) tablistFile = new File(getDataFolder(), "tablist.yml");
            if (!tablistFile.exists()) {
                saveResource("tablist.yml", false);
            }
            tablistConfig = YamlConfiguration.loadConfiguration(tablistFile);
            InputStream defStream = getResource("tablist.yml");
            if (defStream != null) {
                tablistConfig.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(defStream)));
            }
            logDebug("Animierte Tablist wurde geladen!");
        } catch (Exception e) {
            getLogger().log(Level.WARNING, "Fehler beim Laden der Tablist-Konfiguration", e);
        }
        Bukkit.getScheduler().runTaskLater(this, this::applyBlockRules, 20L);
    }

    public void applyBlockRules() {
        boolean cmdAllowed = getConfig().getBoolean("blocks.command-blocks.enabled", true);
        boolean structAllowed = getConfig().getBoolean("blocks.structure-blocks.enabled", true);
        for (World world : Bukkit.getWorlds()) {
            try {
                world.setGameRule(GameRule.COMMAND_BLOCK_OUTPUT, cmdAllowed);
            } catch (NoSuchMethodError | NoClassDefFoundError e) {
                world.setGameRuleValue(GameRule.COMMAND_BLOCK_OUTPUT.getName(), Boolean.toString(cmdAllowed));
            }
            logDebug("Gamerule commandBlockOutput in Welt '" + world.getName() + "' gesetzt auf " + cmdAllowed);
        }
        removeForbiddenBlocksFromInventories(cmdAllowed, structAllowed);
        logDebug("Block-Regeln angewendet: CommandBlocks erlaubt=" + cmdAllowed + ", StructureBlocks erlaubt=" + structAllowed);
    }

    private void ensureVersionAtTop(File file, String version) {
        try {
            if (!file.exists()) return; // Datei existiert nicht
            List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);

            if (!lines.isEmpty() && lines.get(0).startsWith("version:")) {
                // Alte Versionsnummer ersetzen
                lines.set(0, "version: " + version);
            } else {
                // Version an den Anfang setzen
                lines.add(0, "version: " + version);
            }

            Files.write(file.toPath(), lines, StandardCharsets.UTF_8);
        } catch (IOException e) {
            getLogger().warning("Konnte Version in " + file.getName() + " nicht setzen: " + e.getMessage());
        }
    }

/**
 * Speziell für config.yml:
 * - Setzt die Version in der geladenen FileConfiguration (getConfig()) und speichert sie,
 * - und sorgt anschließend dafür, dass die 'version:'-Zeile ganz oben in der Datei steht.
 */
private void ensureConfigVersion(FileConfiguration config, File file, String version) {
    try {
        if (!file.exists()) return; // nichts zu tun, Datei existiert nicht

        // 1) Version in der geladenen Config setzen und speichern (Bukkit nutzt diese Config im Speicher)
        String current = config.getString("version", "");
        if (!version.equals(current)) {
            config.set("version", version);
            try {
                config.save(file);
            } catch (IOException e) {
                getLogger().warning("Konnte config.yml nicht speichern: " + e.getMessage());
            }
        }

        // 2) Text-Nachbearbeitung: sicherstellen, dass 'version:' als erste Zeile steht
        List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);

        // Entferne alle vorhandenen version:-Zeilen (falls irgendwo)
        int foundIndex = -1;
        for (int i = 0; i < lines.size(); i++) {
            if (lines.get(i).trim().startsWith("version:")) {
                foundIndex = i;
                break;
            }
        }

        if (foundIndex == 0) {
            // bereits oben -> ersetzen
            lines.set(0, "version: " + version);
        } else {
            // entferne alte Stelle (wenn vorhanden)
            if (foundIndex > 0) {
                lines.remove(foundIndex);
            }
            // füge neue version ganz oben ein
            lines.add(0, "version: " + version);
        }

        Files.write(file.toPath(), lines, StandardCharsets.UTF_8);
        logDebug("config.yml: Version oben gesetzt auf " + version);
    } catch (IOException e) {
        getLogger().warning("Konnte Version in config.yml nicht setzen: " + e.getMessage());
    }
}

    private void removeForbiddenBlocksFromInventories(boolean cmdAllowed, boolean structAllowed) {
        for (Player p : Bukkit.getOnlinePlayers()) {
            if (p.hasPermission("survivalplus.notify")) {
                continue;
            }
            Inventory inv = p.getInventory();
            boolean removedCommandBlock = false;
            boolean removedStructureBlock = false;
            if (!cmdAllowed && inv.contains(Material.COMMAND_BLOCK)) {
                inv.remove(Material.COMMAND_BLOCK);
                removedCommandBlock = true;
                p.sendMessage(ChatColor.RED + "[SurvivalPlus] Command-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
            }
            if (!structAllowed && inv.contains(Material.STRUCTURE_BLOCK)) {
                inv.remove(Material.STRUCTURE_BLOCK);
                removedStructureBlock = true;
                p.sendMessage(ChatColor.RED + "[SurvivalPlus] Structure-Blöcke wurden aus deinem Inventar entfernt, da sie deaktiviert sind.");
            }
            if ((removedCommandBlock || removedStructureBlock) && getConfig().getBoolean("blocks.notify-admins-on-possession", true)) {
                notifyAdmins(p.getName(), removedCommandBlock, removedStructureBlock);
            }
        }
    }

    private void notifyAdmins(String playerName, boolean hadCommandBlock, boolean hadStructureBlock) {
        String baseTag = ChatColor.GRAY + "[" + ChatColor.GREEN + "SurvivalPlus" + ChatColor.GRAY + "] ";
        for (Player admin : Bukkit.getOnlinePlayers()) {
            if (admin.hasPermission("survivalplus.notify")) {
                if (hadCommandBlock) {
                    admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
                            ChatColor.RED + " hatte einen Command-Block im Inventar, der entfernt wurde.");
                }
                if (hadStructureBlock) {
                    admin.sendMessage(baseTag + ChatColor.RED + "Spieler " + ChatColor.YELLOW + playerName +
                            ChatColor.RED + " hatte einen Structure-Block im Inventar, der entfernt wurde.");
                }
            }
        }
    }

    // === Claims.yml ===
    private void createClaimsFile() {
        claimsFile = new File(getDataFolder(), "claims.yml");
        if (!claimsFile.exists()) {
            try {
                claimsFile.createNewFile();
            } catch (IOException e) {
                getLogger().log(Level.SEVERE, "Fehler beim Erstellen der claims.yml", e);
            }
        }
        claimsConfig = YamlConfiguration.loadConfiguration(claimsFile);
    }

    private void loadClaims() {
        createClaimsFile();
        for (String key : claimsConfig.getKeys(false)) {
            try {
                UUID owner = UUID.fromString(claimsConfig.getString(key + ".owner"));
                String worldName = claimsConfig.getString(key + ".world");
                int x1 = claimsConfig.getInt(key + ".x1");
                int z1 = claimsConfig.getInt(key + ".z1");
                int x2 = claimsConfig.getInt(key + ".x2");
                int z2 = claimsConfig.getInt(key + ".z2");
                Claim claim = new Claim(owner, worldName, x1, z1, x2, z2);
                List<String> trustedList = claimsConfig.getStringList(key + ".trusted");
                for (String trustedStr : trustedList) {
                    claim.addTrusted(UUID.fromString(trustedStr));
                }
                claims.put(key, claim);
                playerClaimCounts.merge(owner, 1, Integer::sum);
            } catch (Exception e) {
                getLogger().warning("Invalid claim data for key: " + key);
            }
        }
    }

    public void saveClaims() {
        for (Map.Entry<String, Claim> entry : claims.entrySet()) {
            String key = entry.getKey();
            Claim claim = entry.getValue();
            claimsConfig.set(key + ".owner", claim.getOwner().toString());
            claimsConfig.set(key + ".x1", claim.getX1());
            claimsConfig.set(key + ".z1", claim.getZ1());
            claimsConfig.set(key + ".x2", claim.getX2());
            claimsConfig.set(key + ".z2", claim.getZ2());
            claimsConfig.set(key + ".world", claim.getWorldName());
            List<String> trustedList = new ArrayList<>();
            for (UUID trusted : claim.getTrusted()) {
                trustedList.add(trusted.toString());
            }
            claimsConfig.set(key + ".trusted", trustedList);
        }
        try {
            claimsConfig.save(claimsFile);
        } catch (IOException e) {
            getLogger().log(Level.SEVERE, "Fehler beim Speichern der claims.yml", e);
        }
    }

    public Claim getClaim(Location location) {
        for (Claim claim : claims.values()) {
            if (claim.isInside(location)) {
                return claim;
            }
        }
        return null;
    }

    public void addClaim(Claim claim, Player player) {
        String key = claim.getWorldName() + ":" + claim.getX1() + ":" + claim.getZ1() + ":" + claim.getX2() + ":" + claim.getZ2();
        claims.put(key, claim);
        playerClaimCounts.merge(player.getUniqueId(), 1, Integer::sum);
        saveClaims();
    }

    public void removeClaim(Location location, Player player) {
        String key = null;
        for (Map.Entry<String, Claim> entry : claims.entrySet()) {
            if (entry.getValue().isInside(location)) {
                key = entry.getKey();
                break;
            }
        }
        if (key != null) {
            claims.remove(key);
            playerClaimCounts.merge(player.getUniqueId(), -1, Integer::sum);
            saveClaims();
        }
    }

    public void removeClaimByKey(String key, UUID playerUUID) {
        claims.remove(key);
        playerClaimCounts.merge(playerUUID, -1, Integer::sum);
        saveClaims();
    }

    public Map<String, Claim> getClaims() {
        return claims;
    }

    public int getClaimCount(Player player) {
        return playerClaimCounts.getOrDefault(player.getUniqueId(), 0);
    }

    public void setPoint1(Player player, Location location) {
        point1Selections.put(player.getUniqueId(), location);
    }

    public void setPoint2(Player player, Location location) {
        point2Selections.put(player.getUniqueId(), location);
    }

    public Location getPoint1(Player player) {
        return point1Selections.get(player.getUniqueId());
    }

    public Location getPoint2(Player player) {
        return point2Selections.get(player.getUniqueId());
    }

    public void clearSelections(Player player) {
        point1Selections.remove(player.getUniqueId());
        point2Selections.remove(player.getUniqueId());
    }

    public boolean hasOverlap(Claim newClaim) {
        for (Claim existingClaim : claims.values()) {
            if (existingClaim.overlaps(newClaim)) {
                return true;
            }
        }
        return false;
    }

    // --- NEU: Delete Claim Methode ---
    public void deleteClaim(Claim claim) {
        String key = getClaimKey(claim);
        if (key != null) {
            claims.remove(key);
            playerClaimCounts.merge(claim.getOwner(), -1, Integer::sum);
            saveClaims();
        }
    }

    private String getClaimKey(Claim claim) {
        for (Map.Entry<String, Claim> entry : claims.entrySet()) {
            if (entry.getValue() == claim) {
                return entry.getKey();
            }
        }
        return null;
    }
    // -----------------------------

    // WICHTIG: Getter für Claim Config für Ban-System
    public FileConfiguration getClaimsConfig() {
        return claimsConfig;
    }


    // Methoden für nicknames.yml
    public void createNicknamesFile() {
        nicknamesFile = new File(getDataFolder(), "nicknames.yml");
        if (!nicknamesFile.exists()) {
            try {
                nicknamesFile.getParentFile().mkdirs();
                nicknamesFile.createNewFile();
            } catch (IOException e) {
                getLogger().severe("Konnte nicknames.yml nicht erstellen!");
                e.printStackTrace();
            }
        }
        nicknamesConfig = YamlConfiguration.loadConfiguration(nicknamesFile);
    }

    public FileConfiguration getNicknamesConfig() {
        return nicknamesConfig;
    }

    public void saveNicknamesConfig() {
        try {
            nicknamesConfig.save(nicknamesFile);
        } catch (IOException e) {
            getLogger().severe("Konnte nicknames.yml nicht speichern!");
            e.printStackTrace();
        }
    }

    private void spawnArmorStandExample() {
        World world = Bukkit.getWorld("world");
        if (world == null) {
            getLogger().warning("Welt 'world' nicht gefunden, ArmorStand wird nicht gespawnt.");
            return;
        }

        Location loc = new Location(world, 0.5, 100, 0.5);
        ArmorStand armorStand = world.spawn(loc, ArmorStand.class);
        armorStand.setVisible(false);
        armorStand.setCustomName(ChatColor.GREEN + "Mein ArmorStand");
        armorStand.setCustomNameVisible(true);
        armorStand.setGravity(false);
        armorStand.setMarker(true);
        armorStand.addScoreboardTag("debugArmorStand");
    }

    @Override
    public void onDisable() {
        if (debugWriter != null) {
            debugWriter.close();
        }
        if (autoClearTaskId != -1) {
            Bukkit.getScheduler().cancelTask(autoClearTaskId);
        }
        saveStats();
        saveLeashesConfig();
        saveMobCapConfig();
        saveMobAdaptConfig(); // NEU: Adaptive Mob Config speichern

        // NEU: NewbieProtection-Daten sichern
        if (newbieListener != null) {
            newbieListener.saveData();
        }

        getLogger().info(getMessage("plugin.disabled"));
    }

    public void saveStats() {
        if (statsManager != null) {
            statsManager.saveStats();
        }
    }

    public String getPluginInfo() {
        return ChatColor.translateAlternateColorCodes('&', getMessage("plugin.info"));
    }

    // === Config Updating Logic ===
    private void updateConfigFiles() {
        updateConfigFile("config.yml");
        updateConfigFile("lang.yml");
        updateConfigFile("help.yml");
    }

    private void updateConfigFile(String fileName) {
        File file = new File(getDataFolder(), fileName);
        FileConfiguration currentConfig = YamlConfiguration.loadConfiguration(file);
        InputStream defaultStream = getResource(fileName);

        if (defaultStream == null) {
            getLogger().warning(fileName + " nicht im JAR gefunden. Erstelle leere Datei.");
            if (!file.exists()) {
                try {
                    file.createNewFile();
                    if (fileName.equals("config.yml")) {
                        saveDefaultConfig();
                    } else if (fileName.equals("lang.yml")) {
                        createLangFile();
                    } else if (fileName.equals("help.yml")) {
                        createHelpFile();
                    }
                } catch (IOException e) {
                    getLogger().severe("Fehler beim Erstellen der " + fileName + ": " + e.getMessage());
                }
                return;
            }
        }

        FileConfiguration defaultConfig = defaultStream != null ?
                YamlConfiguration.loadConfiguration(new InputStreamReader(defaultStream)) : new YamlConfiguration();

        // Merge default config into current config
        mergeConfigs(defaultConfig, currentConfig);

        // Save updated config
        try {
            currentConfig.save(file);
            logDebug(fileName + " erfolgreich aktualisiert.");
        } catch (IOException e) {
            getLogger().severe("Fehler beim Speichern der " + fileName + ": " + e.getMessage());
        }

        // Update instance variables
        if (fileName.equals("config.yml")) {
            reloadConfig();
        } else if (fileName.equals("lang.yml")) {
            langFile = file;
            langConfig = currentConfig;
        } else if (fileName.equals("help.yml")) {
            helpFile = file;
            helpConfig = currentConfig;
        }
    }

    private void mergeConfigs(FileConfiguration defaultConfig, FileConfiguration currentConfig) {
        for (String key : defaultConfig.getKeys(true)) {
            if (!currentConfig.contains(key)) {
                currentConfig.set(key, defaultConfig.get(key));
            } else if (defaultConfig.isConfigurationSection(key) && currentConfig.isConfigurationSection(key)) {
                // Rekursiv für Untersektionen
                mergeConfigs(defaultConfig.getConfigurationSection(key), currentConfig.getConfigurationSection(key));
            }
        }
    }

    private void mergeConfigs(ConfigurationSection defaultSection, ConfigurationSection currentSection) {
        for (String key : defaultSection.getKeys(false)) {
            if (!currentSection.contains(key)) {
                currentSection.set(key, defaultSection.get(key));
            } else if (defaultSection.isConfigurationSection(key) && currentSection.isConfigurationSection(key)) {
                mergeConfigs(defaultSection.getConfigurationSection(key), currentSection.getConfigurationSection(key));
            }
        }
    }

    // === Lang.yml ===
    private void createLangFile() {
        langFile = new File(getDataFolder(), "lang.yml");
        if (!langFile.exists()) {
            saveResource("lang.yml", false);
        }
        langConfig = YamlConfiguration.loadConfiguration(langFile);
    }

    public String getMessage(String key) {
        String message = langConfig.getString(key);
        if (message == null) {
            getLogger().warning("Fehlender Sprachschlüssel: " + key);
            return ChatColor.RED + "[Missing lang key: " + key + "]";
        }
        return ChatColor.translateAlternateColorCodes('&', message);
    }

    public void reloadLangConfig() {
        updateConfigFile("lang.yml");
    }

    public FileConfiguration getLangConfig() {
        return langConfig;
    }

    // === Homes.yml ===
    private void createHomesFile() {
        homesFile = new File(getDataFolder(), "homes.yml");
        if (!homesFile.exists()) {
            try {
                homesFile.createNewFile();
                getLogger().info("homes.yml wurde erstellt.");
            } catch (IOException e) {
                getLogger().severe("Fehler beim Erstellen der homes.yml: " + e.getMessage());
            }
        }
        homesConfig = YamlConfiguration.loadConfiguration(homesFile);
    }

    public FileConfiguration getHomesConfig() {
        return homesConfig;
    }

    public void saveHomesConfig() {
        try {
            homesConfig.save(homesFile);
            getLogger().info("homes.yml erfolgreich gespeichert.");
        } catch (IOException e) {
            getLogger().log(Level.SEVERE, "Fehler beim Speichern der homes.yml: " + e.getMessage());
        }
    }

    public void reloadHomesConfig() {
        homesConfig = YamlConfiguration.loadConfiguration(homesFile);
        getLogger().info("homes.yml erfolgreich neu geladen.");
    }

    // === Graves.yml ===
    private void createGravesFile() {
        gravesFile = new File(getDataFolder(), "graves.yml");
        if (!gravesFile.exists()) {
            try {
                gravesFile.createNewFile();
                getLogger().info("graves.yml wurde erstellt.");
            } catch (IOException e) {
                getLogger().severe("Fehler beim Erstellen der graves.yml: " + e.getMessage());
            }
        }
        gravesConfig = YamlConfiguration.loadConfiguration(gravesFile);
    }

    public FileConfiguration getGravesConfig() {
        return gravesConfig;
    }

    public void saveGravesConfig() {
        try {
            gravesConfig.save(gravesFile);
            getLogger().info("graves.yml erfolgreich gespeichert.");
        } catch (IOException e) {
            getLogger().log(Level.SEVERE, "Fehler beim Speichern der graves.yml: " + e.getMessage());
        }
    }

    public void reloadGravesConfig() {
        gravesConfig = YamlConfiguration.loadConfiguration(gravesFile);
        getLogger().info("graves.yml erfolgreich neu geladen.");
    }

    // === Help.yml ===
    private void createHelpFile() {
        helpFile = new File(getDataFolder(), "help.yml");
        if (!helpFile.exists()) {
            try {
                InputStream resource = getResource("help.yml");
                if (resource != null) {
                    saveResource("help.yml", false);
                } else {
                    getLogger().warning("help.yml nicht im JAR gefunden. Erstelle leere Datei.");
                    helpConfig = new YamlConfiguration();
                    helpConfig.set("header", "§6=== SurvivalPlus Hilfe ===");
                    helpConfig.set("footer", "§6=====================");
                    helpConfig.save(helpFile);
                }
            } catch (IOException e) {
                getLogger().severe("Fehler beim Erstellen der help.yml: " + e.getMessage());
            }
        }
        helpConfig = YamlConfiguration.loadConfiguration(helpFile);
    }

    public FileConfiguration getHelpConfig() {
        return helpConfig;
    }

    public void reloadHelpConfig() {
        updateConfigFile("help.yml");
    }

    // === Backpack.yml ===
    private void createBackpackFile() {
        backpackFile = new File(getDataFolder(), "backpacks.yml");
        if (!backpackFile.exists()) {
            try {
                backpackFile.createNewFile();
                getLogger().info("backpacks.yml wurde erstellt.");
            } catch (IOException e) {
                getLogger().severe("Fehler beim Erstellen der backpacks.yml: " + e.getMessage());
            }
        }
        backpackConfig = YamlConfiguration.loadConfiguration(backpackFile);
    }

    public FileConfiguration getBackpackConfig() {
        return backpackConfig;
    }

    public void saveBackpackConfig() {
        try {
            backpackConfig.save(backpackFile);
            getLogger().info("backpacks.yml erfolgreich gespeichert.");
        } catch (IOException e) {
            getLogger().log(Level.SEVERE, "Fehler beim Speichern der backpacks.yml: " + e.getMessage());
        }
    }

    public void reloadBackpackConfig() {
        backpackConfig = YamlConfiguration.loadConfiguration(backpackFile);
        getLogger().info("backpacks.yml erfolgreich neu geladen.");
    }

    // === Friends.yml ===
    private void createFriendsFile() {
        friendsFile = new File(getDataFolder(), "friends.yml");
        if (!friendsFile.exists()) {
            try {
                friendsFile.createNewFile();
                getLogger().info("friends.yml wurde erstellt.");
            } catch (IOException e) {
                getLogger().severe("Fehler beim Erstellen der friends.yml: " + e.getMessage());
            }
        }
        friendsConfig = YamlConfiguration.loadConfiguration(friendsFile);
    }

    public FileConfiguration getFriendsConfig() {
        return friendsConfig;
    }

    public void saveFriendsConfig() {
        try {
            friendsConfig.save(friendsFile);
            getLogger().info("friends.yml erfolgreich gespeichert.");
        } catch (IOException e) {
            getLogger().log(Level.SEVERE, "Fehler beim Speichern der friends.yml: " + e.getMessage());
        }
    }

    public void reloadFriendsConfig() {
        friendsConfig = YamlConfiguration.loadConfiguration(friendsFile);
        getLogger().info("friends.yml erfolgreich neu geladen.");
    }

    // === Leashes.yml ===
    private void createLeashesFile() {
        leashesFile = new File(getDataFolder(), "leashes.yml");
        if (!leashesFile.exists()) {
            try {
                leashesFile.createNewFile();
                logDebug("leashes.yml wurde erstellt.");
            } catch (IOException e) {
                getLogger().severe("Fehler beim Erstellen der leashes.yml: " + e.getMessage());
            }
        }
        leashesConfig = YamlConfiguration.loadConfiguration(leashesFile);
    }

    public FileConfiguration getLeashesConfig() {
        return leashesConfig;
    }

    public void saveLeashesConfig() {
        try {
            leashesConfig.save(leashesFile);
            logDebug("leashes.yml erfolgreich gespeichert.");
        } catch (IOException e) {
            getLogger().log(Level.SEVERE, "Fehler beim Speichern der leashes.yml: " + e.getMessage());
        }
    }

    public void reloadLeashesConfig() {
        leashesConfig = YamlConfiguration.loadConfiguration(leashesFile);
        logDebug("leashes.yml erfolgreich neu geladen.");
    }

    // === MobCap.yml ===
    private void createMobCapFile() {
        mobCapFile = new File(getDataFolder(), "mobcap.yml");
        if (!mobCapFile.exists()) {
            try {
                mobCapFile.createNewFile();
                logDebug("mobcap.yml wurde erstellt.");
            } catch (IOException e) {
                getLogger().severe("Fehler beim Erstellen der mobcap.yml: " + e.getMessage());
            }
        }
        mobCapConfig = YamlConfiguration.loadConfiguration(mobCapFile);
    }

    public FileConfiguration getMobCapConfig() {
        return mobCapConfig;
    }

    public void saveMobCapConfig() {
        try {
            mobCapConfig.save(mobCapFile);
            logDebug("mobcap.yml erfolgreich gespeichert.");
        } catch (IOException e) {
            getLogger().log(Level.SEVERE, "Fehler beim Speichern der mobcap.yml: " + e.getMessage());
        }
    }

    public void reloadMobCapConfig() {
        mobCapConfig = YamlConfiguration.loadConfiguration(mobCapFile);
        logDebug("mobcap.yml erfolgreich neu geladen.");
    }

    // === NEU: MobAdapt.yml ===
    private void createMobAdaptFile() {
        mobAdaptFile = new File(getDataFolder(), "mobadapt.yml");
        if (!mobAdaptFile.exists()) {
            try {
                mobAdaptFile.createNewFile();
                getLogger().info("mobadapt.yml wurde erstellt.");
            } catch (IOException e) {
                getLogger().severe("Fehler beim Erstellen der mobadapt.yml: " + e.getMessage());
            }
        }
        mobAdaptConfig = YamlConfiguration.loadConfiguration(mobAdaptFile);
    }

    public FileConfiguration getMobAdaptConfig() {
        return mobAdaptConfig;
    }

    public void saveMobAdaptConfig() {
        try {
            mobAdaptConfig.save(mobAdaptFile);
        } catch (IOException e) {
            getLogger().log(Level.SEVERE, "Fehler beim Speichern der mobadapt.yml: " + e.getMessage());
        }
    }
    // ===========================

    // === AutoClearTask ===
    private void startAutoClearTask() {
        if (autoClearTaskId != -1) {
            Bukkit.getScheduler().cancelTask(autoClearTaskId);
            autoClearTaskId = -1;
        }

        if (getConfig().getBoolean("auto-clear-enabled", true)) {
            int intervalMinutes = getConfig().getInt("auto-clear-interval-minutes", 15);
            int intervalTicks = intervalMinutes * 60 * 20; // Minuten in Ticks umrechnen
            if (intervalTicks > 0) {
                autoClearTaskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new AutoClearTask(this), intervalTicks, intervalTicks);
                logDebug("AutoClearTask gestartet mit Intervall von " + intervalMinutes + " Minuten.");
            }
        } else {
            logDebug("AutoClearTask deaktiviert, da auto-clear-enabled auf false gesetzt ist.");
        }
    }

    // === Reload Plugin ===
    public void reloadPlugin() {
        try {
            // Config-Dateien aktualisieren
            updateConfigFiles();
            reloadBackpackConfig();
            reloadFriendsConfig();
            reloadHomesConfig();
            reloadGravesConfig();
            reloadLeashesConfig();
            reloadMobCapConfig();

            // AutoClearTask neu starten
            startAutoClearTask();

            // Bestehende Listener abmelden
            PluginManager pm = getServer().getPluginManager();
            HandlerList.unregisterAll(this);

            // FriendCommand instanzieren für PlayerJoinListener
            FriendCommand friendCommand = new FriendCommand(this, friendsConfig, langConfig, getLogger());

            // Listener neu erstellen und registrieren
            mobLeashLimitListener = new MobLeashLimitListener(this, getConfig());
            mobLeashLimitListener.reloadConfig(getConfig());
            pm.registerEvents(mobLeashLimitListener, this);

            mobCapListener = new MobCapListener(this, getConfig());
            mobCapListener.reloadConfig(getConfig());
            pm.registerEvents(mobCapListener, this);

            sleepListener = new SleepListener(this);
            sleepListener.reloadConfig(getConfig());
            pm.registerEvents(sleepListener, this);

            oreAlarmListener = new OreAlarmListener(this);
            oreAlarmListener.reloadConfig(getConfig());
            pm.registerEvents(oreAlarmListener, this);

            afkListener = new AFKListener(this);
            afkListener.reloadConfig(getConfig());
            pm.registerEvents(afkListener, this);

            graveListener = new GraveListener(this);
            graveListener.reloadConfig(getConfig());
            pm.registerEvents(graveListener, this);

            sitListener = new SitListener(this);
            pm.registerEvents(sitListener, this);

            playerJoinListener = new PlayerJoinListener(friendCommand);
            pm.registerEvents(playerJoinListener, this);

            pm.registerEvents(new InventoryClickListener(this), this);
            pm.registerEvents(new BackpackListener(backpackConfig, langConfig, getLogger(), backpackFile), this);
            pm.registerEvents(new StatsListener(this, statsManager), this);
            pm.registerEvents(new LoginListener(this), this);
            pm.registerEvents(new DebugArmorStandListener(), this);
            pm.registerEvents(new ArmorStandDestroyListener(), this);
            pm.registerEvents(new FirstJoinListener(), this);

            spawnProtectionListener = new SpawnProtectionListener(this);
            pm.registerEvents(spawnProtectionListener, this);

            LockSystem lockSystem = new LockSystem(this);
            pm.registerEvents(lockSystem, this);
            getCommand("splock").setExecutor(lockSystem);

            // Commands neu registrieren
            getCommand("friend").setExecutor(friendCommand);

            registerTabCompleters();

            getLogger().info(getMessage("plugin.reloaded"));
        } catch (Exception e) {
            getLogger().severe("Fehler beim Neuladen des Plugins: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public BannerManager getBannerManager() {
        return bannerManager;
    }

    public WarpManager getWarpManager() {
        return warpManager;
    }

    public FunChallengeManager getFunChallengeManager() {
        return funChallengeManager;
    }

    // Nur Fehler/Exceptions
    public void log(String msg) {
        if (getConfig().getBoolean("debug-logging", false) && debugWriter != null) {
            debugWriter.println("[" + new java.util.Date() + "] " + msg);
        } else {
            getLogger().info(msg);
        }
    }

    private void registerTabCompleters() {
        SurvivalPlusTabCompleter completer = new SurvivalPlusTabCompleter(this);
        String[] commands = {
                "sp", "ir", "gm", "sethome", "delhome", "homelist", "home", "inv", "ec",
                "setworldspawn", "setspawn", "clearchat", "clearitems", "closedoors", "sit",
                "back", "friend", "stats", "showarmorstands", "cleardebugarmorstands", "trash",
                "workbench", "anvil", "leashcount", "splock", "tp", "tphere", "tpa",
                "tpaccept", "tpdeny", "block", "unblock", "blocklist", "kit", "nick", "ride",
                "vanish", "freeze", "lootchests", "tploot", "day", "night", "trade", "tradeaccept",
                "report", "showreport", "clearreport", "shop", "spawn", "setwarp", "delwarp",
                "warps", "startchallenge", "heal", "claim", "head"
        };
        for (String name : commands) {
            if (getCommand(name) != null) {
                getCommand(name).setTabCompleter(completer);
            }
        }
    }

    public void logError(String msg, Throwable t) {
        if (getConfig().getBoolean("debug-logging", false) && debugWriter != null) {
            debugWriter.println("[" + new java.util.Date() + "] ERROR: " + msg);
            t.printStackTrace(debugWriter);
        } else {
            getLogger().log(Level.SEVERE, msg, t);
        }
    }

    public void logDebug(String msg) {
        if (!getConfig().getBoolean("debug-logging", false)) {
            return;
        }
        if (debugWriter != null) {
            debugWriter.println("[" + new java.util.Date() + "] " + msg);
        }
        getLogger().info(msg);
    }

    // Komplette Plugin-Logs in console.log
    public void logConsole(String msg) {
        if (getConfig().getBoolean("debug-logging", false) && consoleWriter != null) {
            consoleWriter.println("[" + new java.util.Date() + "] " + msg);
        }
        getLogger().info(msg); // Optional: zusätzlich Konsole ausgeben
    }

    // --- NEU: HELFERMETHODEN FÜR NEUE FEATURES ---

    // Vanish
    public void setVanished(UUID uuid, boolean vanished) {
        if (vanished) {
            vanishedPlayers.put(uuid, true);
        } else {
            vanishedPlayers.remove(uuid);
        }
    }

    public boolean isVanished(UUID uuid) {
        return vanishedPlayers.containsKey(uuid) && vanishedPlayers.get(uuid);
    }

    public Map<UUID, Boolean> getVanishedPlayers() {
        return vanishedPlayers;
    }

    // Economy
    public Economy getEconomy() {
        return economy;
    }

    // ProtocolLib Bridge (für Silent Vanish)
    public ProtocolManager getProtocolManager() {
        return ProtocolLibrary.getProtocolManager();
    }

}