package fr.luc.gamingcore.listener;

import fr.luc.gamingcore.Main;
import fr.luc.gamingcore.manager.GuildManager;
import fr.luc.gamingcore.util.MessageManager;
import fr.luc.gamingcore.model.Guild;
import fr.luc.gamingcore.model.GuildMember;
import fr.luc.gamingcore.model.GuildRank;
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.plain.PlainTextComponentSerializer;
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 le tag de guilde.
 */
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 avec le tag coloré [TAG] Pseudo: Message.
     *
     * @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
        event.renderer(new ChatRenderer() {
            @Override
            public @NotNull Component render(@NotNull Player source, @NotNull Component sourceDisplayName, @NotNull Component message, @NotNull Audience viewer) {
                Guild guild = guildManager.getGuildByPlayer(source.getUniqueId());
                if (guild != null) {
                    Component tagComponent = MiniMessage.miniMessage().deserialize("<color:" + guild.getColor() + ">[" + guild.getTag() + "] </color>");
                    return tagComponent
                            .append(sourceDisplayName.color(NamedTextColor.WHITE))
                            .append(Component.text(": ", NamedTextColor.DARK_GRAY))
                            .append(message.color(NamedTextColor.WHITE));
                } else {
                    return sourceDisplayName.color(NamedTextColor.WHITE)
                            .append(Component.text(": ", NamedTextColor.DARK_GRAY))
                            .append(message.color(NamedTextColor.WHITE));
                }
            }
        });
    }

    /**
     * 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);
                }
            }
        }
    }
}
