package net.viper.status.modules.serverswitcher;

import net.viper.status.StatusAPI;
import net.md_5.bungee.api.ChatColor;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.CommandSender;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.ProxyServer;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.chat.ClickEvent;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.chat.HoverEvent;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.chat.TextComponent;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.config.ServerInfo;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.event.TabCompleteEvent;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.plugin.Command;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.plugin.Listener;
import net.viper.status.StatusAPI;
import net.md_5.bungee.api.plugin.Plugin;
import net.viper.status.StatusAPI;
import net.md_5.bungee.event.EventHandler;
import net.viper.status.module.Module;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class ServerSwitcherModule implements Module {

    private static final String CONFIG_FILE = "serverswitcher.properties";

    private Plugin plugin;
    private boolean enabled = true;
    private String permission = "serverswitcher.use";
    private String commandName = "go";
    private List<String> aliases = new ArrayList<>(Arrays.asList("wechsel", "switch"));
    private List<String> serverWhitelist = new ArrayList<>();

    private String colorHeader  = "&8&m---&r &6&lServer-Men\u00fc &8&m---";
    private String colorEntry   = "&7>> &e";
    private String colorOnline  = "&a";
    private String colorOffline = "&c";
    private String colorSelf    = "&7(Aktuell)";

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

    @Override
    public void onEnable(Plugin plugin) {
        this.plugin = plugin;
        ensureConfigExists();
        loadConfig();

        if (!enabled) {
            StatusAPI.debugLog(plugin, "[ServerSwitcherModule] Deaktiviert.");
            return;
        }

        String[] aliasArray = aliases.toArray(new String[0]);
        ProxyServer.getInstance().getPluginManager().registerCommand(plugin,
                new GoCommand(commandName, permission, aliasArray));
        ProxyServer.getInstance().getPluginManager().registerListener(plugin,
                new GoTabListener());

        plugin.getLogger().fine("[ServerSwitcherModule] Aktiviert. Command: /" + commandName
                + " | Aliases: " + aliases + " | Permission: " + permission);
    }

    @Override
    public void onDisable(Plugin plugin) {
    }

    private void ensureConfigExists() {
        File target = new File(plugin.getDataFolder(), CONFIG_FILE);
        if (target.exists()) return;
        if (!plugin.getDataFolder().exists()) plugin.getDataFolder().mkdirs();

        String defaults =
                "# ServerSwitcherModule Konfiguration\n" +
                "serverswitcher.enabled=true\n\n" +
                "serverswitcher.command=go\n" +
                "serverswitcher.aliases=wechsel,switch\n" +
                "serverswitcher.permission=serverswitcher.use\n\n" +
                "# Optionale Whitelist (leer = alle BungeeCord-Server)\n" +
                "# Beispiel: serverswitcher.servers=lobby,citybuild,survival\n" +
                "serverswitcher.servers=\n\n" +
                "serverswitcher.color.header=&8&m---&r &6&lServer-Men\u00fc &8&m---\n" +
                "serverswitcher.color.entry=&7>> &e\n" +
                "serverswitcher.color.online=&a\n" +
                "serverswitcher.color.offline=&c\n" +
                "serverswitcher.color.self=&7(Aktuell)\n";

        try (OutputStream out = new FileOutputStream(target)) {
            out.write(defaults.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            plugin.getLogger().warning("[ServerSwitcherModule] Konnte " + CONFIG_FILE + " nicht erstellen: " + e.getMessage());
        }
    }

    private void loadConfig() {
        File file = new File(plugin.getDataFolder(), CONFIG_FILE);
        if (!file.exists()) return;

        Properties props = new Properties();
        try (FileInputStream fis = new FileInputStream(file)) {
            props.load(new InputStreamReader(fis, StandardCharsets.UTF_8));
        } catch (Exception e) {
            plugin.getLogger().warning("[ServerSwitcherModule] Fehler beim Laden: " + e.getMessage());
            return;
        }

        enabled     = Boolean.parseBoolean(props.getProperty("serverswitcher.enabled", "true"));
        commandName = props.getProperty("serverswitcher.command", "go").trim();
        permission  = props.getProperty("serverswitcher.permission", "serverswitcher.use").trim();

        aliases.clear();
        for (String a : props.getProperty("serverswitcher.aliases", "wechsel,switch").split(",")) {
            String t = a.trim();
            if (!t.isEmpty()) aliases.add(t);
        }

        serverWhitelist.clear();
        for (String s : props.getProperty("serverswitcher.servers", "").split(",")) {
            String t = s.trim().toLowerCase();
            if (!t.isEmpty()) serverWhitelist.add(t);
        }

        colorHeader  = props.getProperty("serverswitcher.color.header",  colorHeader);
        colorEntry   = props.getProperty("serverswitcher.color.entry",   colorEntry);
        colorOnline  = props.getProperty("serverswitcher.color.online",  colorOnline);
        colorOffline = props.getProperty("serverswitcher.color.offline", colorOffline);
        colorSelf    = props.getProperty("serverswitcher.color.self",    colorSelf);
    }

    private List<String> getServerList() {
        if (!serverWhitelist.isEmpty()) return new ArrayList<>(serverWhitelist);
        List<String> list = new ArrayList<>(ProxyServer.getInstance().getServers().keySet());
        list.sort(String.CASE_INSENSITIVE_ORDER);
        return list;
    }

    private static String c(String text) {
        return ChatColor.translateAlternateColorCodes('&', text);
    }

    private static String capitalize(String s) {
        if (s == null || s.isEmpty()) return s;
        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
    }

    // ── Command ───────────────────────────────────────────────────────────────

    private class GoCommand extends Command {

        GoCommand(String name, String permission, String[] aliases) {
            super(name, permission.isEmpty() ? null : permission, aliases);
        }

        @Override
        public void execute(CommandSender sender, String[] args) {
            if (!(sender instanceof ProxiedPlayer)) {
                sender.sendMessage(c("&cDieser Befehl ist nur f\u00fcr Spieler verf\u00fcgbar."));
                return;
            }

            ProxiedPlayer player = (ProxiedPlayer) sender;

            if (args.length >= 1) {
                String target = args[0].trim();
                ServerInfo server = null;
                for (Map.Entry<String, ServerInfo> entry : ProxyServer.getInstance().getServers().entrySet()) {
                    if (entry.getKey().equalsIgnoreCase(target)) {
                        server = entry.getValue();
                        break;
                    }
                }

                if (server == null) {
                    player.sendMessage(c("&cServer &e" + args[0] + " &cnicht gefunden."));
                    return;
                }

                if (player.getServer() != null
                        && player.getServer().getInfo().getName().equalsIgnoreCase(server.getName())) {
                    player.sendMessage(c("&7Du bist bereits auf &e" + server.getName() + "&7."));
                    return;
                }

                player.sendMessage(c("&7Verbinde mit &e" + server.getName() + "&7..."));
                player.connect(server);
                return;
            }

            sendServerMenu(player);
        }

        private void sendServerMenu(ProxiedPlayer player) {
            player.sendMessage(c(colorHeader));

            for (String serverName : getServerList()) {
                ServerInfo info = ProxyServer.getInstance().getServerInfo(serverName);
                if (info == null) continue;

                boolean isCurrent = player.getServer() != null
                        && player.getServer().getInfo().getName().equalsIgnoreCase(serverName);
                int count = info.getPlayers().size();

                TextComponent line = new TextComponent(c(colorEntry));
                TextComponent btn  = new TextComponent(c((isCurrent ? colorOffline : colorOnline) + capitalize(serverName)));

                if (!isCurrent) {
                    btn.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND,
                            "/" + commandName + " " + serverName));
                    btn.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
                            new ComponentBuilder(c("&7Klicken zum Verbinden\n&7Online: &a" + count + " Spieler")).create()));
                }

                line.addExtra(btn);
                line.addExtra(new TextComponent(c(" &8(&7" + count + " online&8)")));
                if (isCurrent) line.addExtra(new TextComponent(c(" " + colorSelf)));

                player.sendMessage(line);
            }

            player.sendMessage(c("&8&m----------------------------"));
            player.sendMessage(c("&7Tipp: &e/" + commandName + " <Server> &7f\u00fcr direkten Wechsel"));
        }
    }

    // ── Tab-Completion ─────────────────────────────────────────────────────────

    public class GoTabListener implements Listener {

        @EventHandler
        public void onTabComplete(TabCompleteEvent event) {
            String cursor = event.getCursor();
            if (cursor == null) return;

            String lower = cursor.toLowerCase();
            boolean matches = lower.startsWith("/" + commandName.toLowerCase() + " ");
            if (!matches) {
                for (String alias : aliases) {
                    if (lower.startsWith("/" + alias.toLowerCase() + " ")) {
                        matches = true;
                        break;
                    }
                }
            }
            if (!matches) return;

            if (event.getSender() instanceof ProxiedPlayer) {
                ProxiedPlayer p = (ProxiedPlayer) event.getSender();
                if (!permission.isEmpty() && !p.hasPermission(permission)) return;
            }

            int spaceIdx = cursor.indexOf(' ');
            String input = spaceIdx >= 0 ? cursor.substring(spaceIdx + 1).toLowerCase() : "";

            List<String> suggestions = new ArrayList<>();
            for (String server : getServerList()) {
                if (server.toLowerCase().startsWith(input)) suggestions.add(server);
            }

            event.getSuggestions().clear();
            event.getSuggestions().addAll(suggestions);
        }
    }
}
