package net.viper.status.modules.commandblocker;

import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ChatEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
import net.viper.status.StatusAPI;
import net.viper.status.module.Module;
import net.viper.status.ratelimit.GlobalRateLimitFramework;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import org.yaml.snakeyaml.Yaml;

@SuppressWarnings({"unchecked", "rawtypes"})
public class CommandBlockerModule implements Module, Listener {

    private StatusAPI plugin;
    private boolean enabled = true; // Standardm\u00e4\u00dfig aktiv
    private String bypassPermission = "commandblocker.bypass"; // Standard Permission

    private File file;
    private Set<String> blocked = new HashSet<>();
    private final GlobalRateLimitFramework rateLimiter = GlobalRateLimitFramework.getInstance();

    private boolean commandRateLimitEnabled = true;
    private long commandRateLimitWindowMs = 3000L;
    private int commandRateLimitMaxActions = 8;
    private long commandRateLimitBlockMs = 6000L;
    private String commandRateLimitMessage = "&cZu viele Befehle in kurzer Zeit. Bitte warte kurz.";

    @Override
    public String getName() {
        return "CommandBlockerModule";
    }

    @Override
    public void onEnable(Plugin plugin) {
        if (!(plugin instanceof StatusAPI)) return; // Sicherheit
        this.plugin = (StatusAPI) plugin;

        // Datei laden
        file = new File(this.plugin.getDataFolder(), "blocked-commands.yml");
        loadFile();

        // Listener registrieren
        ProxyServer.getInstance().getPluginManager().registerListener(this.plugin, this);

        // /cb Befehl registrieren
        ProxyServer.getInstance().getPluginManager().registerCommand(this.plugin,
                new net.md_5.bungee.api.plugin.Command("cb", "commandblocker.admin") {
                    @Override
                    public void execute(CommandSender sender, String[] args) {
                        handleCommand(sender, args);
                    }
                });

        this.plugin.getLogger().fine("[CommandBlocker] aktiviert (" + blocked.size() + " Commands).");
    }


    @Override
    public void onDisable(Plugin plugin) {
        blocked.clear();
    }

    @EventHandler
    public void onCommand(ChatEvent event) {
        if (!enabled || !event.isCommand()) return;

        if (!(event.getSender() instanceof ProxiedPlayer)) return;
        ProxiedPlayer player = (ProxiedPlayer) event.getSender();

        if (player.hasPermission(bypassPermission)) return;

        String msg = event.getMessage();
        if (msg == null || msg.length() <= 1) return;

        if (commandRateLimitEnabled) {
            GlobalRateLimitFramework.Result result = rateLimiter.check(
                "chat.command",
                player.getUniqueId().toString(),
                new GlobalRateLimitFramework.Rule(
                    true,
                    commandRateLimitWindowMs,
                    commandRateLimitMaxActions,
                    commandRateLimitBlockMs
                )
            );

            if (result.isBlocked()) {
            event.setCancelled(true);
            player.sendMessage(ChatColor.translateAlternateColorCodes('&', commandRateLimitMessage));
            return;
            }
        }

        String cmd = msg.substring(1).toLowerCase(Locale.ROOT);
        String base = cmd.split(" ")[0];

        if (blocked.contains(base)) {
            event.setCancelled(true);
            player.sendMessage(ChatColor.RED + "Dieser Befehl ist auf diesem Netzwerk blockiert.");
        }
    }

    private void handleCommand(CommandSender sender, String[] args) {
        if (args == null || args.length == 0) {
            sender.sendMessage(ChatColor.YELLOW + "/cb add <command>");
            sender.sendMessage(ChatColor.YELLOW + "/cb remove <command>");
            sender.sendMessage(ChatColor.YELLOW + "/cb list");
            sender.sendMessage(ChatColor.YELLOW + "/cb reload");
            return;
        }

        String action = args[0].toLowerCase();

        switch (action) {
            case "add":
                if (args.length < 2) break;
                blocked.add(args[1].toLowerCase());
                saveFile();
                sender.sendMessage(ChatColor.GREEN + "Command blockiert: " + args[1]);
                break;
            case "remove":
                if (args.length < 2) break;
                blocked.remove(args[1].toLowerCase());
                saveFile();
                sender.sendMessage(ChatColor.GREEN + "Command freigegeben: " + args[1]);
                break;
            case "list":
                sender.sendMessage(ChatColor.GOLD + "Blockierte Commands:");
                for (String c : blocked) {
                    sender.sendMessage(ChatColor.RED + "- " + c);
                }
                break;
            case "reload":
                loadFile();
                sender.sendMessage(ChatColor.GREEN + "CommandBlocker neu geladen.");
                break;
            default:
                sender.sendMessage(ChatColor.RED + "Unbekannter Unterbefehl.");
                break;
        }
    }

    private void loadFile() {
        try {
            if (!file.exists()) {
                File parent = file.getParentFile();
                if (parent != null && !parent.exists()) parent.mkdirs();
                file.createNewFile();
                saveFile();
            }

            Yaml yaml = new Yaml();
            Map<String, Object> data = null;
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(file);
                data = yaml.loadAs(fis, Map.class);
            } finally {
                if (fis != null) try { fis.close(); } catch (IOException ignored) {}
            }

            blocked.clear();
            if (data != null && data.containsKey("blocked")) {
                Object obj = data.get("blocked");
                if (obj instanceof List) {
                    List list = (List) obj;
                    for (Object o : list) {
                        if (o != null) blocked.add(String.valueOf(o).toLowerCase());
                    }
                }
            }

            if (data != null && data.containsKey("rate-limit")) {
                Object rlObj = data.get("rate-limit");
                if (rlObj instanceof Map) {
                    Map rl = (Map) rlObj;
                    commandRateLimitEnabled = parseBoolean(rl.get("enabled"), commandRateLimitEnabled);
                    commandRateLimitWindowMs = parseLong(rl.get("window-ms"), commandRateLimitWindowMs);
                    commandRateLimitMaxActions = (int) parseLong(rl.get("max-actions"), commandRateLimitMaxActions);
                    commandRateLimitBlockMs = parseLong(rl.get("block-ms"), commandRateLimitBlockMs);
                    Object msgObj = rl.get("message");
                    if (msgObj != null) {
                        commandRateLimitMessage = String.valueOf(msgObj);
                    }
                }
            }

        } catch (Exception e) {
            if (plugin != null) plugin.getLogger().severe("[CommandBlocker] Fehler beim Laden: " + e.getMessage());
            else System.err.println("[CommandBlocker] Fehler beim Laden: " + e.getMessage());
        }
    }

    private void saveFile() {
        try {
            Yaml yaml = new Yaml();
            Map<String, Object> out = new LinkedHashMap<>();
            out.put("blocked", new ArrayList<>(blocked));

            Map<String, Object> rl = new LinkedHashMap<>();
            rl.put("enabled", commandRateLimitEnabled);
            rl.put("window-ms", commandRateLimitWindowMs);
            rl.put("max-actions", commandRateLimitMaxActions);
            rl.put("block-ms", commandRateLimitBlockMs);
            rl.put("message", commandRateLimitMessage);
            out.put("rate-limit", rl);

            FileWriter fw = null;
            try {
                fw = new FileWriter(file);
                yaml.dump(out, fw);
            } finally {
                if (fw != null) try { fw.close(); } catch (IOException ignored) {}
            }
        } catch (IOException e) {
            if (plugin != null) plugin.getLogger().severe("[CommandBlocker] Fehler beim Speichern: " + e.getMessage());
            else System.err.println("[CommandBlocker] Fehler beim Speichern: " + e.getMessage());
        }
    }

    private boolean parseBoolean(Object obj, boolean fallback) {
        if (obj == null) return fallback;
        return Boolean.parseBoolean(String.valueOf(obj));
    }

    private long parseLong(Object obj, long fallback) {
        if (obj == null) return fallback;
        try {
            return Long.parseLong(String.valueOf(obj));
        } catch (Exception ignored) {
            return fallback;
        }
    }
}
