package fr.luc.gamingcore.listener;

import fr.luc.gamingcore.Main;
import fr.luc.gamingcore.manager.GuildManager;
import fr.luc.gamingcore.model.Guild;
import fr.luc.gamingcore.model.GuildMember;
import fr.luc.gamingcore.model.GuildRank;
import fr.luc.gamingcore.util.MessageManager;
import io.papermc.paper.chat.ChatRenderer;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;

/**
 * Écouteur gérant à la fois le chat privé de guilde (#message) et le formatage du chat global avec :
 * [Grade] [TagGuilde] Pseudo: Message (avec couleurs dynamiques de pseudo et de message par grade).
 */
public class GuildChatListener implements Listener {

    private final Main plugin;
    private final GuildManager guildManager;
    private final MessageManager messageManager;

    /**
     * Constructeur du listener de chat.
     *
     * @param plugin Instance principale du plugin.
     */
    public GuildChatListener(Main plugin) {
        this.plugin = plugin;
        this.guildManager = plugin.getGuildManager();
        this.messageManager = plugin.getMessageManager();
    }

    /**
     * Intercepte les messages de chat pour :
     * 1. Rediriger les messages commençant par '#' vers le chat privé de guilde.
     * 2. Formater le chat global public dans l'ordre : [Grade] [TagGuilde] Pseudo: Message avec dégradés.
     *
     * @param event L'événement AsyncChatEvent de Paper.
     */
    @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
    public void onAsyncChat(AsyncChatEvent event) {
        String rawText = PlainTextComponentSerializer.plainText().serialize(event.message()).trim();

        // 1. Gestion du Chat de Guilde (#)
        if (rawText.startsWith("#")) {
            event.setCancelled(true);
            Player sender = event.getPlayer();

            Guild guild = guildManager.getGuildByPlayer(sender.getUniqueId());
            if (guild == null) {
                messageManager.send(sender, "guild.not_in_guild");
                return;
            }

            String guildMsg = rawText.substring(1).trim();
            if (guildMsg.isEmpty()) {
                return;
            }

            sendGuildChatMessage(guild, sender, guildMsg);
            return;
        }

        // 2. Gestion et Formatage du Chat Global Public ([Grade] [TagGuilde] Pseudo: Message)
        event.renderer(new ChatRenderer() {
            @Override
            public @NotNull Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer) {
                boolean hasPapi = Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null;

                // A. Préfixe de Grade (LuckPerms via PlaceholderAPI avec support des dégradés TAB & MiniMessage)
                Component prefixComponent = Component.empty();
                if (hasPapi) {
                    String lpPrefix = me.clip.placeholderapi.PlaceholderAPI.setPlaceholders(source, "%luckperms_prefix%");
                    if (lpPrefix != null && !lpPrefix.trim().isEmpty() && !lpPrefix.startsWith("%")) {
                        if (lpPrefix.contains("{#") && lpPrefix.contains(">}")) {
                            lpPrefix = lpPrefix.replaceAll("\\{#([0-9a-fA-F]{6})>\\}(.*?)\\{#([0-9a-fA-F]{6})<\\}", "<gradient:#$1:#$3>$2</gradient>");
                        }

                        if (lpPrefix.contains("<") && lpPrefix.contains(">")) {
                            prefixComponent = MiniMessage.miniMessage().deserialize(lpPrefix);
                        } else {
                            prefixComponent = LegacyComponentSerializer.legacyAmpersand().deserialize(lpPrefix);
                        }

                        if (!lpPrefix.endsWith(" ")) {
                            prefixComponent = prefixComponent.append(Component.space());
                        }
                    }
                }

                // B. Tag de Guilde (GamingCore avec support Dégradé MiniMessage)
                Component tagComponent = Component.empty();
                Guild guild = guildManager.getGuildByPlayer(source.getUniqueId());
                if (guild != null) {
                    String c = guild.getColor();
                    if (c.contains(":")) {
                        tagComponent = MiniMessage.miniMessage().deserialize("<gradient:" + c + ">[" + guild.getTag() + "]</gradient> ");
                    } else {
                        tagComponent = MiniMessage.miniMessage().deserialize("<color:" + c + ">[" + guild.getTag() + "]</color> ");
                    }
                }

                // C. Couleur du Pseudo (via Suffixe LuckPerms ou meta name-color)
                Component nameComponent = sourceDisplayName.color(NamedTextColor.WHITE);
                if (hasPapi) {
                    String lpSuffix = me.clip.placeholderapi.PlaceholderAPI.setPlaceholders(source, "%luckperms_suffix%");
                    if (lpSuffix != null && !lpSuffix.trim().isEmpty() && !lpSuffix.startsWith("%")) {
                        if (lpSuffix.contains("{#") && lpSuffix.contains(">}")) {
                            lpSuffix = lpSuffix.replaceAll("\\{#([0-9a-fA-F]{6})>\\}(.*?)\\{#([0-9a-fA-F]{6})<\\}", "<gradient:#$1:#$3>$2</gradient>");
                        }
                        if (lpSuffix.contains("<") && lpSuffix.contains(">")) {
                            nameComponent = MiniMessage.miniMessage().deserialize(lpSuffix + source.getName());
                        } else {
                            nameComponent = LegacyComponentSerializer.legacyAmpersand().deserialize(lpSuffix + source.getName());
                        }
                    }
                }

                // D. Couleur et Formatage du Message
                Component messageComponent;
                String rawMsg = PlainTextComponentSerializer.plainText().serialize(message);
                if (source.hasPermission("gamingcore.chat.color") || source.isOp()) {
                    if (rawMsg.contains("<") && rawMsg.contains(">")) {
                        messageComponent = MiniMessage.miniMessage().deserialize(rawMsg);
                    } else {
                        messageComponent = LegacyComponentSerializer.legacyAmpersand().deserialize(rawMsg);
                    }
                } else if (hasPapi) {
                    String chatColor = me.clip.placeholderapi.PlaceholderAPI.setPlaceholders(source, "%luckperms_meta_chat-color%");
                    if (chatColor != null && !chatColor.trim().isEmpty() && !chatColor.startsWith("%")) {
                        messageComponent = LegacyComponentSerializer.legacyAmpersand().deserialize(chatColor + rawMsg);
                    } else {
                        messageComponent = message.color(NamedTextColor.WHITE);
                    }
                } else {
                    messageComponent = message.color(NamedTextColor.WHITE);
                }

                // Assemblage final : [Grade] [TagGuilde] Pseudo: Message
                return prefixComponent
                        .append(tagComponent)
                        .append(nameComponent)
                        .append(Component.text(": ", NamedTextColor.DARK_GRAY))
                        .append(messageComponent);
            }
        });
    }

    /**
     * Diffuse un message formaté dans le canal privé de la guilde à tous les membres connectés.
     *
     * @param guild   La guilde émettrice.
     * @param sender  Le joueur ayant envoyé le message.
     * @param message Le texte du message.
     */
    public void sendGuildChatMessage(Guild guild, Player sender, String message) {
        GuildMember member = guild.getMember(sender.getUniqueId());
        GuildRank rank = member != null ? guild.getRank(member.getRankId()) : null;
        String rankName = rank != null ? rank.getName() : "Membre";

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

        Component component = MiniMessage.miniMessage().deserialize(formatted);

        for (GuildMember gm : guild.getMembers()) {
            if (gm.getOfflinePlayer() != null && gm.getOfflinePlayer().isOnline()) {
                Player p = gm.getOfflinePlayer().getPlayer();
                if (p != null) {
                    p.sendMessage(component);
                }
            }
        }
    }
}
