package de.viper.survivalplus.listeners;

import de.viper.survivalplus.SurvivalPlus;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.EquipmentSlot;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;

public class SitListener implements Listener {
    private final SurvivalPlus plugin;
    private final Map<UUID, ArmorStand> sittingPlayers = new HashMap<>();
    private final Map<UUID, Long> sitCooldown = new HashMap<>(); // Neuer Cooldown gegen "Auto-Standup"
    private static final String SIT_TAG = "SP_SIT_STAND";

    public SitListener(SurvivalPlus plugin) {
        this.plugin = plugin;
        cleanUpGhostStands();
    }

    public boolean isSitting(Player player) {
        return sittingPlayers.containsKey(player.getUniqueId());
    }

    public void sitPlayer(Player player, Location location) {
        if (sittingPlayers.containsKey(player.getUniqueId())) {
            return;
        }

        // Erstelle einen unsichtbaren ArmorStand als Sitz
        ArmorStand armorStand = player.getWorld().spawn(location, ArmorStand.class);
        armorStand.setGravity(false);
        armorStand.setMarker(true); 
        armorStand.setInvisible(true);
        armorStand.setInvulnerable(true);
        armorStand.addScoreboardTag(SIT_TAG);
        
        // Setze Rotation des Stands auf Rotation des Spielers
        armorStand.setRotation(player.getLocation().getYaw(), player.getLocation().getPitch());

        // Füge Spieler als Passenger hinzu
        armorStand.addPassenger(player);

        // FIX: KEIN player.teleport() hier ausführen!
        // In neueren Versionen "bricht" das Teleportieren das Mounten sofort wieder.
        // Der Spieler wird automatisch durch addPassenger zum Stand teleportiert.

        // Cooldown setzen, damit wir nicht sofort durch "Movement" aufstehen
        sitCooldown.put(player.getUniqueId(), System.currentTimeMillis() + 500L);

        sittingPlayers.put(player.getUniqueId(), armorStand);
        
        FileConfiguration lang = plugin.getLangConfig();
        player.sendMessage(lang.getString("sit.success", "§aDu hast dich hingesetzt!"));
    }

    public void standUp(Player player) {
        UUID playerId = player.getUniqueId();
        ArmorStand armorStand = sittingPlayers.remove(playerId);
        sitCooldown.remove(playerId); // Cooldown löschen
        
        if (armorStand != null) {
            if (player.isValid() && armorStand.isValid()) {
                // Wenn man absteigt, landet man oft leicht daneben. Wir korrigieren das leicht, 
                // aber nicht so aggressiv wie beim Hinsetzen.
                Location loc = player.getLocation().add(0, 0.2, 0);
                armorStand.removePassenger(player);
                armorStand.remove();
                
                // Kleiner Fix, damit man nicht im Boden klebt
                player.teleport(loc);
            } else {
                armorStand.remove();
            }
            
            FileConfiguration lang = plugin.getLangConfig();
            if (player.isOnline()) {
                player.sendMessage(lang.getString("sit.stand-up", "§aDu bist aufgestanden!"));
            }
        }
    }

    @EventHandler
    public void onPlayerInteract(PlayerInteractEvent event) {
        if (event.getHand() != EquipmentSlot.HAND || event.getAction() != Action.RIGHT_CLICK_BLOCK) {
            return;
        }

        Player player = event.getPlayer();
        FileConfiguration lang = plugin.getLangConfig();

        if (!player.hasPermission("survivalplus.sit")) {
            return;
        }

        Block block = event.getClickedBlock();
        if (block == null || !isStair(block.getType())) {
            return;
        }

        double distance = player.getLocation().distance(block.getLocation());
        if (distance > 3.0) {
            return;
        }

        if (sittingPlayers.containsKey(player.getUniqueId())) {
            standUp(player);
            event.setCancelled(true);
            return;
        }
        
        if (player.isInsideVehicle()) return;

        // Position berechnen
        Location location = block.getLocation();
        location.setX(location.getX() + 0.5);
        location.setZ(location.getZ() + 0.5);
        
        // Bei Treppen: Y + 0.5 ist meistens korrekt für die Sitzfläche
        location.setY(location.getY() + 0.5);
        
        // Drehung anpassen, damit man nicht auf der Treppe schräg sitzt
        location.setYaw(player.getLocation().getYaw());
        location.setPitch(player.getLocation().getPitch());
        
        sitPlayer(player, location);
        event.setCancelled(true);
    }

    @EventHandler
    public void onPlayerMove(PlayerMoveEvent event) {
        Player player = event.getPlayer();
        UUID playerId = player.getUniqueId();
        
        // Wenn der Spieler sitzt
        if (sittingPlayers.containsKey(playerId)) {
            
            // FIX: Cooldown prüfen (Verhindert "Auto-Standup" durch Lag beim Hinsetzen)
            Long cooldown = sitCooldown.get(playerId);
            if (cooldown != null && cooldown > System.currentTimeMillis()) {
                return;
            }

            Location from = event.getFrom();
            Location to = event.getTo();
            if (to == null) return;
            
            // Prüfe signifikante Bewegung
            if (from.distanceSquared(to) > 0.0025) {
                standUp(player);
            }
        }
    }
    
    @EventHandler
    public void onPlayerTeleport(PlayerTeleportEvent event) {
        if (sittingPlayers.containsKey(event.getPlayer().getUniqueId())) {
            standUp(event.getPlayer());
        }
    }

    @EventHandler
    public void onPlayerQuit(PlayerQuitEvent event) {
        Player player = event.getPlayer();
        standUp(player);
    }

    private boolean isStair(Material material) {
        return material.name().endsWith("_STAIRS");
    }
    
    private void cleanUpGhostStands() {
        Bukkit.getScheduler().runTaskLater(plugin, () -> {
            for (World world : Bukkit.getWorlds()) {
                for (Entity entity : world.getEntities()) {
                    if (entity instanceof ArmorStand) {
                        if (entity.getScoreboardTags().contains(SIT_TAG)) {
                            entity.remove();
                        }
                    }
                }
            }
            plugin.logDebug("Ghost Stands (Sit) bereinigt.");
        }, 20L);
    }
}