package de.viper.survivalplus.listeners;

import de.viper.survivalplus.SurvivalPlus;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.Material;

import java.util.*;

public class MobLeashLimitListener implements Listener {

    private final SurvivalPlus plugin;
    private boolean enabled;
    private int maxLeashCount;
    private final Map<UUID, Set<UUID>> leashedEntities = new HashMap<>();
    private final Map<UUID, Integer> leashCounts = new HashMap<>();
    private final Map<UUID, UUID> entityToPlayer = new HashMap<>();

    public MobLeashLimitListener(SurvivalPlus plugin, FileConfiguration config) {
        this.plugin = plugin;
        reloadConfig(config);
    }

    public void reloadConfig(FileConfiguration config) {
        this.enabled = config.getBoolean("mob-leash-limit.enabled", true);
        this.maxLeashCount = config.getInt("mob-leash-limit.max-leash-count", 5);
        plugin.logDebug("MobLeashLimitListener: enabled=" + enabled + ", maxLeashCount=" + maxLeashCount);

        // Bereinige bestehende Daten
        leashedEntities.clear();
        leashCounts.clear();
        entityToPlayer.clear();

        if (!enabled) {
            plugin.getLeashesConfig().set("leashes", null); // Bereinige leashes.yml
            plugin.saveLeashesConfig();
            plugin.logDebug("MobLeashLimitListener: Daten bereinigt, da enabled=false");
            return;
        }

        // Lade Zuordnungen aus leashes.yml
        FileConfiguration leashesConfig = plugin.getLeashesConfig();
        if (leashesConfig.contains("leashes")) {
            for (String entityIdStr : leashesConfig.getConfigurationSection("leashes").getKeys(false)) {
                UUID entityId;
                try {
                    entityId = UUID.fromString(entityIdStr);
                } catch (IllegalArgumentException e) {
                    plugin.getLogger().warning("Ungültige UUID in leashes.yml: " + entityIdStr);
                    continue;
                }
                String playerIdStr = leashesConfig.getString("leashes." + entityIdStr);
                if (playerIdStr != null) {
                    try {
                        UUID playerId = UUID.fromString(playerIdStr);
                        LivingEntity entity = (LivingEntity) plugin.getServer().getEntity(entityId);
                        if (entity != null && entity.isLeashed()) {
                            Set<UUID> playerLeashedEntities = leashedEntities.computeIfAbsent(playerId, k -> new HashSet<>());
                            playerLeashedEntities.add(entityId);
                            leashCounts.put(playerId, playerLeashedEntities.size());
                            entityToPlayer.put(entityId, playerId);
                        } else {
                            // Entferne ungültige Einträge aus leashes.yml
                            leashesConfig.set("leashes." + entityIdStr, null);
                        }
                    } catch (IllegalArgumentException e) {
                        plugin.getLogger().warning("Ungültige Spieler-UUID in leashes.yml für Entity " + entityIdStr + ": " + playerIdStr);
                    }
                }
            }
        }

        // Scanne alle Welten nach angeleinten Tieren, die noch nicht in leashes.yml sind
        for (org.bukkit.World world : plugin.getServer().getWorlds()) {
            for (LivingEntity entity : world.getLivingEntities()) {
                if (entity.isLeashed() && !entityToPlayer.containsKey(entity.getUniqueId())) {
                    // Nur Tiere zählen, die von einem Spieler gehalten werden (für neue Leashes)
                    if (entity.getLeashHolder() instanceof Player) {
                        Player player = (Player) entity.getLeashHolder();
                        UUID playerId = player.getUniqueId();
                        UUID entityId = entity.getUniqueId();

                        Set<UUID> playerLeashedEntities = leashedEntities.computeIfAbsent(playerId, k -> new HashSet<>());
                        playerLeashedEntities.add(entityId);
                        leashCounts.put(playerId, playerLeashedEntities.size());
                        entityToPlayer.put(entityId, playerId);

                        // Speichere in leashes.yml
                        leashesConfig.set("leashes." + entityId.toString(), playerId.toString());
                    }
                }
            }
        }

        // Prüfe, ob das neue Limit überschritten wird
        for (Map.Entry<UUID, Set<UUID>> entry : leashedEntities.entrySet()) {
            UUID playerId = entry.getKey();
            Set<UUID> playerLeashedEntities = entry.getValue();
            if (playerLeashedEntities.size() > maxLeashCount) {
                Player player = plugin.getServer().getPlayer(playerId);
                if (player != null && player.isOnline()) {
                    player.sendMessage(plugin.getMessage("mob-leash-limit.limit-adjusted")
                            .replace("%count%", String.valueOf(playerLeashedEntities.size()))
                            .replace("%max%", String.valueOf(maxLeashCount)));
                }
            }
        }

        // Entferne leere Einträge
        leashedEntities.entrySet().removeIf(entry -> entry.getValue().isEmpty());
        leashCounts.entrySet().removeIf(entry -> entry.getValue() == 0);

        // Speichere aktualisierte leashes.yml
        plugin.saveLeashesConfig();

        plugin.logDebug("MobLeashLimitListener: Nach Reload " + leashedEntities.size() + " Spieler mit angeleinten Tieren gefunden.");
    }

    @EventHandler
    public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
        if (!enabled) return;

        Player player = event.getPlayer();
        ItemStack itemInHand = player.getInventory().getItemInMainHand();
        UUID playerId = player.getUniqueId();
        LivingEntity entity = (LivingEntity) event.getRightClicked();
        UUID entityId = entity.getUniqueId();

        if (itemInHand != null && itemInHand.getType() == Material.LEAD) {
            Set<UUID> playerLeashedEntities = leashedEntities.computeIfAbsent(playerId, k -> new HashSet<>());
            int currentCount = playerLeashedEntities.size();
            plugin.logDebug("PlayerInteractEntity: player=" + player.getName() + ", currentCount=" + currentCount + ", maxLeashCount=" + maxLeashCount);

            if (playerLeashedEntities.contains(entityId)) {
                // Ableinen
                playerLeashedEntities.remove(entityId);
                leashCounts.put(playerId, currentCount - 1);
                entityToPlayer.remove(entityId);
                plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
                plugin.saveLeashesConfig();
                player.sendMessage(plugin.getMessage("mob-leash-limit.unleashed")
                        .replace("%count%", String.valueOf(currentCount - 1)));

                // Entferne leere Einträge
                if (playerLeashedEntities.isEmpty()) {
                    leashedEntities.remove(playerId);
                    leashCounts.remove(playerId);
                }
            } else {
                // Anleinen
                if (currentCount >= maxLeashCount) {
                    player.sendMessage(plugin.getMessage("mob-leash-limit.max-reached")
                            .replace("%count%", String.valueOf(maxLeashCount)));
                    event.setCancelled(true);
                } else {
                    playerLeashedEntities.add(entityId);
                    leashCounts.put(playerId, currentCount + 1);
                    entityToPlayer.put(entityId, playerId);
                    plugin.getLeashesConfig().set("leashes." + entityId.toString(), playerId.toString());
                    plugin.saveLeashesConfig();
                    player.sendMessage(plugin.getMessage("mob-leash-limit.leashed")
                            .replace("%count%", String.valueOf(currentCount + 1)));
                }
            }
        }
    }

    @EventHandler
    public void onEntityDeath(EntityDeathEvent event) {
        if (!enabled) {
            UUID entityId = event.getEntity().getUniqueId();
            entityToPlayer.remove(entityId);
            plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
            plugin.saveLeashesConfig();
            return;
        }

        LivingEntity entity = event.getEntity();
        UUID entityId = entity.getUniqueId();
        UUID playerId = entityToPlayer.remove(entityId);

        if (playerId != null) {
            Set<UUID> playerLeashedEntities = leashedEntities.getOrDefault(playerId, new HashSet<>());
            playerLeashedEntities.remove(entityId);
            int newCount = playerLeashedEntities.size();
            leashCounts.put(playerId, newCount);

            // Entferne aus leashes.yml
            plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
            plugin.saveLeashesConfig();

            // Entferne leere Einträge
            if (playerLeashedEntities.isEmpty()) {
                leashedEntities.remove(playerId);
                leashCounts.remove(playerId);
            }

            Player player = plugin.getServer().getPlayer(playerId);
            if (player != null && player.isOnline()) {
                player.sendMessage(plugin.getMessage("mob-leash-limit.entity-died")
                        .replace("%count%", String.valueOf(newCount)));
            }
        }
    }

    public void updateLeashCount(Player player) {
        UUID playerId = player.getUniqueId();
        Set<UUID> playerLeashedEntities = leashedEntities.getOrDefault(playerId, new HashSet<>());
        // Entferne nicht existierende oder nicht angeleinte Entities
        playerLeashedEntities.removeIf(entityId -> {
            LivingEntity entity = (LivingEntity) plugin.getServer().getEntity(entityId);
            if (entity == null || !entity.isLeashed()) {
                plugin.getLeashesConfig().set("leashes." + entityId.toString(), null);
                return true;
            }
            return false;
        });
        int currentCount = playerLeashedEntities.size();
        leashCounts.put(playerId, currentCount);

        // Aktualisiere entityToPlayer-Map
        entityToPlayer.entrySet().removeIf(entry -> entry.getValue().equals(playerId) && !playerLeashedEntities.contains(entry.getKey()));

        // Entferne leere Einträge
        if (playerLeashedEntities.isEmpty()) {
            leashedEntities.remove(playerId);
            leashCounts.remove(playerId);
        }

        // Falls disabled, bereinige die Daten für diesen Spieler
        if (!enabled) {
            playerLeashedEntities.clear();
            leashedEntities.remove(playerId);
            leashCounts.remove(playerId);
            entityToPlayer.entrySet().removeIf(entry -> entry.getValue().equals(playerId));
            plugin.getLeashesConfig().set("leashes", null);
            plugin.saveLeashesConfig();
        }

        plugin.getLogger().info("updateLeashCount: player=" + player.getName() + ", currentCount=" + currentCount);
    }

    public int getLeashCount(Player player) {
        updateLeashCount(player);
        return leashCounts.getOrDefault(player.getUniqueId(), 0);
    }
}