package fr.luc.gamingcore.manager;

import fr.luc.gamingcore.Main;
import fr.luc.gamingcore.model.Guild;
import fr.luc.gamingcore.model.GuildMember;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;

import java.util.UUID;

/**
 * Gestionnaire responsable de l'affichage des tags et couleurs de guilde
 * au-dessus de la tête des joueurs (Nametag / Scoreboard Team) et dans la liste des joueurs (TabList).
 */
public class NametagManager {

    private final Main plugin;
    private final GuildManager guildManager;
    private final Scoreboard scoreboard;

    /**
     * Constructeur du gestionnaire de Nametags.
     *
     * @param plugin       Instance principale du plugin.
     * @param guildManager Gestionnaire métier des guildes.
     */
    public NametagManager(Main plugin, GuildManager guildManager) {
        this.plugin = plugin;
        this.guildManager = guildManager;
        this.scoreboard = Bukkit.getScoreboardManager().getMainScoreboard();
    }

    /**
     * Met à jour le nametag et le nom dans le TabList pour un joueur spécifique.
     *
     * @param player Le joueur à mettre à jour.
     */
    public void updatePlayer(Player player) {
        if (player == null || !player.isOnline()) return;

        // Si le plugin TAB est installé, lui laisser la gestion complète des Nametags et du TabList
        if (Bukkit.getPluginManager().getPlugin("TAB") != null) {
            return;
        }

        Guild guild = guildManager.getGuildByPlayer(player.getUniqueId());

        if (guild != null) {
            String teamName = getTeamName(guild.getId());
            Team team = scoreboard.getTeam(teamName);
            if (team == null) {
                team = scoreboard.registerNewTeam(teamName);
            }

            String tagText = "<color:" + guild.getColor() + ">[" + guild.getTag() + "] </color>";
            Component prefixComponent = MiniMessage.miniMessage().deserialize(tagText);
            team.prefix(prefixComponent);

            if (!team.hasEntry(player.getName())) {
                // Retirer d'une ancienne équipe de guilde si nécessaire
                Team oldTeam = scoreboard.getEntryTeam(player.getName());
                if (oldTeam != null && oldTeam.getName().startsWith("g_") && !oldTeam.getName().equals(teamName)) {
                    oldTeam.removeEntry(player.getName());
                }
                team.addEntry(player.getName());
            }

            // TabList Name
            Component tabName = MiniMessage.miniMessage().deserialize(tagText + "<white>" + player.getName() + "</white>");
            player.playerListName(tabName);
        } else {
            // Joueur sans guilde
            Team currentTeam = scoreboard.getEntryTeam(player.getName());
            if (currentTeam != null && currentTeam.getName().startsWith("g_")) {
                currentTeam.removeEntry(player.getName());
            }
            player.playerListName(Component.text(player.getName()));
        }
    }

    /**
     * Met à jour l'affichage de tous les membres d'une guilde donnée.
     *
     * @param guild La guilde dont les membres doivent être actualisés.
     */
    public void updateGuild(Guild guild) {
        if (guild == null) return;
        for (GuildMember member : guild.getMembers()) {
            if (member.getOfflinePlayer() != null && member.getOfflinePlayer().isOnline()) {
                Player p = member.getOfflinePlayer().getPlayer();
                if (p != null) {
                    updatePlayer(p);
                }
            }
        }
    }

    /**
     * Supprime l'équipe Scoreboard associée à une guilde lors de sa dissolution.
     *
     * @param guildId L'UUID de la guilde dissoute.
     */
    public void removeGuildTeam(UUID guildId) {
        if (guildId == null) return;
        String teamName = getTeamName(guildId);
        Team team = scoreboard.getTeam(teamName);
        if (team != null) {
            team.unregister();
        }
    }

    /**
     * Met à jour tous les joueurs actuellement connectés sur le serveur.
     */
    public void updateAll() {
        for (Player online : Bukkit.getOnlinePlayers()) {
            updatePlayer(online);
        }
    }

    /**
     * Nettoie les équipes lors de la déconnexion d'un joueur.
     *
     * @param player Le joueur déconnecté.
     */
    public void removePlayer(Player player) {
        if (player == null) return;
        Team team = scoreboard.getEntryTeam(player.getName());
        if (team != null && team.getName().startsWith("g_")) {
            team.removeEntry(player.getName());
        }
    }

    private String getTeamName(UUID guildId) {
        // Le nom d'équipe est préfixé par "g_" suivi des 12 premiers caractères de l'UUID pour rester sous les 16 car.
        String raw = guildId.toString().replace("-", "");
        return "g_" + (raw.length() > 12 ? raw.substring(0, 12) : raw);
    }
}
