package de.viper.survivalplus.commands;

import de.viper.survivalplus.SurvivalPlus;
import de.viper.survivalplus.util.Claim;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;

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

public class ClaimCommand implements CommandExecutor {
    private SurvivalPlus plugin;
    private static final int MAX_CLAIMS = 10;
    private static final int MAX_AREA = 10000; // 100x100 blocks

    public ClaimCommand(SurvivalPlus plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage(plugin.getMessage("commands.player-only"));
            return true;
        }
        Player player = (Player) sender;

        if (args.length == 0) {
            if (!player.hasPermission("survivalplus.claim.use")) {
                player.sendMessage(plugin.getMessage("commands.no-permission"));
                return true;
            }
            Location point1 = plugin.getPoint1(player);
            Location point2 = plugin.getPoint2(player);
            if (point1 == null || point2 == null) {
                player.sendMessage(plugin.getMessage("claim.points-not-set"));
                return true;
            }
            if (!point1.getWorld().equals(point2.getWorld())) {
                player.sendMessage(plugin.getMessage("claim.different-worlds"));
                return true;
            }
            int x1 = point1.getBlockX();
            int z1 = point1.getBlockZ();
            int x2 = point2.getBlockX();
            int z2 = point2.getBlockZ();
            int width = Math.abs(x2 - x1) + 1;
            int length = Math.abs(z2 - z1) + 1;
            if (width * length > MAX_AREA) {
                player.sendMessage(plugin.getMessage("claim.too-large").replace("%max%", String.valueOf(MAX_AREA)));
                return true;
            }
            Claim newClaim = new Claim(player, point1.getWorld().getName(), x1, z1, x2, z2);
            if (plugin.hasOverlap(newClaim)) {
                player.sendMessage(plugin.getMessage("claim.overlap"));
                return true;
            }
            if (plugin.getClaimCount(player) >= MAX_CLAIMS) {
                player.sendMessage(plugin.getMessage("claim.max-reached").replace("%max%", String.valueOf(MAX_CLAIMS)));
                return true;
            }
            plugin.addClaim(newClaim, player);
            player.sendMessage(plugin.getMessage("claim.success").replace("%count%", String.valueOf(plugin.getClaimCount(player))).replace("%max%", String.valueOf(MAX_CLAIMS)));
            plugin.clearSelections(player);
            return true;
        }

        switch (args[0].toLowerCase()) {
            case "mark": {
                if (!player.hasPermission("survivalplus.claim.use")) {
                    player.sendMessage(plugin.getMessage("commands.no-permission"));
                    return true;
                }
                if (args.length < 2 || (!args[1].equals("1") && !args[1].equals("2"))) {
                    player.sendMessage(plugin.getMessage("claim.usage-mark"));
                    return true;
                }
                Location location = player.getLocation();
                if (args[1].equals("1")) {
                    plugin.setPoint1(player, location);
                    player.sendMessage(plugin.getMessage("claim.point1-set").replace("%x%", String.valueOf(location.getBlockX())).replace("%z%", String.valueOf(location.getBlockZ())));
                } else {
                    plugin.setPoint2(player, location);
                    player.sendMessage(plugin.getMessage("claim.point2-set").replace("%x%", String.valueOf(location.getBlockX())).replace("%z%", String.valueOf(location.getBlockZ())));
                }
                return true;
            }

            case "unclaim":
            case "del":
            case "delete": {
                // 1. Mass Delete (Admin): /claim unclaim <Spieler> (oder del/delete)
                if (args.length == 2 && player.isOp()) {
                    Player target = Bukkit.getPlayer(args[1]);
                    UUID targetUUID;
                    if (target != null) {
                        targetUUID = target.getUniqueId();
                    } else {
                        try {
                            targetUUID = UUID.fromString(args[1]);
                        } catch (IllegalArgumentException e) {
                            player.sendMessage(plugin.getMessage("commands.player-not-found"));
                            return true;
                        }
                    }
                    int removedCount = removePlayerClaims(targetUUID);
                    if (removedCount > 0) {
                        player.sendMessage(plugin.getMessage("claim.op-unclaimed")
                                .replace("%player%", args[1])
                                .replace("%count%", String.valueOf(removedCount)));
                    } else {
                        player.sendMessage(plugin.getMessage("claim.no-claims-found")
                                .replace("%player%", args[1]));
                    }
                    return true;
                }

                // 2. Normaler oder Admin Targeted Delete
                Claim claim = plugin.getClaim(player.getLocation());
                if (claim == null) {
                    player.sendMessage(plugin.getMessage("claim.no-claim-at-location"));
                    return true;
                }

                // Prüfen, ob Spieler Owner ist (oder OP)
                if (!claim.getOwner().equals(player.getUniqueId())) {
                    // NICHT Owner -> Aber Admin?
                    if (player.isOp()) {
                        plugin.deleteClaim(claim);
                        String ownerName = Bukkit.getOfflinePlayer(claim.getOwner()).getName();
                        if (ownerName == null) ownerName = "Unbekannt";
                        player.sendMessage(ChatColor.GREEN + "Claim wurde entfernt. (Besitzer war: " + ChatColor.YELLOW + ownerName + ChatColor.GREEN + ")");
                        return true;
                    } else {
                        // Nicht Owner und kein Admin -> Abbruch
                        player.sendMessage(plugin.getMessage("claim.not-owner"));
                        return true;
                    }
                }

                // Owner löscht eigenen Claim
                plugin.deleteClaim(claim);
                player.sendMessage(plugin.getMessage("claim.unclaimed"));
                return true;
            }

            case "trust": {
                if (!player.hasPermission("survivalplus.claim.trust")) {
                    player.sendMessage(plugin.getMessage("commands.no-permission"));
                    return true;
                }
                if (args.length < 2) {
                    player.sendMessage(plugin.getMessage("claim.usage-trust"));
                    return true;
                }
                Player target = Bukkit.getPlayer(args[1]);
                if (target == null) {
                    player.sendMessage(plugin.getMessage("commands.player-not-found"));
                    return true;
                }
                Claim trustClaim = plugin.getClaim(player.getLocation());
                if (trustClaim == null || !trustClaim.getOwner().equals(player.getUniqueId())) {
                    player.sendMessage(plugin.getMessage("claim.not-owner"));
                    return true;
                }
                trustClaim.addTrusted(target.getUniqueId());
                player.sendMessage(plugin.getMessage("claim.trusted").replace("%player%", args[1]));
                plugin.saveClaims();
                return true;
            }

            case "untrust": {
                if (!player.hasPermission("survivalplus.claim.trust")) {
                    player.sendMessage(plugin.getMessage("commands.no-permission"));
                    return true;
                }
                if (args.length < 2) {
                    player.sendMessage(plugin.getMessage("claim.usage-untrust"));
                    return true;
                }
                Player target = Bukkit.getPlayer(args[1]);
                if (target == null) {
                    player.sendMessage(plugin.getMessage("commands.player-not-found"));
                    return true;
                }
                Claim trustClaim = plugin.getClaim(player.getLocation());
                if (trustClaim == null || !trustClaim.getOwner().equals(player.getUniqueId())) {
                    player.sendMessage(plugin.getMessage("claim.not-owner"));
                    return true;
                }
                trustClaim.removeTrusted(target.getUniqueId());
                player.sendMessage(plugin.getMessage("claim.untrusted").replace("%player%", args[1]));
                plugin.saveClaims();
                return true;
            }

            // --- NEU: KICK ---
            case "kick": {
                if (!player.hasPermission("survivalplus.claim.kick")) {
                    player.sendMessage(ChatColor.RED + "Keine Berechtigung!");
                    return true;
                }
                if (args.length < 2) {
                    player.sendMessage(ChatColor.RED + "Verwendung: /claim kick <Spieler>");
                    return true;
                }
                Player kickTarget = Bukkit.getPlayer(args[1]);
                if (kickTarget == null) {
                    player.sendMessage(ChatColor.RED + "Spieler nicht gefunden oder offline!");
                    return true;
                }
                Claim currentClaim = plugin.getClaim(kickTarget.getLocation());
                if (currentClaim == null || !currentClaim.getOwner().equals(player.getUniqueId())) {
                    player.sendMessage(ChatColor.RED + "Du bist hier nicht Besitzer oder kein Claim.");
                    return true;
                }
                kickPlayerFromClaim(kickTarget, currentClaim);
                player.sendMessage(ChatColor.GREEN + "Spieler " + kickTarget.getName() + " wurde aus dem Claim gekickt!");
                kickTarget.sendMessage(ChatColor.RED + "Du wurdest aus dem Claim geworfen!");
                return true;
            }

            // --- NEU: BAN ---
            case "ban": {
                if (!player.hasPermission("survivalplus.claim.ban")) {
                    player.sendMessage(ChatColor.RED + "Keine Berechtigung!");
                    return true;
                }
                if (args.length < 2) {
                    player.sendMessage(ChatColor.RED + "Verwendung: /claim ban <Spieler>");
                    return true;
                }
                
                String claimKey = getClaimKeyAtLocation(player.getLocation());
                if (claimKey == null) {
                    player.sendMessage(ChatColor.RED + "Du stehst in keinem Claim.");
                    return true;
                }

                Player banTarget = Bukkit.getPlayer(args[1]);
                UUID banUUID;
                if (banTarget != null) {
                    banUUID = banTarget.getUniqueId();
                    Claim banCheck = plugin.getClaim(player.getLocation());
                    if (banCheck != null && banCheck.isInside(banTarget.getLocation())) {
                         kickPlayerFromClaim(banTarget, banCheck);
                         banTarget.sendMessage(ChatColor.RED + "Du wurdest aus dem Claim geworfen und gebannt!");
                    }
                } else {
                    try {
                        banUUID = UUID.fromString(args[1]);
                    } catch (IllegalArgumentException e) {
                        player.sendMessage(ChatColor.RED + "Ungültige UUID oder Spieler nicht online.");
                        return true;
                    }
                }
                
                banPlayerInClaim(banUUID, claimKey);
                player.sendMessage(ChatColor.GREEN + "Spieler wurde von diesem Claim gebannt.");
                return true;
            }
            
            // --- NEU: UNBAN ---
            case "unban": {
                if (!player.hasPermission("survivalplus.claim.ban")) {
                    player.sendMessage(ChatColor.RED + "Keine Berechtigung!");
                    return true;
                }
                if (args.length < 2) {
                    player.sendMessage(ChatColor.RED + "Verwendung: /claim unban <Spieler>");
                    return true;
                }
                Player unbanTarget = Bukkit.getPlayer(args[1]);
                UUID unbanUUID;
                if (unbanTarget != null) {
                    unbanUUID = unbanTarget.getUniqueId();
                } else {
                    try {
                        unbanUUID = UUID.fromString(args[1]);
                    } catch (IllegalArgumentException e) {
                        player.sendMessage(ChatColor.RED + "Ungültige UUID.");
                        return true;
                    }
                }

                String claimKeyUnban = getClaimKeyAtLocation(player.getLocation());
                if (claimKeyUnban == null) {
                    player.sendMessage(ChatColor.RED + "Du stehst in keinem Claim.");
                    return true;
                }

                unbanPlayerInClaim(unbanUUID, claimKeyUnban);
                player.sendMessage(ChatColor.GREEN + "Spieler wurde für diesen Claim entbannt.");
                return true;
            }

            case "info": {
                if (!player.hasPermission("survivalplus.claim.use")) {
                    player.sendMessage(plugin.getMessage("commands.no-permission"));
                    return true;
                }
                Claim infoClaim = plugin.getClaim(player.getLocation());
                if (infoClaim == null) {
                    player.sendMessage(plugin.getMessage("claim.no-claim-at-location"));
                    return true;
                }
                String ownerName = Bukkit.getOfflinePlayer(infoClaim.getOwner()).getName();
                if (ownerName == null) {
                    ownerName = infoClaim.getOwner().toString();
                }
                player.sendMessage(plugin.getMessage("claim.info")
                        .replace("%owner%", ownerName)
                        .replace("%world%", infoClaim.getWorldName())
                        .replace("%x1%", String.valueOf(infoClaim.getX1()))
                        .replace("%z1%", String.valueOf(infoClaim.getZ1()))
                        .replace("%x2%", String.valueOf(infoClaim.getX2()))
                        .replace("%z2%", String.valueOf(infoClaim.getZ2())));
                return true;
            }

            default:
                player.sendMessage(plugin.getMessage("claim.usage"));
        }
        return true;
    }

    private int removePlayerClaims(UUID targetUUID) {
        Map<String, Claim> claims = new HashMap<>(plugin.getClaims());
        int removedCount = 0;
        for (Map.Entry<String, Claim> entry : claims.entrySet()) {
            if (entry.getValue().getOwner().equals(targetUUID)) {
                plugin.removeClaimByKey(entry.getKey(), targetUUID);
                removedCount++;
            }
        }
        if (removedCount > 0) {
            plugin.saveClaims();
        }
        return removedCount;
    }

    // --- HILFSMETHODEN ---
    private void kickPlayerFromClaim(Player player, Claim claim) {
        Location loc = player.getLocation();
        int x = loc.getBlockX();
        int z = loc.getBlockZ();
        int minX = Math.min(claim.getX1(), claim.getX2());
        int maxX = Math.max(claim.getX1(), claim.getX2());
        int minZ = Math.min(claim.getZ1(), claim.getZ2());
        int maxZ = Math.max(claim.getZ1(), claim.getZ2());

        int distX1 = Math.abs(x - minX);
        int distX2 = Math.abs(x - maxX);
        int distZ1 = Math.abs(z - minZ);
        int distZ2 = Math.abs(z - maxZ);

        int minDist = Math.min(Math.min(distX1, distX2), Math.min(distZ1, distZ2));

        Location newLoc = loc.clone();
        if (minDist == distX1) {
            newLoc.setX(minX - 1);
        } else if (minDist == distX2) {
            newLoc.setX(maxX + 1);
        } else if (minDist == distZ1) {
            newLoc.setZ(minZ - 1);
        } else {
            newLoc.setZ(maxZ + 1);
        }
        newLoc.setY(newLoc.getY() + 1);
        player.teleport(newLoc);
    }

    private String getClaimKeyAtLocation(Location loc) {
        for (String key : plugin.getClaims().keySet()) {
             if (plugin.getClaims().get(key).isInside(loc)) {
                 return key;
             }
        }
        return null;
    }

    private void banPlayerInClaim(UUID uuid, String claimKey) {
        FileConfiguration config = plugin.getClaimsConfig();
        List<String> banned = config.getStringList(claimKey + ".banned");
        if (!banned.contains(uuid.toString())) {
            banned.add(uuid.toString());
            config.set(claimKey + ".banned", banned);
            plugin.saveClaims();
        }
    }

    private void unbanPlayerInClaim(UUID uuid, String claimKey) {
        FileConfiguration config = plugin.getClaimsConfig();
        List<String> banned = config.getStringList(claimKey + ".banned");
        banned.remove(uuid.toString());
        config.set(claimKey + ".banned", banned);
        plugin.saveClaims();
    }
}