package com.spaceshipproject;

import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

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

/**
 * Commandes joueur de SpaceShipProject :
 *  - /spaceship help
 *  - /spaceship create                       : cree un nouveau spaceship (boussole donnee)
 *  - /spaceship give <player> <id>           : recupere une telecommande perdue (proprietaire requis)
 *  - /spaceship list [joueur]                : liste les ships
 *  - /spaceship info [joueur]                : infos detaillees
 *  - /spaceship delete <id>                  : supprime un de ses ships (boussole retiree)
 *  - /spaceship remote <id>                  : alias de give pour soi-meme
 *  - /spaceship reload                       : recharge la config
 */
public class SpaceShipCommand implements CommandExecutor, TabCompleter {

    private final SpaceShipProject plugin;

    public SpaceShipCommand(SpaceShipProject plugin) {
        this.plugin = plugin;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (args.length == 0 || args[0].equalsIgnoreCase("help")) {
            help(sender);
            return true;
        }

        switch (args[0].toLowerCase()) {
            case "create"  -> handleCreate(sender);
            case "give"    -> handleGive(sender, args);
            case "remote"  -> handleRemoteSelf(sender, args);
            case "list"    -> handleList(sender, args);
            case "info"    -> handleInfo(sender, args);
            case "delete"  -> handleDelete(sender, args);
            case "reload"  -> handleReload(sender);
            default -> sender.sendMessage(ConfigManager.color("&cCommande inconnue. /spaceship help"));
        }
        return true;
    }

    private void help(CommandSender s) {
        s.sendMessage(ConfigManager.color("&b&l=== SpaceShipProject ==="));
        s.sendMessage(ConfigManager.color("&7/spaceship create &8- creer un nouveau spaceship"));
        s.sendMessage(ConfigManager.color("&7/spaceship give <joueur> <id> &8- recuperer une telecommande perdue"));
        s.sendMessage(ConfigManager.color("&7/spaceship remote <id> &8- recuperer sa propre telecommande"));
        s.sendMessage(ConfigManager.color("&7/spaceship list [joueur] &8- lister les spaceships"));
        s.sendMessage(ConfigManager.color("&7/spaceship info [joueur] &8- infos detaillees"));
        s.sendMessage(ConfigManager.color("&7/spaceship delete <id> &8- supprimer un spaceship"));
        s.sendMessage(ConfigManager.color("&7/spaceship reload &8- recharger la config"));
        s.sendMessage(ConfigManager.color("&7Telecommande : "));
        s.sendMessage(ConfigManager.color("&7  &eClic gauche &8: invoquer / decharger"));
        s.sendMessage(ConfigManager.color("&7  &eClic droit &8: monter / redescendre"));
        s.sendMessage(ConfigManager.color("&7  &eShift + droit &8: parametres"));
    }

    /* ============================ CREATE ============================ */

    private void handleCreate(CommandSender sender) {
        if (!(sender instanceof Player player)) {
            sender.sendMessage(ConfigManager.color("&cCommande joueur uniquement."));
            return;
        }
        if (!player.hasPermission("spaceship.create")) {
            player.sendMessage(plugin.getConfigManager().msgNoPerm());
            return;
        }
        long id = plugin.getSpaceshipManager().createNewSpaceship(player);
        if (id < 0) return; // message deja envoye (quota)
        Spaceship ship = plugin.getDatabaseManager().getSpaceship(id);
        if (ship == null) {
            sender.sendMessage(ConfigManager.color("&cErreur interne : ship introuvable apres creation."));
            return;
        }
        giveRemote(player, ship);
        player.sendMessage(plugin.getConfigManager().msgGiven(ship.getName()));
    }

    /* ============================ GIVE (recover) ============================ */

    private void handleGive(CommandSender sender, String[] args) {
        if (args.length < 3) {
            sender.sendMessage(ConfigManager.color("&cUsage : /spaceship give <joueur> <id>"));
            return;
        }
        if (!sender.hasPermission("spaceship.give")) {
            sender.sendMessage(plugin.getConfigManager().msgNoPerm());
            return;
        }
        Player target = plugin.getServer().getPlayer(args[1]);
        if (target == null) {
            sender.sendMessage(ConfigManager.color("&cJoueur introuvable (doit etre en ligne)."));
            return;
        }
        long id;
        try { id = Long.parseLong(args[2]); }
        catch (NumberFormatException e) {
            sender.sendMessage(ConfigManager.color("&cID invalide."));
            return;
        }
        Spaceship ship = plugin.getDatabaseManager().getSpaceship(id);
        if (ship == null) {
            sender.sendMessage(ConfigManager.color("&cSpaceship introuvable."));
            return;
        }
        if (!ship.getOwnerUuid().equals(target.getUniqueId())
                && !sender.hasPermission("spaceship.admin")) {
            sender.sendMessage(ConfigManager.color("&cLe spaceship #" + id + " n'appartient pas a " + target.getName() + "."));
            return;
        }

        // Nettoie d'eventuels doublons et compte ce qui reste.
        plugin.getSpaceshipManager().sanitizePlayerRemotes(target);
        int existing = countRemotes(target, id);
        if (existing >= 1) {
            sender.sendMessage(ConfigManager.color("&7" + target.getName()
                    + " possede deja la telecommande #" + id + " (rien a faire)."));
            return;
        }
        giveRemote(target, ship);
        sender.sendMessage(ConfigManager.color("&aTelecommande #" + id + " donnee a " + target.getName() + "."));
        if (target != sender) {
            target.sendMessage(plugin.getConfigManager().prefix()
                    + ConfigManager.color("&aTelecommande &b" + ship.getName() + " &arendue."));
        }
    }

    /** Version courte pour soi-meme : /spaceship remote <id>. */
    private void handleRemoteSelf(CommandSender sender, String[] args) {
        if (!(sender instanceof Player player)) {
            sender.sendMessage(ConfigManager.color("&cCommande joueur uniquement."));
            return;
        }
        if (args.length < 2) {
            sender.sendMessage(ConfigManager.color("&cUsage : /spaceship remote <id>"));
            return;
        }
        // Reutilise la logique de give pour soi-meme.
        handleGive(sender, new String[]{"give", player.getName(), args[1]});
    }

    private int countRemotes(Player p, long id) {
        int n = 0;
        for (ItemStack it : p.getInventory().getContents()) {
            if (it == null || !plugin.getRemoteManager().isRemote(it)) continue;
            long sid = plugin.getRemoteManager().getShipId(it);
            if (sid == id) n++;
        }
        return n;
    }

    private void giveRemote(Player target, Spaceship ship) {
        ItemStack remote = plugin.getRemoteManager().buildRemote(ship);
        HashMap<Integer, ItemStack> remaining = target.getInventory().addItem(remote);
        if (!remaining.isEmpty()) {
            target.getWorld().dropItemNaturally(target.getLocation(), remote);
        }
    }

    /* ============================ LIST ============================ */

    private void handleList(CommandSender sender, String[] args) {
        UUID target; String name;
        if (args.length >= 2) {
            if (!sender.hasPermission("spaceship.admin")) {
                sender.sendMessage(plugin.getConfigManager().msgNoPerm());
                return;
            }
            OfflinePlayer p = resolveOfflinePlayer(args[1]);
            if (p == null) {
                sender.sendMessage(ConfigManager.color("&cJoueur introuvable."));
                return;
            }
            target = p.getUniqueId();
            name = p.getName() != null ? p.getName() : args[1];
        } else {
            if (!(sender instanceof Player p)) {
                sender.sendMessage(ConfigManager.color("&cSpecifiez un joueur."));
                return;
            }
            target = p.getUniqueId();
            name = p.getName();
        }

        List<Spaceship> ships = plugin.getDatabaseManager().getSpaceshipsByOwner(target);
        sender.sendMessage(ConfigManager.color("&bSpaceships de &f" + name + " &b: &f" + ships.size()));
        for (Spaceship s : ships) {
            boolean loaded = plugin.getSpaceshipManager().isLoaded(s.getId());
            sender.sendMessage(ConfigManager.color("&7- &f#" + s.getId() + " &b" + s.getName()
                    + " &7Lv&f" + s.getLevel() + " &7" + s.getSizeX() + "x" + s.getSizeY() + "x" + s.getSizeZ()
                    + " &7" + (loaded ? "&aCHARGE" : "&8decharge")));
        }
    }

    /* ============================ INFO ============================ */

    private void handleInfo(CommandSender sender, String[] args) {
        UUID target; String name;
        if (args.length >= 2) {
            if (!sender.hasPermission("spaceship.info.other") && !sender.hasPermission("spaceship.admin")) {
                sender.sendMessage(plugin.getConfigManager().msgNoPerm());
                return;
            }
            OfflinePlayer p = resolveOfflinePlayer(args[1]);
            if (p == null) {
                sender.sendMessage(ConfigManager.color("&cJoueur introuvable."));
                return;
            }
            target = p.getUniqueId();
            name = p.getName() != null ? p.getName() : args[1];
        } else {
            if (!(sender instanceof Player p)) {
                sender.sendMessage(ConfigManager.color("&cSpecifiez un joueur."));
                return;
            }
            target = p.getUniqueId();
            name = p.getName();
        }

        List<Spaceship> ships = plugin.getDatabaseManager().getSpaceshipsByOwner(target);
        EconomyHook eco = plugin.getEconomy();
        double balance = eco.isReady() ? eco.getBalance(target) : 0;
        sender.sendMessage(ConfigManager.color("&b&l== Infos spaceships de &f" + name + " &b&l(" + ships.size() + ") =="));
        sender.sendMessage(ConfigManager.color("&7Solde Vault : &6" + (eco.isReady() ? eco.format(balance) : "-")));
        for (Spaceship s : ships) {
            LoadedSpaceship loaded = plugin.getSpaceshipManager().getLoaded(s.getId());
            String status = loaded != null
                    ? "&aCHARGE &7@ " + loaded.getWorldName() + " " + loaded.getOriginX() + "," + loaded.getOriginY() + "," + loaded.getOriginZ()
                    : "&8decharge";
            double cost = plugin.getSpaceshipManager().upgradeCost(s.getLevel());
            int[] nextSize = ShipSizing.sizeForLevel(plugin.getConfigManager(), s.getLevel() + 1);
            int jumpMax = plugin.getSpaceshipManager().spaceJumpMax(s.getLevel());
            sender.sendMessage(ConfigManager.color("&7-------------------------"));
            sender.sendMessage(ConfigManager.color("&b#" + s.getId() + " &f" + s.getName()));
            sender.sendMessage(ConfigManager.color("  &7Statut : " + status));
            sender.sendMessage(ConfigManager.color("  &7Niveau : &e" + s.getLevel()
                    + " &7(upgrade : &6" + (eco.isReady() ? eco.format(cost) : cost) + "&7)"));
            sender.sendMessage(ConfigManager.color("  &7Taille : &f" + s.getSizeX() + "x" + s.getSizeY() + "x" + s.getSizeZ()
                    + " &7(prochaine : &f" + nextSize[0] + "x" + nextSize[1] + "x" + nextSize[2] + "&7)"));
            sender.sendMessage(ConfigManager.color("  &7Saut max : &f" + jumpMax + " &7blocs"));
            sender.sendMessage(ConfigManager.color("  &7Spawn (rel.) : &f" + s.getSpawnX() + "," + s.getSpawnY() + "," + s.getSpawnZ()));
        }
        if (ships.isEmpty()) {
            sender.sendMessage(ConfigManager.color("&7Aucun spaceship."));
        }
    }

    /* ============================ DELETE ============================ */

    private void handleDelete(CommandSender sender, String[] args) {
        if (args.length < 2) {
            sender.sendMessage(ConfigManager.color("&cUsage : /spaceship delete <id>"));
            return;
        }
        long id;
        try { id = Long.parseLong(args[1]); }
        catch (NumberFormatException e) {
            sender.sendMessage(ConfigManager.color("&cID invalide."));
            return;
        }
        Spaceship ship = plugin.getDatabaseManager().getSpaceship(id);
        if (ship == null) {
            sender.sendMessage(ConfigManager.color("&cSpaceship introuvable."));
            return;
        }
        if (!sender.hasPermission("spaceship.admin")
                && (!(sender instanceof Player p) || !ship.getOwnerUuid().equals(p.getUniqueId()))) {
            sender.sendMessage(plugin.getConfigManager().msgNotOwner());
            return;
        }
        plugin.getSpaceshipManager().delete(ship);
        sender.sendMessage(plugin.getConfigManager().msgDeleted());
    }

    /* ============================ RELOAD ============================ */

    private void handleReload(CommandSender sender) {
        if (!sender.hasPermission("spaceship.reload")) {
            sender.sendMessage(plugin.getConfigManager().msgNoPerm());
            return;
        }
        plugin.getConfigManager().reload();
        plugin.getModelManager().reload();
        sender.sendMessage(ConfigManager.color("&aConfiguration rechargee."));
    }

    /* ============================ HELPERS ============================ */

    private OfflinePlayer resolveOfflinePlayer(String name) {
        Player p = plugin.getServer().getPlayer(name);
        if (p != null) return p;
        OfflinePlayer off = plugin.getServer().getOfflinePlayerIfCached(name);
        return off; // peut etre null
    }

    @Override
    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
        if (args.length == 1) {
            return Arrays.asList("help", "create", "give", "remote", "list", "info", "delete", "reload");
        }
        if (args.length == 2 && (args[0].equalsIgnoreCase("give")
                || args[0].equalsIgnoreCase("list")
                || args[0].equalsIgnoreCase("info"))) {
            List<String> out = new ArrayList<>();
            for (Player p : plugin.getServer().getOnlinePlayers()) out.add(p.getName());
            return out;
        }
        if (args.length == 2 && (args[0].equalsIgnoreCase("delete") || args[0].equalsIgnoreCase("remote"))
                && sender instanceof Player p) {
            List<String> out = new ArrayList<>();
            for (Spaceship s : plugin.getDatabaseManager().getSpaceshipsByOwner(p.getUniqueId())) {
                out.add(String.valueOf(s.getId()));
            }
            return out;
        }
        if (args.length == 3 && args[0].equalsIgnoreCase("give")) {
            Player target = plugin.getServer().getPlayer(args[1]);
            if (target != null) {
                List<String> out = new ArrayList<>();
                for (Spaceship s : plugin.getDatabaseManager().getSpaceshipsByOwner(target.getUniqueId())) {
                    out.add(String.valueOf(s.getId()));
                }
                return out;
            }
        }
        return new ArrayList<>();
    }
}
