package fr.luc.gamingcore.command;

import fr.luc.bettermccommands.BetterMcCommands;
import fr.luc.bettermccommands.argument.Arguments;
import fr.luc.bettermccommands.validation.ValidationResult;
import fr.luc.gamingcore.Main;
import fr.luc.gamingcore.manager.GuildManager;
import fr.luc.gamingcore.manager.GuildResult;
import fr.luc.gamingcore.manager.InviteManager;
import fr.luc.gamingcore.model.*;
import fr.luc.gamingcore.util.MessageManager;
import fr.luc.gamingcore.util.TextUtil;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.entity.Player;

import java.time.Duration;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * Enregistrement et définition de la suite complète de commandes `/guild`
 * utilisant les validateurs métier, les confirmations et les composants interactifs de **betterMcCommands**.
 */
public class GuildCommands {

    private static final Pattern GUILD_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_]{3,16}$");
    private static final int HELP_PAGE_SIZE = 8;
    private static final int GUILD_LIST_PAGE_SIZE = 6;
    private static final int LOGS_PAGE_SIZE = 6;

    private final Main plugin;
    private final GuildManager guildManager;
    private final InviteManager inviteManager;
    private final MessageManager msg;

    /**
     * Constructeur des commandes de guilde.
     *
     * @param plugin       Instance principale du plugin.
     * @param guildManager Gestionnaire métier des guildes.
     */
    public GuildCommands(Main plugin, GuildManager guildManager) {
        this.plugin = plugin;
        this.guildManager = guildManager;
        this.inviteManager = guildManager.getInviteManager();
        this.msg = plugin.getMessageManager();
    }

    /**
     * Enregistre l'arbre complet de la commande racine `/guild` et de toutes ses sous-commandes.
     */
    public void register() {
        double creationCost = plugin.getConfig().getDouble("guild.creation_cost", 1000.0);

        BetterMcCommands.builder("guild")
                .description("Commande principale de gestion des guildes")
                .aliases("g", "guilde", "clan")

                // -------------------------------------------------------------
                // Racine /guild : Affichage du panneau d'aide interactif
                // -------------------------------------------------------------
                .executes(context -> sendHelpMenu(context, 1))

                // -------------------------------------------------------------
                // Sous-commande : /guild help [page]
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("help")
                        .description("Afficher le menu d'aide interactif")
                        .aliases("aide", "?")
                        .argument(Arguments.integer("page", 1, 10).optional().description("Numéro de page"))
                        .executes(context -> {
                            int page = context.getOptional("page", Integer.class).orElse(1);
                            sendHelpMenu(context, page);
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild chat <message>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("chat")
                        .description("Envoyer un message dans le chat privé de votre guilde (ou préfixez par #)")
                        .aliases("c", "msg")
                        .playerOnly()
                        .argument(Arguments.string("message").greedy().description("Message à envoyer"))
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            String chatMsg = context.getString("message");

                            GuildMember member = guild.getMember(player.getUniqueId());
                            GuildRank rank = member != null ? guild.getRank(member.getRankId()) : null;
                            String rankName = rank != null ? rank.getName() : "Membre";

                            String formatted = msg.get("guild.chat.format",
                                    "{guild}", guild.getFormattedName(),
                                    "{tag}", guild.getFormattedTag(),
                                    "{color}", guild.getColor(),
                                    "{rank}", rankName,
                                    "{player}", player.getName(),
                                    "{message}", chatMsg
                            );

                            for (GuildMember m : guild.getMembers()) {
                                if (m.getOfflinePlayer() != null && m.getOfflinePlayer().isOnline()) {
                                    Player onlinePlayer = m.getOfflinePlayer().getPlayer();
                                    if (onlinePlayer != null) {
                                        TextUtil.sendMessage(onlinePlayer, formatted);
                                    }
                                }
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild history [page]
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("history")
                        .description("Consulter l'historique des actions et transactions de votre guilde")
                        .aliases("logs", "journal", "historique")
                        .playerOnly()
                        .argument(Arguments.integer("page", 1, 100).optional().description("Numéro de page"))
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            int page = context.getOptional("page", Integer.class).orElse(1);

                            plugin.getGuildRepository().getLogsAsync(guild.getId(), 100, logs -> {
                                if (logs.isEmpty()) {
                                    context.reply(msg.get("guild.history.empty"));
                                    return;
                                }

                                int totalLogs = logs.size();
                                int maxPage = (int) Math.ceil((double) totalLogs / LOGS_PAGE_SIZE);
                                int finalPage = Math.min(Math.max(1, page), maxPage);

                                context.reply(msg.get("guild.history.header",
                                        "{page}", String.valueOf(finalPage),
                                        "{max_page}", String.valueOf(maxPage)
                                ));

                                int startIndex = (finalPage - 1) * LOGS_PAGE_SIZE;
                                int endIndex = Math.min(startIndex + LOGS_PAGE_SIZE, totalLogs);

                                for (int i = startIndex; i < endIndex; i++) {
                                    GuildLog log = logs.get(i);
                                    context.reply(msg.get("guild.history.item",
                                            "{date}", log.getFormattedDate(),
                                            "{actor}", log.getActorName(),
                                            "{details}", log.getDetails()
                                    ));
                                }

                                int prevPage = Math.max(1, finalPage - 1);
                                int nextPage = Math.min(maxPage, finalPage + 1);

                                String pagination = msg.get("guild.history.pagination",
                                        "{prev_page}", String.valueOf(prevPage),
                                        "{next_page}", String.valueOf(nextPage)
                                );
                                context.reply(pagination);
                            });
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild list [page]
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("list")
                        .description("Afficher la liste des guildes du serveur")
                        .aliases("liste", "top")
                        .argument(Arguments.integer("page", 1, 100).optional().description("Numéro de page"))
                        .executes(context -> {
                            int page = context.getOptional("page", Integer.class).orElse(1);
                            List<Guild> allGuilds = new ArrayList<>(guildManager.getAllGuilds());

                            if (allGuilds.isEmpty()) {
                                context.reply(msg.get("guild.list.empty"));
                                return;
                            }

                            allGuilds.sort((g1, g2) -> Integer.compare(g2.getMemberCount(), g1.getMemberCount()));

                            int totalGuilds = allGuilds.size();
                            int maxPage = (int) Math.ceil((double) totalGuilds / GUILD_LIST_PAGE_SIZE);
                            if (page > maxPage) page = maxPage;
                            if (page < 1) page = 1;

                            context.reply(msg.get("guild.list.header",
                                    "{page}", String.valueOf(page),
                                    "{max_page}", String.valueOf(maxPage)
                            ));

                            int startIndex = (page - 1) * GUILD_LIST_PAGE_SIZE;
                            int endIndex = Math.min(startIndex + GUILD_LIST_PAGE_SIZE, totalGuilds);

                            for (int i = startIndex; i < endIndex; i++) {
                                Guild g = allGuilds.get(i);
                                GuildMember leader = g.getLeaderMember();
                                String leaderName = leader != null && leader.getOfflinePlayer() != null && leader.getOfflinePlayer().getName() != null
                                        ? leader.getOfflinePlayer().getName()
                                        : "Inconnu";

                                String line = msg.get("guild.list.item",
                                        "{index}", String.valueOf(i + 1),
                                        "{guild}", g.getFormattedName(),
                                        "{tag}", g.getFormattedTag(),
                                        "{leader}", leaderName,
                                        "{members}", String.valueOf(g.getMemberCount()),
                                        "{claims}", String.valueOf(g.getClaimCount())
                                );
                                context.reply(line);
                            }

                            int prevPage = Math.max(1, page - 1);
                            int nextPage = Math.min(maxPage, page + 1);

                            String pagination = msg.get("guild.list.pagination",
                                    "{prev_page}", String.valueOf(prevPage),
                                    "{next_page}", String.valueOf(nextPage)
                            );
                            context.reply(pagination);
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild create <nom> [tag]
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("create")
                        .description("Créer une nouvelle guilde")
                        .playerOnly()
                        .argument(Arguments.string("nom").description("Nom de la guilde (3-16 car)"))
                        .argument(Arguments.string("tag").optional().description("Tag court (ex: LEG)"))

                        .validate(context -> {
                            if (guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.already_in_guild"));
                            }
                            return ValidationResult.valid();
                        })
                        .validate(context -> {
                            String name = context.getString("nom");
                            if (!GUILD_NAME_PATTERN.matcher(name).matches()) {
                                return ValidationResult.invalid(msg.get("guild.invalid_name"));
                            }
                            if (guildManager.getGuildByName(name) != null) {
                                return ValidationResult.invalid(msg.get("guild.name_taken", "{guild}", name));
                            }
                            return ValidationResult.valid();
                        })
                        .validate(context -> {
                            Chunk chunk = context.getPlayer().getLocation().getChunk();
                            if (guildManager.isChunkClaimed(chunk.getWorld().getName(), chunk.getX(), chunk.getZ())) {
                                return ValidationResult.invalid(msg.get("guild.creation.chunk_already_claimed"));
                            }
                            return ValidationResult.valid();
                        })
                        .validate(context -> {
                            if (!guildManager.getEconomyManager().has(context.getPlayer(), creationCost)) {
                                return ValidationResult.invalid(msg.get("guild.creation.insufficient_funds",
                                        "{cost}", guildManager.getEconomyManager().format(creationCost)));
                            }
                            return ValidationResult.valid();
                        })

                        .requireConfirmation(Duration.ofSeconds(20))

                        .executes(context -> {
                            Player player = context.getPlayer();
                            String name = context.getString("nom");
                            Optional<String> tagOpt = context.getOptional("tag", String.class);
                            String tag = tagOpt.filter(s -> !s.trim().isEmpty())
                                    .orElse(name.length() <= 4 ? name.toUpperCase() : name.substring(0, 4).toUpperCase());

                            Location loc = player.getLocation();
                            Chunk chunk = loc.getChunk();

                            GuildResult result = guildManager.createGuild(player, name, tag, creationCost);
                            if (result.isSuccess()) {
                                Guild createdGuild = guildManager.getGuildByName(name);
                                String formattedName = createdGuild != null ? createdGuild.getFormattedName() : name;
                                String formattedTag = createdGuild != null ? createdGuild.getFormattedTag() : "[" + tag + "]";

                                String successMsg = msg.get("guild.creation.success",
                                        "{guild}", formattedName,
                                        "{tag}", formattedTag,
                                        "{cost}", guildManager.getEconomyManager().format(creationCost),
                                        "{world}", loc.getWorld().getName(),
                                        "{chunk_x}", String.valueOf(chunk.getX()),
                                        "{chunk_z}", String.valueOf(chunk.getZ())
                                );
                                context.reply(successMsg);
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild disband
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("disband")
                        .description("Dissoudre définitivement votre guilde")
                        .aliases("delete", "supprimer")
                        .playerOnly()
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null) return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            GuildRank leaderRank = g.getLeaderRank();
                            GuildMember member = g.getMember(context.getPlayer().getUniqueId());
                            if (member == null || leaderRank == null || !member.getRankId().equalsIgnoreCase(leaderRank.getId())) {
                                return ValidationResult.invalid(msg.get("guild.disband.not_leader"));
                            }
                            return ValidationResult.valid();
                        })
                        .requireConfirmation(Duration.ofSeconds(15))
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            if (guild == null) return;

                            String formattedName = guild.getFormattedName();
                            GuildResult result = guildManager.disbandGuild(player, guild);
                            if (result.isSuccess()) {
                                context.reply(msg.get("guild.disband.success", "{guild}", formattedName));
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild invite <joueur>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("invite")
                        .description("Inviter un joueur connecté à rejoindre votre guilde")
                        .playerOnly()
                        .argument(Arguments.player("joueur").description("Joueur cible"))
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.INVITE)) {
                                return ValidationResult.invalid(msg.get("guild.invite.no_permission"));
                            }
                            Player target = context.getTargetPlayer("joueur");
                            if (target.getUniqueId().equals(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.invite.cannot_invite_self"));
                            }
                            if (guildManager.isInGuild(target.getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.invite.target_already_in_guild", "{player}", target.getName()));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player sender = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(sender.getUniqueId());
                            Player target = context.getTargetPlayer("joueur");

                            GuildInvite invite = inviteManager.sendInvite(guild, sender, target);
                            context.reply(msg.get("guild.invite.sent",
                                    "{player}", target.getName(),
                                    "{seconds}", String.valueOf(invite.getRemainingSeconds())
                            ));

                            String interactiveMsg = msg.get("guild.invite.received_interactive",
                                    "{guild}", guild.getFormattedName(),
                                    "{tag}", guild.getFormattedTag(),
                                    "{raw_guild}", guild.getName(),
                                    "{sender}", sender.getName()
                            );
                            TextUtil.sendMessage(target, interactiveMsg);
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild join <guilde>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("join")
                        .description("Accepter une invitation et rejoindre une guilde")
                        .aliases("accept", "rejoindre")
                        .playerOnly()
                        .argument(Arguments.string("guilde").description("Nom de la guilde"))
                        .validate(context -> {
                            if (guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.already_in_guild"));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            String guildName = context.getString("guilde");
                            Guild targetGuild = guildManager.getGuildByName(guildName);

                            if (targetGuild == null) {
                                context.reply(msg.get("guild.guild_not_found", "{guild}", guildName));
                                return;
                            }

                            GuildInvite invite = inviteManager.getValidInvite(player, targetGuild.getId());
                            if (invite == null) {
                                context.reply(msg.get("guild.invite.no_pending_invite", "{guild}", targetGuild.getFormattedName()));
                                return;
                            }

                            inviteManager.removeInvite(player, targetGuild.getId());
                            GuildResult result = guildManager.addMember(targetGuild, player);
                            if (result.isSuccess()) {
                                context.reply(msg.get("guild.invite.accepted_self",
                                        "{guild}", targetGuild.getFormattedName(),
                                        "{tag}", targetGuild.getFormattedTag()
                                ));
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild decline <guilde>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("decline")
                        .description("Refuser une invitation de guilde reçue")
                        .aliases("refuser", "deny")
                        .playerOnly()
                        .argument(Arguments.string("guilde").description("Nom de la guilde"))
                        .executes(context -> {
                            Player player = context.getPlayer();
                            String guildName = context.getString("guilde");
                            Guild targetGuild = guildManager.getGuildByName(guildName);

                            if (targetGuild == null) {
                                context.reply(msg.get("guild.guild_not_found", "{guild}", guildName));
                                return;
                            }

                            GuildInvite invite = inviteManager.getValidInvite(player, targetGuild.getId());
                            if (invite == null) {
                                context.reply(msg.get("guild.invite.no_pending_invite", "{guild}", targetGuild.getFormattedName()));
                                return;
                            }

                            inviteManager.removeInvite(player, targetGuild.getId());
                            context.reply(msg.get("guild.invite.declined_target", "{guild}", targetGuild.getFormattedName()));

                            GuildMember leader = targetGuild.getLeaderMember();
                            if (leader != null && leader.getOfflinePlayer() != null && leader.getOfflinePlayer().isOnline()) {
                                Player leaderPlayer = leader.getOfflinePlayer().getPlayer();
                                if (leaderPlayer != null) {
                                    TextUtil.sendMessage(leaderPlayer, msg.get("guild.invite.declined_sender", "{player}", player.getName()));
                                }
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild leave
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("leave")
                        .description("Quitter votre guilde actuelle")
                        .aliases("quitter")
                        .playerOnly()
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g != null) {
                                GuildRank leaderRank = g.getLeaderRank();
                                GuildMember member = g.getMember(context.getPlayer().getUniqueId());
                                if (leaderRank != null && member != null && member.getRankId().equalsIgnoreCase(leaderRank.getId())) {
                                    return ValidationResult.invalid(msg.get("guild.leave.leader_cannot_leave"));
                                }
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            if (guild == null) return;

                            String formattedName = guild.getFormattedName();
                            GuildResult result = guildManager.leaveGuild(player, guild);
                            if (result.isSuccess()) {
                                context.reply(msg.get("guild.leave.success", "{guild}", formattedName));
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild kick <joueur>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("kick")
                        .description("Expulser un membre de votre guilde")
                        .playerOnly()
                        .argument(Arguments.player("joueur").description("Joueur à expulser"))
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.KICK)) {
                                return ValidationResult.invalid(msg.get("guild.kick.no_permission"));
                            }
                            Player target = context.getTargetPlayer("joueur");
                            if (target.getUniqueId().equals(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.kick.cannot_kick_self"));
                            }
                            if (!g.isMember(target.getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_member"));
                            }
                            GuildRank actorRank = g.getMemberRank(context.getPlayer().getUniqueId());
                            GuildRank targetRank = g.getMemberRank(target.getUniqueId());
                            if (actorRank != null && targetRank != null && targetRank.getPriority() >= actorRank.getPriority()) {
                                return ValidationResult.invalid(msg.get("guild.kick.insufficient_rank"));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            if (guild == null) return;

                            Player target = context.getTargetPlayer("joueur");
                            GuildResult result = guildManager.kickMember(player, guild, target.getUniqueId());
                            if (result.isSuccess()) {
                                context.reply(msg.get("guild.kick.success", "{player}", target.getName()));
                                TextUtil.sendMessage(target, msg.get("guild.kick.target_notify", "{guild}", guild.getFormattedName()));
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild claim
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("claim")
                        .description("Revendiquer le chunk actuel pour votre guilde")
                        .playerOnly()
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.CLAIM)) {
                                return ValidationResult.invalid(msg.get("guild.claim.no_permission"));
                            }
                            Chunk chunk = context.getPlayer().getLocation().getChunk();
                            if (guildManager.isChunkClaimed(chunk.getWorld().getName(), chunk.getX(), chunk.getZ())) {
                                return ValidationResult.invalid(msg.get("guild.claim.already_claimed"));
                            }
                            double price = guildManager.getPriceCalculator().calculateNextChunkPrice(g);
                            if (!g.hasBalance(price)) {
                                return ValidationResult.invalid(msg.get("guild.claim.insufficient_bank",
                                        "{cost}", guildManager.getEconomyManager().format(price),
                                        "{balance}", guildManager.getEconomyManager().format(g.getBalance())
                                ));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            Location loc = player.getLocation();
                            Chunk chunk = loc.getChunk();

                            double price = guildManager.getPriceCalculator().calculateNextChunkPrice(guild);
                            GuildResult result = guildManager.claimChunk(player, guild, loc.getWorld(), chunk.getX(), chunk.getZ());

                            if (result.isSuccess()) {
                                context.reply(msg.get("guild.claim.success",
                                        "{cost}", guildManager.getEconomyManager().format(price),
                                        "{count}", String.valueOf(guild.getClaimCount())
                                ));
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild unclaim
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("unclaim")
                        .description("Libérer le chunk actuel possédé par la guilde")
                        .playerOnly()
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.UNCLAIM)) {
                                return ValidationResult.invalid(msg.get("guild.claim.unclaim_no_permission"));
                            }
                            Chunk chunk = context.getPlayer().getLocation().getChunk();
                            if (!g.isClaimed(chunk.getWorld().getName(), chunk.getX(), chunk.getZ())) {
                                return ValidationResult.invalid(msg.get("guild.claim.unclaim_not_owned"));
                            }
                            if (g.getClaimCount() <= 1) {
                                return ValidationResult.invalid(msg.get("guild.claim.unclaim_last_chunk"));
                            }
                            return ValidationResult.valid();
                        })
                        .requireConfirmation(Duration.ofSeconds(15))
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            Location loc = player.getLocation();
                            Chunk chunk = loc.getChunk();

                            GuildResult result = guildManager.unclaimChunk(player, guild, loc.getWorld(), chunk.getX(), chunk.getZ());
                            if (result.isSuccess()) {
                                context.reply(msg.get("guild.claim.unclaim_success"));
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild deposit <montant>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("deposit")
                        .description("Déposer de l'argent dans la banque de guilde")
                        .aliases("deposer", "don")
                        .playerOnly()
                        .argument(Arguments.decimal("montant", 1.0, 1000000000.0).description("Somme à déposer"))
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.BANK_DEPOSIT)) {
                                return ValidationResult.invalid(msg.get("guild.bank.deposit_no_permission"));
                            }
                            double amount = context.getDouble("montant");
                            if (!guildManager.getEconomyManager().has(context.getPlayer(), amount)) {
                                return ValidationResult.invalid(msg.get("guild.bank.deposit_insufficient_player"));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            double amount = context.getDouble("montant");

                            GuildResult result = guildManager.depositMoney(player, guild, amount);
                            if (result.isSuccess()) {
                                context.reply(msg.get("guild.bank.deposit_success",
                                        "{amount}", guildManager.getEconomyManager().format(amount),
                                        "{balance}", guildManager.getEconomyManager().format(guild.getBalance())
                                ));
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild withdraw <montant>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("withdraw")
                        .description("Retirer de l'argent de la banque de guilde")
                        .aliases("retirer")
                        .playerOnly()
                        .argument(Arguments.decimal("montant", 1.0, 1000000000.0).description("Somme à retirer"))
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.BANK_WITHDRAW)) {
                                return ValidationResult.invalid(msg.get("guild.bank.withdraw_no_permission"));
                            }
                            double amount = context.getDouble("montant");
                            if (!g.hasBalance(amount)) {
                                return ValidationResult.invalid(msg.get("guild.bank.withdraw_insufficient_bank",
                                        "{balance}", guildManager.getEconomyManager().format(g.getBalance())
                                ));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            double amount = context.getDouble("montant");

                            GuildResult result = guildManager.withdrawMoney(player, guild, amount);
                            if (result.isSuccess()) {
                                context.reply(msg.get("guild.bank.withdraw_success",
                                        "{amount}", guildManager.getEconomyManager().format(amount)
                                ));
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild sethome
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("sethome")
                        .description("Définir le home de guilde à votre position")
                        .playerOnly()
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.SET_HOME)) {
                                return ValidationResult.invalid(msg.get("guild.home.set_no_permission"));
                            }
                            Location loc = context.getPlayer().getLocation();
                            if (!g.isClaimed(loc.getWorld().getName(), loc.getBlockX() >> 4, loc.getBlockZ() >> 4)) {
                                return ValidationResult.invalid(msg.get("guild.home.set_must_be_in_claim"));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            Location loc = player.getLocation();

                            guild.setHome(loc);
                            plugin.getGuildRepository().saveGuildAsync(guild);
                            context.reply(msg.get("guild.home.set_success"));
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild home
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("home")
                        .description("Se téléporter au point de ralliement de la guilde")
                        .playerOnly()
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.HOME)) {
                                return ValidationResult.invalid(msg.get("guild.home.teleport_no_permission"));
                            }
                            if (g.getHomeLocation() == null) {
                                return ValidationResult.invalid(msg.get("guild.home.not_set"));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            Location homeLoc = guild.getHomeLocation();

                            player.teleportAsync(homeLoc).thenAccept(success -> {
                                if (success) {
                                    msg.sendActionBar(player, "guild.home.teleport_success");
                                }
                            });
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild color <#hex>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("color")
                        .description("Changer la couleur hexadécimale de votre guilde")
                        .aliases("couleur")
                        .playerOnly()
                        .argument(Arguments.string("hex").description("Code couleur hexadécimal (ex: #FF5555)"))
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.MANAGE_GUILD)) {
                                return ValidationResult.invalid("<red>Votre rang ne vous autorise pas à modifier les informations de la guilde.</red>");
                            }
                            if (!context.getString("hex").matches("^#[0-9a-fA-F]{6}$")) {
                                return ValidationResult.invalid("<red>Format de couleur invalide ! Utilisez un code hexadécimal à 6 caractères (ex: <yellow>#00FFAA</yellow> ou <yellow>#FF5555</yellow>).</red>");
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            String hex = context.getString("hex");

                            GuildResult result = guildManager.setGuildColor(player, guild, hex);
                            if (result.isSuccess()) {
                                context.replySuccess(result.getMessage());
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild tag <nouveau_tag>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("tag")
                        .description("Changer le tag court de votre guilde")
                        .playerOnly()
                        .argument(Arguments.string("tag").description("Nouveau tag (2-6 car)"))
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            Guild g = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                            if (g == null || !g.hasPermission(context.getPlayer().getUniqueId(), GuildPermission.MANAGE_GUILD)) {
                                return ValidationResult.invalid("<red>Votre rang ne vous autorise pas à modifier les informations de la guilde.</red>");
                            }
                            if (!context.getString("tag").matches("^[a-zA-Z0-9_]{2,6}$")) {
                                return ValidationResult.invalid("<red>Le tag doit comporter entre 2 et 6 caractères alphanumériques.</red>");
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            String newTag = context.getString("tag");

                            GuildResult result = guildManager.setGuildTag(player, guild, newTag);
                            if (result.isSuccess()) {
                                context.replySuccess(result.getMessage());
                            } else {
                                context.replyError(result.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild info [guilde]
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("info")
                        .description("Afficher les informations d'une guilde")
                        .argument(Arguments.string("guilde").optional().description("Nom de la guilde"))
                        .executes(context -> {
                            Guild targetGuild;
                            Optional<String> nameOpt = context.getOptional("guilde", String.class);
                            String inputName = nameOpt.orElse(null);

                            if (inputName != null && !inputName.trim().isEmpty()) {
                                targetGuild = guildManager.getGuildByName(inputName.trim());
                                if (targetGuild == null) {
                                    context.reply(msg.get("guild.guild_not_found", "{guild}", inputName.trim()));
                                    return;
                                }
                            } else if (context.isPlayer()) {
                                targetGuild = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                                if (targetGuild == null) {
                                    context.reply(msg.get("guild.not_in_guild"));
                                    return;
                                }
                            } else {
                                context.replyError("Veuillez préciser le nom de la guilde : /guild info <guilde>");
                                return;
                            }

                            double nextPrice = guildManager.getPriceCalculator().calculateNextChunkPrice(targetGuild);
                            GuildMember leader = targetGuild.getLeaderMember();
                            String leaderName = leader != null && leader.getOfflinePlayer() != null && leader.getOfflinePlayer().getName() != null
                                    ? leader.getOfflinePlayer().getName()
                                    : "Inconnu";

                            context.reply("<gradient:#00C9FF:#92FE9D><bold>=== INFORMATIONS DE GUILDE ===</bold></gradient>");
                            context.reply("<gray>Nom :</gray> " + targetGuild.getFormattedName() + " " + targetGuild.getFormattedTag());
                            context.reply("<gray>Couleur :</gray> <color:" + targetGuild.getColor() + ">" + targetGuild.getColor() + " ■</color>");
                            context.reply("<gray>Chef :</gray> <gold>" + leaderName + "</gold>");
                            context.reply("<gray>Membres :</gray> <yellow>" + targetGuild.getMemberCount() + "</yellow>");
                            context.reply("<gray>Banque :</gray> <green>" + guildManager.getEconomyManager().format(targetGuild.getBalance()) + "</green>");
                            context.reply("<gray>Territoires :</gray> <aqua>" + targetGuild.getClaimCount() + " chunks</aqua> <dark_gray>(Prochain: " + guildManager.getEconomyManager().format(nextPrice) + ")</dark_gray>");
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild members [guilde]
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("members")
                        .description("Afficher la liste des membres d'une guilde")
                        .argument(Arguments.string("guilde").optional().description("Nom de la guilde"))
                        .executes(context -> {
                            Guild targetGuild;
                            Optional<String> nameOpt = context.getOptional("guilde", String.class);
                            String inputName = nameOpt.orElse(null);

                            if (inputName != null && !inputName.trim().isEmpty()) {
                                targetGuild = guildManager.getGuildByName(inputName.trim());
                                if (targetGuild == null) {
                                    context.reply(msg.get("guild.guild_not_found", "{guild}", inputName.trim()));
                                    return;
                                }
                            } else if (context.isPlayer()) {
                                targetGuild = guildManager.getGuildByPlayer(context.getPlayer().getUniqueId());
                                if (targetGuild == null) {
                                    context.reply(msg.get("guild.not_in_guild"));
                                    return;
                                }
                            } else {
                                context.replyError("Veuillez préciser le nom de la guilde : /guild members <guilde>");
                                return;
                            }

                            context.reply("<gradient:#00C9FF:#92FE9D><bold>=== MEMBRES : </bold></gradient>" + targetGuild.getFormattedName());
                            for (GuildRank rank : targetGuild.getRanks()) {
                                String membersInRank = targetGuild.getMembers().stream()
                                        .filter(m -> m.getRankId().equalsIgnoreCase(rank.getId()))
                                        .map(m -> m.getOfflinePlayer() != null && m.getOfflinePlayer().getName() != null ? m.getOfflinePlayer().getName() : m.getPlayerUuid().toString().substring(0, 8))
                                        .collect(Collectors.joining(", "));

                                if (!membersInRank.isEmpty()) {
                                    context.reply("<gold>" + rank.getName() + " <dark_gray>(" + rank.getPriority() + ")</dark_gray> :</gold> <gray>" + membersInRank + "</gray>");
                                }
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild ranks (ou /guild rank)
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("ranks")
                        .description("Afficher les rangs et permissions de votre guilde")
                        .aliases("rank", "rangs", "rang")
                        .playerOnly()
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());

                            context.reply(msg.get("guild.ranks.header"));
                            for (GuildRank r : guild.getRanks()) {
                                String perms = r.getPermissions().stream().map(Enum::name).collect(Collectors.joining(", "));
                                if (perms.isEmpty()) perms = "Aucune";
                                context.reply(msg.get("guild.ranks.item",
                                        "{name}", r.getName(),
                                        "{id}", r.getId(),
                                        "{priority}", String.valueOf(r.getPriority()),
                                        "{permissions}", perms
                                ));
                            }
                        })
                        // /guild rank create <id> <nom> <priorite>
                        .subcommand(BetterMcCommands.subBuilder("create")
                                .description("Créer un nouveau rang de guilde")
                                .playerOnly()
                                .argument(Arguments.string("id").description("ID unique du rang"))
                                .argument(Arguments.string("nom").description("Nom affiché"))
                                .argument(Arguments.integer("priorite", 1, 99).description("Priorité (1-99)"))
                                .executes(context -> {
                                    Player player = context.getPlayer();
                                    Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                                    String id = context.getString("id");
                                    String name = context.getString("nom");
                                    int priority = context.getInt("priorite");

                                    GuildResult res = guildManager.createRank(player, guild, id, name, priority);
                                    if (res.isSuccess()) {
                                        context.replySuccess(res.getMessage());
                                    } else {
                                        context.replyError(res.getMessage());
                                    }
                                })
                        )
                        // /guild rank delete <id>
                        .subcommand(BetterMcCommands.subBuilder("delete")
                                .description("Supprimer un rang de guilde")
                                .aliases("supprimer", "remove")
                                .playerOnly()
                                .argument(Arguments.string("id").description("ID du rang"))
                                .executes(context -> {
                                    Player player = context.getPlayer();
                                    Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                                    String id = context.getString("id");

                                    GuildResult res = guildManager.deleteRank(player, guild, id);
                                    if (res.isSuccess()) {
                                        context.replySuccess(res.getMessage());
                                    } else {
                                        context.replyError(res.getMessage());
                                    }
                                })
                        )
                        // /guild rank setperm <id> <permission> <true/false>
                        .subcommand(BetterMcCommands.subBuilder("setperm")
                                .description("Modifier une permission pour un rang")
                                .playerOnly()
                                .argument(Arguments.string("id").description("ID du rang"))
                                .argument(Arguments.enumOf("permission", GuildPermission.class).description("Permission"))
                                .argument(Arguments.bool("valeur").description("true ou false"))
                                .executes(context -> {
                                    Player player = context.getPlayer();
                                    Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                                    String id = context.getString("id");
                                    GuildPermission perm = context.get("permission", GuildPermission.class);
                                    boolean state = context.getBoolean("valeur");

                                    GuildResult res = guildManager.setRankPermission(player, guild, id, perm, state);
                                    if (res.isSuccess()) {
                                        context.replySuccess(res.getMessage());
                                    } else {
                                        context.replyError(res.getMessage());
                                    }
                                })
                        )
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild setrank <joueur> <rang>
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("setrank")
                        .description("Modifier le rang d'un membre de la guilde")
                        .aliases("promote", "demote")
                        .playerOnly()
                        .argument(Arguments.player("joueur").description("Membre cible"))
                        .argument(Arguments.string("rang").description("ID du rang cible"))
                        .validate(context -> {
                            if (!guildManager.isInGuild(context.getPlayer().getUniqueId())) {
                                return ValidationResult.invalid(msg.get("guild.not_in_guild"));
                            }
                            return ValidationResult.valid();
                        })
                        .executes(context -> {
                            Player player = context.getPlayer();
                            Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());
                            Player target = context.getTargetPlayer("joueur");
                            String rankId = context.getString("rang");

                            GuildResult res = guildManager.setMemberRank(player, guild, target.getUniqueId(), rankId);
                            if (res.isSuccess()) {
                                context.replySuccess(res.getMessage());
                            } else {
                                context.replyError(res.getMessage());
                            }
                        })
                )

                // -------------------------------------------------------------
                // Sous-commande : /guild reload
                // -------------------------------------------------------------
                .subcommand(BetterMcCommands.subBuilder("reload")
                        .description("Recharger les fichiers de configuration et de messages")
                        .permission("guild.admin.reload")
                        .executes(context -> {
                            plugin.reloadPlugin();
                            context.reply(msg.get("general.reloaded"));
                        })
                )

                .register();
    }

    /**
     * Envoie le menu d'aide interactif et paginé avec tooltips au survol et suggestions de commande au clic.
     */
    private void sendHelpMenu(fr.luc.bettermccommands.api.CommandContext context, int page) {
        List<HelpEntry> entries = new ArrayList<>();
        entries.add(new HelpEntry("/guild create <nom> [tag]", "Fonder une nouvelle guilde et revendiquer le 1er chunk", "/guild create "));
        entries.add(new HelpEntry("/guild list [page]", "Afficher la liste des guildes du serveur", "/guild list "));
        entries.add(new HelpEntry("/guild chat <message>", "Envoyer un message dans le canal privé de guilde (ou #message)", "/guild chat "));
        entries.add(new HelpEntry("/guild history [page]", "Consulter le journal des actions et transactions de la guilde", "/guild history "));
        entries.add(new HelpEntry("/guild ranks", "Afficher et gérer les rangs et permissions de la guilde", "/guild ranks"));
        entries.add(new HelpEntry("/guild setrank <joueur> <rang>", "Modifier le rang d'un membre de la guilde", "/guild setrank "));
        entries.add(new HelpEntry("/guild info [guilde]", "Afficher les statistiques détaillées d'une guilde", "/guild info "));
        entries.add(new HelpEntry("/guild members [guilde]", "Afficher la liste des membres classés par rang", "/guild members "));
        entries.add(new HelpEntry("/guild color <#hex>", "Modifier la couleur hexadécimale de la guilde", "/guild color "));
        entries.add(new HelpEntry("/guild tag <tag>", "Modifier le tag court de la guilde (2-6 car)", "/guild tag "));
        entries.add(new HelpEntry("/guild invite <joueur>", "Inviter un joueur connecté à rejoindre la guilde", "/guild invite "));
        entries.add(new HelpEntry("/guild join <guilde>", "Accepter une invitation et rejoindre une guilde", "/guild join "));
        entries.add(new HelpEntry("/guild decline <guilde>", "Refuser une invitation de guilde reçue", "/guild decline "));
        entries.add(new HelpEntry("/guild leave", "Quitter votre guilde actuelle", "/guild leave"));
        entries.add(new HelpEntry("/guild kick <joueur>", "Expulser un membre ayant un rang inférieur", "/guild kick "));
        entries.add(new HelpEntry("/guild disband", "Dissoudre définitivement votre guilde (Chef uniquement)", "/guild disband"));
        entries.add(new HelpEntry("/guild claim", "Revendiquer le chunk actuel pour votre guilde", "/guild claim"));
        entries.add(new HelpEntry("/guild unclaim", "Libérer le chunk actuel possédé par la guilde", "/guild unclaim"));
        entries.add(new HelpEntry("/guild deposit <montant>", "Déposer des fonds dans la banque de guilde", "/guild deposit "));
        entries.add(new HelpEntry("/guild withdraw <montant>", "Retirer des fonds de la banque de guilde", "/guild withdraw "));
        entries.add(new HelpEntry("/guild sethome", "Définir le point de ralliement de la guilde", "/guild sethome"));
        entries.add(new HelpEntry("/guild home", "Se téléporter au point de ralliement de la guilde", "/guild home"));
        if (context.getSender().hasPermission("guild.admin.reload")) {
            entries.add(new HelpEntry("/guild reload", "Recharger les configurations et messages du plugin", "/guild reload"));
        }

        int totalEntries = entries.size();
        int maxPage = (int) Math.ceil((double) totalEntries / HELP_PAGE_SIZE);
        if (page > maxPage) page = maxPage;
        if (page < 1) page = 1;

        context.reply(msg.get("help.header", "{page}", String.valueOf(page), "{max_page}", String.valueOf(maxPage)));

        int startIndex = (page - 1) * HELP_PAGE_SIZE;
        int endIndex = Math.min(startIndex + HELP_PAGE_SIZE, totalEntries);

        for (int i = startIndex; i < endIndex; i++) {
            HelpEntry entry = entries.get(i);
            String line = "<click:suggest_command:'" + entry.suggestCommand + "'>" +
                    "<hover:show_text:'<green>Cliquez pour insérer : </green><yellow>" + entry.usage + "</yellow>'>" +
                    "<yellow>" + entry.usage + "</yellow></hover></click> <gray>- " + entry.description + "</gray>";
            context.reply(line);
        }

        int prevPage = Math.max(1, page - 1);
        int nextPage = Math.min(maxPage, page + 1);

        String footer = "<click:run_command:'/guild help " + prevPage + "'><hover:show_text:'<yellow>Page précédente</yellow>'><aqua>[◀ Précédent]</aqua></hover></click> " +
                "<dark_gray>---</dark_gray> " +
                "<click:run_command:'/guild help " + nextPage + "'><hover:show_text:'<yellow>Page suivante</yellow>'><aqua>[Suivant ▶]</aqua></hover></click>";
        context.reply(footer);
    }

    private static class HelpEntry {
        final String usage;
        final String description;
        final String suggestCommand;

        HelpEntry(String usage, String description, String suggestCommand) {
            this.usage = usage;
            this.description = description;
            this.suggestCommand = suggestCommand;
        }
    }
}
