package de.viper.survivalplus.listeners;

import de.viper.survivalplus.SurvivalPlus;
import org.bukkit.Chunk;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Animals;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.entity.EntityDeathEvent;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class MobCapListener implements Listener {

    private final SurvivalPlus plugin;
    private boolean enabled;
    private int maxAnimalsPerChunk;
    private final Map<String, Map<UUID, UUID>> chunkAnimalMap = new HashMap<>(); // Chunk -> Tier-UUID -> Spieler-UUID

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

    public void reloadConfig(FileConfiguration config) {
        this.enabled = config.getBoolean("mob-cap.enabled", true);
        this.maxAnimalsPerChunk = config.getInt("mob-cap.max-animals-per-chunk", 10);
        plugin.logDebug("MobCapListener: enabled=" + enabled + ", maxAnimalsPerChunk=" + maxAnimalsPerChunk);

        // Bereinige bestehende Daten
        chunkAnimalMap.clear();

        if (!enabled) {
            plugin.getMobCapConfig().set("mobcap", null); // Bereinige mobcap.yml
            plugin.saveMobCapConfig();
            plugin.logDebug("MobCapListener: Daten bereinigt, da enabled=false");
            return;
        }

        // Lade Zuordnungen aus mobcap.yml
        FileConfiguration mobCapConfig = plugin.getMobCapConfig();
        if (mobCapConfig.contains("mobcap")) {
            for (String chunkKey : mobCapConfig.getConfigurationSection("mobcap").getKeys(false)) {
                Map<UUID, UUID> animalToPlayer = new HashMap<>();
                for (String animalIdStr : mobCapConfig.getConfigurationSection("mobcap." + chunkKey).getKeys(false)) {
                    try {
                        UUID animalId = UUID.fromString(animalIdStr);
                        String playerIdStr = mobCapConfig.getString("mobcap." + chunkKey + "." + animalIdStr);
                        if (playerIdStr != null) {
                            UUID playerId = UUID.fromString(playerIdStr);
                            Entity entity = plugin.getServer().getEntity(animalId);
                            if (entity instanceof Animals) {
                                animalToPlayer.put(animalId, playerId);
                            } else {
                                // Entferne ungültige Einträge
                                mobCapConfig.set("mobcap." + chunkKey + "." + animalIdStr, null);
                            }
                        }
                    } catch (IllegalArgumentException e) {
                        plugin.getLogger().warning("Ungültige UUID in mobcap.yml: " + animalIdStr);
                    }
                }
                chunkAnimalMap.put(chunkKey, animalToPlayer);
            }
        }

        // Scanne alle Welten nach Tieren
        for (org.bukkit.World world : plugin.getServer().getWorlds()) {
            for (Chunk chunk : world.getLoadedChunks()) {
                String chunkKey = getChunkKey(chunk);
                Map<UUID, UUID> animalToPlayer = chunkAnimalMap.computeIfAbsent(chunkKey, k -> new HashMap<>());
                for (Entity entity : chunk.getEntities()) {
                    if (entity instanceof Animals) {
                        UUID id = entity.getUniqueId();
                        if (!animalToPlayer.containsKey(id)) {
                            animalToPlayer.put(id, null); // Kein Spieler zugeordnet
                        }
                    }
                }
            }
        }

        // Speichere aktualisierte mobcap.yml
        saveChunkAnimalMap();
        plugin.logDebug("MobCapListener: Nach Reload " + chunkAnimalMap.size() + " Chunks mit Tieren gefunden.");
    }

    @EventHandler
    public void onCreatureSpawn(CreatureSpawnEvent event) {
        if (!enabled) return;

        LivingEntity entity = event.getEntity();
        if (!(entity instanceof Animals)) return;

        Chunk chunk = entity.getLocation().getChunk();
        String chunkKey = getChunkKey(chunk);
        Map<UUID, UUID> animalToPlayer = chunkAnimalMap.computeIfAbsent(chunkKey, k -> new HashMap<>());

        int animalCount = animalToPlayer.size();
        if (animalCount >= maxAnimalsPerChunk) {
            event.setCancelled(true);
            plugin.logDebug("Spawn von " + entity.getType() + " in Chunk " + chunkKey + " verhindert: Limit von " + maxAnimalsPerChunk + " erreicht.");

            // HINWEIS: Wenn du dem Züchter eine Nachricht schicken willst, nutze EntityBreedEvent
            // Hier ist das nicht möglich, weil man beim Spawn keinen Spielerzugriff hat
        } else {
            animalToPlayer.put(entity.getUniqueId(), null); // Kein Spieler zugeordnet
            saveChunkAnimalMap();
        }
    }

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

        if (!(event.getRightClicked() instanceof Animals)) return;

        Player player = event.getPlayer();
        Entity entity = event.getRightClicked();
        Chunk chunk = entity.getLocation().getChunk();
        String chunkKey = getChunkKey(chunk);
        Map<UUID, UUID> animalToPlayer = chunkAnimalMap.computeIfAbsent(chunkKey, k -> new HashMap<>());

        int animalCount = animalToPlayer.size();
        if (animalCount >= maxAnimalsPerChunk) {
            event.setCancelled(true);
            player.sendMessage(plugin.getMessage("mob-cap.limit-reached").replace("%max%", String.valueOf(maxAnimalsPerChunk)));
            plugin.logDebug("Interaktion mit " + entity.getType() + " in Chunk " + chunkKey + " verhindert: Limit von " + maxAnimalsPerChunk + " erreicht.");
        } else {
            animalToPlayer.put(entity.getUniqueId(), player.getUniqueId());
            saveChunkAnimalMap();
        }
    }

    @EventHandler
    public void onEntityDeath(EntityDeathEvent event) {
        if (!enabled) return;

        if (!(event.getEntity() instanceof Animals)) return;

        LivingEntity entity = event.getEntity();
        Chunk chunk = entity.getLocation().getChunk();
        String chunkKey = getChunkKey(chunk);
        Map<UUID, UUID> animalToPlayer = chunkAnimalMap.get(chunkKey);

        if (animalToPlayer != null) {
            UUID animalId = entity.getUniqueId();
            animalToPlayer.remove(animalId);
            if (animalToPlayer.isEmpty()) {
                chunkAnimalMap.remove(chunkKey);
            }
            saveChunkAnimalMap();
            plugin.logDebug("Tier " + entity.getType() + " in Chunk " + chunkKey + " gestorben. Verbleibende Tiere: " + animalToPlayer.size());
        }
    }

    private String getChunkKey(Chunk chunk) {
        return chunk.getWorld().getName() + "," + chunk.getX() + "," + chunk.getZ();
    }

    private void saveChunkAnimalMap() {
        FileConfiguration mobCapConfig = plugin.getMobCapConfig();
        mobCapConfig.set("mobcap", null); // Bereinige vorherige Daten
        for (Map.Entry<String, Map<UUID, UUID>> entry : chunkAnimalMap.entrySet()) {
            String chunkKey = entry.getKey();
            Map<UUID, UUID> animalToPlayer = entry.getValue();
            for (Map.Entry<UUID, UUID> animalEntry : animalToPlayer.entrySet()) {
                mobCapConfig.set("mobcap." + chunkKey + "." + animalEntry.getKey().toString(),
                        animalEntry.getValue() != null ? animalEntry.getValue().toString() : null);
            }
        }
        plugin.saveMobCapConfig();
    }
}
