package eu.mrneznamy.mrultimatelibrary.utils;

import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;

import java.util.*;

/**
 * MrLibHelper - Universal help system for Minecraft plugins
 * 
 * This system allows plugins to register their commands and display them
 * in a unified help format with pagination, hover effects, and click actions.
 * 
 * Usage:
 * 1. In your plugin's onEnable() method, register your commands:
 *    MrLibHelper.registerPluginCommands(this, "MyPlugin", commands);
 * 
 * 2. Players can view help using:
 *    /mvt help                    - Show all registered plugins
 *    /mvt help MyPlugin          - Show MyPlugin commands (page 1)
 *    /mvt help MyPlugin 2        - Show MyPlugin commands (page 2)
 * 
 * Example:
 * <pre>
 * List&lt;MrLibHelper.CommandInfo&gt; commands = new ArrayList&lt;&gt;();
 * commands.add(new MrLibHelper.CommandInfo(
 *     "/myplugin create &lt;name&gt;", 
 *     "Create a new item with specified name", 
 *     "/myplugin create MyAwesomeItem"
 * ));
 * commands.add(new MrLibHelper.CommandInfo(
 *     "/myplugin delete &lt;id&gt;", 
 *     "Delete item by ID", 
 *     "/myplugin delete 123"
 * ));
 * MrLibHelper.registerPluginCommands(this, "MyPlugin", commands);
 * </pre>
 */
public class MrLibHelper {

    @SuppressWarnings("unchecked")
    private static Map<String, Object> getRegistry() {
        Object registry = System.getProperties().get("mrlib.helper.registry");
        if (!(registry instanceof Map)) {
            registry = new java.util.concurrent.ConcurrentHashMap<String, Object>();
            System.getProperties().put("mrlib.helper.registry", registry);
        }
        return (Map<String, Object>) registry;
    }

    private static final int COMMANDS_PER_PAGE = 5;

    public static String getPlayerName(Player player) {
        return player.getName();
    }

    public static void registerPluginCommands(JavaPlugin plugin, String pluginName, List<CommandInfo> commands) {
        getRegistry().put(pluginName, new PluginCommandInfo(plugin, pluginName, commands, "/mvt"));
    }

    /**
     * Register plugin commands for help display with custom command prefix
     * 
     * @param plugin The plugin instance
     * @param pluginName Display name for the plugin
     * @param helpCommandPrefix Command prefix for help (e.g., "/msc")
     * @param commands List of commands to register
     */
    public static void registerPluginCommands(JavaPlugin plugin, String pluginName, String helpCommandPrefix, List<CommandInfo> commands) {
        getRegistry().put(pluginName, new PluginCommandInfo(plugin, pluginName, commands, helpCommandPrefix));
    }

    /**
     * Show help for specific plugin
     * 
     * @param player Player to show help to
     * @param pluginName Name of the plugin
     * @param page Page number (1-based)
     */
    public static void showPluginHelp(Player player, String pluginName, int page) {
        Object pluginInfo = getRegistry().get(pluginName);
        if (pluginInfo == null) {
            player.sendMessage(MrLibColors.colorize("&cPlugin " + pluginName + " is not registered!"));
            return;
        }

        List<?> commands = null;
        try {
            java.lang.reflect.Method getCommandsMethod = pluginInfo.getClass().getMethod("getCommands");
            commands = (List<?>) getCommandsMethod.invoke(pluginInfo);
        } catch (Exception e) {
            player.sendMessage(MrLibColors.colorize("&cFailed to load commands for " + pluginName));
            return;
        }

        if (commands == null) {
            player.sendMessage(MrLibColors.colorize("&cNo commands found for " + pluginName));
            return;
        }

        int totalPages = (int) Math.ceil((double) commands.size() / COMMANDS_PER_PAGE);

        if (page < 1 || page > totalPages) {
            player.sendMessage(MrLibColors.colorize("&cInvalid page number! Available pages: 1-" + totalPages));
            return;
        }

        String primary = getPrimaryColorForPlugin(pluginName);
        String secondary = getSecondaryColorForPlugin(pluginName);

        player.sendMessage(MrLibColors.colorize("  {" + primary + ">}&l" + pluginName + " - Commands{" + secondary + "<} &8(Page &a" + page + "&8/&c" + totalPages + "&8)"));
        player.sendMessage("");

        int startIndex = (page - 1) * COMMANDS_PER_PAGE;
        int endIndex = Math.min(startIndex + COMMANDS_PER_PAGE, commands.size());

        for (int i = startIndex; i < endIndex; i++) {
            Object cmd = commands.get(i);
            try {
                java.lang.reflect.Method getCommandMethod = cmd.getClass().getMethod("getCommand");
                String commandVal = (String) getCommandMethod.invoke(cmd);
                
                java.lang.reflect.Method getDescriptionMethod = cmd.getClass().getMethod("getDescription");
                String descriptionVal = (String) getDescriptionMethod.invoke(cmd);

                java.lang.reflect.Method getExampleMethod = cmd.getClass().getMethod("getExample");
                String exampleVal = (String) getExampleMethod.invoke(cmd);

                String commandText = MrLibColors.colorize("  &8» &c" + commandVal + " &8| &7" + descriptionVal);

                TextComponent component = new TextComponent("");
                for (BaseComponent tc : TextComponent.fromLegacyText(commandText)) {
                    component.addExtra(tc);
                }

                if (exampleVal != null && !exampleVal.isEmpty()) {
                    component.setHoverEvent(new HoverEvent(
                        HoverEvent.Action.SHOW_TEXT,
                        TextComponent.fromLegacyText(MrLibColors.colorize("&7Example: &f" + exampleVal + "\n&eClick to suggest command!"))
                    ));
                    component.setClickEvent(new ClickEvent(
                        ClickEvent.Action.SUGGEST_COMMAND,
                        exampleVal
                    ));
                } else {
                    component.setHoverEvent(new HoverEvent(
                        HoverEvent.Action.SHOW_TEXT,
                        TextComponent.fromLegacyText(MrLibColors.colorize("&eClick to suggest command!"))
                    ));
                    component.setClickEvent(new ClickEvent(
                        ClickEvent.Action.SUGGEST_COMMAND,
                        commandVal.split(" ")[0]
                    ));
                }

                player.spigot().sendMessage(component);
            } catch (Exception e) {
                //
            }
        }

        player.sendMessage("");
        showNavigation(player, page, totalPages, pluginName);
    }

    private static void showNavigation(Player player, int currentPage, int totalPages, String pluginName) {
        Object pluginInfo = getRegistry().get(pluginName);
        String prefix = "/mvt";
        if (pluginInfo != null) {
            try {
                java.lang.reflect.Method getPrefixMethod = pluginInfo.getClass().getMethod("getHelpCommandPrefix");
                prefix = (String) getPrefixMethod.invoke(pluginInfo);
            } catch (Exception ignored) {}
        }
        String primary = getPrimaryColorForPlugin(pluginName);
        String secondary = getSecondaryColorForPlugin(pluginName);

        String navCommandBase = prefix.equalsIgnoreCase("/mvt") ? prefix + " help " + pluginName : prefix + " help";

        TextComponent navigation = new TextComponent("  ");

        if (currentPage > 1) {
            TextComponent prevButton = new TextComponent("");
            for (BaseComponent tc : TextComponent.fromLegacyText(MrLibColors.colorize("{" + primary + ">}« Previous Page{" + secondary + "<}"))) {
                prevButton.addExtra(tc);
            }
            prevButton.setClickEvent(new ClickEvent(
                ClickEvent.Action.RUN_COMMAND,
                navCommandBase + " " + (currentPage - 1)
            ));
            prevButton.setHoverEvent(new HoverEvent(
                HoverEvent.Action.SHOW_TEXT,
                TextComponent.fromLegacyText(MrLibColors.colorize("&7Go to page &f" + (currentPage - 1)))
            ));
            navigation.addExtra(prevButton);
        } else {
            navigation.addExtra(new TextComponent(MrLibColors.colorize("&8« Previous Page")));
        }

        navigation.addExtra(new TextComponent(MrLibColors.colorize(" &8| ")));

        if (currentPage < totalPages) {
            TextComponent nextButton = new TextComponent("");
            for (BaseComponent tc : TextComponent.fromLegacyText(MrLibColors.colorize("{" + primary + ">}Next Page »{" + secondary + "<}"))) {
                nextButton.addExtra(tc);
            }
            nextButton.setClickEvent(new ClickEvent(
                ClickEvent.Action.RUN_COMMAND,
                navCommandBase + " " + (currentPage + 1)
            ));
            nextButton.setHoverEvent(new HoverEvent(
                HoverEvent.Action.SHOW_TEXT,
                TextComponent.fromLegacyText(MrLibColors.colorize("&7Go to page &f" + (currentPage + 1)))
            ));
            navigation.addExtra(nextButton);
        } else {
            navigation.addExtra(new TextComponent(MrLibColors.colorize("&8Next Page »")));
        }

        player.spigot().sendMessage(navigation);
    }

    /**
     * Show all registered plugins
     * 
     * @param player Player to show plugins to
     */
    public static void showRegisteredPlugins(Player player) {
        if (getRegistry().isEmpty()) {
            player.sendMessage(MrLibColors.colorize("&cNo plugins registered for help system!"));
            return;
        }

        player.sendMessage("");
        player.sendMessage(MrLibColors.colorize("  {#8B5CF6>}&lMrLibHelper{#D946EF<} &8| &fAvailable plugins:"));
        player.sendMessage("");

        for (Object info : getRegistry().values()) {
            try {
                java.lang.reflect.Method getPluginNameMethod = info.getClass().getMethod("getPluginName");
                String pluginName = (String) getPluginNameMethod.invoke(info);
                
                java.lang.reflect.Method getHelpCommandPrefixMethod = info.getClass().getMethod("getHelpCommandPrefix");
                String helpCommandPrefix = (String) getHelpCommandPrefixMethod.invoke(info);

                String primary = getPrimaryColorForPlugin(pluginName);
                TextComponent pluginButton = new TextComponent("");
                for (BaseComponent tc : TextComponent.fromLegacyText(MrLibColors.colorize("  &8• {" + primary + "}" + pluginName))) {
                    pluginButton.addExtra(tc);
                }

                String helpCmd = helpCommandPrefix.equalsIgnoreCase("/mvt") 
                    ? "/mvt help " + pluginName + " 1" 
                    : helpCommandPrefix + " help 1";

                pluginButton.setClickEvent(new ClickEvent(
                    ClickEvent.Action.RUN_COMMAND,
                    helpCmd
                ));
                pluginButton.setHoverEvent(new HoverEvent(
                    HoverEvent.Action.SHOW_TEXT,
                    TextComponent.fromLegacyText(MrLibColors.colorize("&7Click to view &b" + pluginName + " &7help\n&eCommand: &f" + helpCmd))
                ));

                player.spigot().sendMessage(pluginButton);
            } catch (Exception e) {
                
            }
        }
        player.sendMessage("");
    }

    private static String getPrimaryColorForPlugin(String pluginName) {
        String name = pluginName.toLowerCase();
        if (name.contains("generator")) return "#ff0000";
        if (name.contains("sellchest")) return "#8B5CF6";
        return "#8B5CF6";
    }

    private static String getSecondaryColorForPlugin(String pluginName) {
        String name = pluginName.toLowerCase();
        if (name.contains("generator")) return "#eb0000";
        if (name.contains("sellchest")) return "#D946EF";
        return "#D946EF";
    }

    public static String serializeItemStack(ItemStack item) {
        if (item == null) return null;
        try {
            java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
            org.bukkit.util.io.BukkitObjectOutputStream dataOutput = new org.bukkit.util.io.BukkitObjectOutputStream(outputStream);
            dataOutput.writeObject(item);
            dataOutput.close();
            return Base64.getEncoder().encodeToString(outputStream.toByteArray());
        } catch (Exception e) {
            return null;
        }
    }

    public static ItemStack deserializeItemStack(String data) {
        if (data == null || data.isEmpty()) return null;
        try {
            java.io.ByteArrayInputStream inputStream = new java.io.ByteArrayInputStream(Base64.getDecoder().decode(data));
            org.bukkit.util.io.BukkitObjectInputStream dataInput = new org.bukkit.util.io.BukkitObjectInputStream(inputStream);
            ItemStack item = (ItemStack) dataInput.readObject();
            dataInput.close();
            return item;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Command information class
     */
    public static class CommandInfo {
        private final String command;
        private final String description;
        private final String example;

        /**
         * Create command info
         * 
         * @param command Command syntax (e.g., "/myplugin create <name>")
         * @param description Command description
         * @param example Example usage (e.g., "/myplugin create MyItem")
         */
        public CommandInfo(String command, String description, String example) {
            this.command = command;
            this.description = description;
            this.example = example;
        }

        public String getCommand() { return command; }
        public String getDescription() { return description; }
        public String getExample() { return example; }
    }

    /**
     * Plugin command info class (internal use)
     */
    private static class PluginCommandInfo {
        private final JavaPlugin plugin;
        private final String pluginName;
        private final List<CommandInfo> commands;
        private final String helpCommandPrefix;

        public PluginCommandInfo(JavaPlugin plugin, String pluginName, List<CommandInfo> commands, String helpCommandPrefix) {
            this.plugin = plugin;
            this.pluginName = pluginName;
            this.commands = commands;
            this.helpCommandPrefix = helpCommandPrefix;
        }

        public JavaPlugin getPlugin() { return plugin; }
        public String getPluginName() { return pluginName; }
        public List<CommandInfo> getCommands() { return commands; }
        public String getHelpCommandPrefix() { return helpCommandPrefix; }
    }
}