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.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;

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

/**
 * Commande admin /spaceshipadmin (/ssa).
 *
 * Sous-commandes :
 *   - reload                                                : recharge config + modeles
 *   - list [joueur]                                         : liste les ships (tous ou d'un joueur)
 *   - delete <id>                                           : supprime un ship n'importe lequel
 *   - addmoney <joueur> <id> <montant>                      : donne de la money a un ship
 *   - setlevel <joueur> <id> <level>                        : force le niveau d'un ship
 *   - setname <joueur> <id> <nom...>                        : renomme un ship
 *   - setconfig <chemin> <valeur>                           : modifie config.yml
 *   - getconfig <chemin>                                    : lit config.yml
 *   - loadmodel [nom]                                       : place le modele dans le monde pour edition
 *   - savemodel                                             : sauvegarde la session active
 *   - cancelmodel                                           : annule la session active
 */
public class SpaceShipAdminCommand implements CommandExecutor, TabCompleter {

    private final SpaceShipProject plugin;

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

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!sender.hasPermission("spaceship.admin")) {
            sender.sendMessage(plugin.getConfigManager().msgNoPerm());
            return true;
        }
        if (args.length == 0 || args[0].equalsIgnoreCase("help")) {
            help(sender);
            return true;
        }
        switch (args[0].toLowerCase()) {
            case "reload"      -> handleReload(sender);
            case "list"        -> handleList(sender, args);
            case "delete"      -> handleDelete(sender, args);
            case "addmoney"    -> handleAddMoney(sender, args);
            case "setlevel"    -> handleSetLevel(sender, args);
            case "setname"     -> handleSetName(sender, args);
            case "setconfig"   -> handleSetConfig(sender, args);
            case "getconfig"   -> handleGetConfig(sender, args);
            case "loadmodel"   -> handleLoadModel(sender, args);
            case "savemodel"   -> handleSaveModel(sender);
            case "cancelmodel" -> handleCancelModel(sender);
            default -> sender.sendMessage(ConfigManager.color("&cSous-commande inconnue. /ssa help"));
        }
        return true;
    }

    private void help(CommandSender s) {
        s.sendMessage(ConfigManager.color("&c&l=== SpaceShipAdmin ==="));
        s.sendMessage(ConfigManager.color("&7/ssa reload"));
        s.sendMessage(ConfigManager.color("&7/ssa list [joueur]"));
        s.sendMessage(ConfigManager.color("&7/ssa delete <id>"));
        s.sendMessage(ConfigManager.color("&7/ssa addmoney <joueur> <montant> &8(via Vault)"));
        s.sendMessage(ConfigManager.color("&7/ssa setlevel <joueur> <id> <level>"));
        s.sendMessage(ConfigManager.color("&7/ssa setname <joueur> <id> <nom...>"));
        s.sendMessage(ConfigManager.color("&7/ssa setconfig <chemin> <valeur>"));
        s.sendMessage(ConfigManager.color("&7/ssa getconfig <chemin>"));
        s.sendMessage(ConfigManager.color("&7/ssa loadmodel [nom]"));
        s.sendMessage(ConfigManager.color("&7/ssa savemodel"));
        s.sendMessage(ConfigManager.color("&7/ssa cancelmodel"));
    }

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

    private void handleReload(CommandSender s) {
        plugin.getConfigManager().reload();
        plugin.getModelManager().reload();
        s.sendMessage(ConfigManager.color("&aConfig et modeles recharges."));
    }

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

    private void handleList(CommandSender s, String[] args) {
        if (args.length >= 2) {
            OfflinePlayer p = resolveOfflinePlayer(args[1]);
            if (p == null) { s.sendMessage(ConfigManager.color("&cJoueur introuvable.")); return; }
            List<Spaceship> ships = plugin.getDatabaseManager().getSpaceshipsByOwner(p.getUniqueId());
            s.sendMessage(ConfigManager.color("&bShips de &f" + (p.getName() != null ? p.getName() : args[1])
                    + " &b: &f" + ships.size()));
            for (Spaceship ship : ships) {
                s.sendMessage(ConfigManager.color("&7- &f#" + ship.getId() + " &b" + ship.getName()
                        + " &7Lv&f" + ship.getLevel() + " &7Taille&f " + ship.getSizeX() + "x" + ship.getSizeY() + "x" + ship.getSizeZ()));
            }
        } else {
            // Liste de tous les loaded actuels
            List<LoadedSpaceship> loaded = plugin.getDatabaseManager().getAllLoaded();
            s.sendMessage(ConfigManager.color("&bSpaceships actuellement charges : &f" + loaded.size()));
            for (LoadedSpaceship l : loaded) {
                Spaceship ship = plugin.getDatabaseManager().getSpaceship(l.getSpaceshipId());
                if (ship == null) continue;
                s.sendMessage(ConfigManager.color("&7- &f#" + ship.getId() + " &b" + ship.getName()
                        + " &7@ " + l.getWorldName() + " " + l.getOriginX() + "," + l.getOriginY() + "," + l.getOriginZ()));
            }
        }
    }

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

    private void handleDelete(CommandSender s, String[] args) {
        if (args.length < 2) { s.sendMessage(ConfigManager.color("&cUsage : /ssa delete <id>")); return; }
        long id;
        try { id = Long.parseLong(args[1]); } catch (NumberFormatException e) {
            s.sendMessage(ConfigManager.color("&cID invalide.")); return;
        }
        Spaceship ship = plugin.getDatabaseManager().getSpaceship(id);
        if (ship == null) { s.sendMessage(ConfigManager.color("&cShip introuvable.")); return; }
        plugin.getSpaceshipManager().delete(ship);
        s.sendMessage(ConfigManager.color("&aShip #" + id + " supprime."));
    }

    /* ============================ MONEY / LEVEL / NAME ============================ */

    private void handleAddMoney(CommandSender s, String[] args) {
        if (args.length < 3) { s.sendMessage(ConfigManager.color("&cUsage : /ssa addmoney <joueur> <montant>")); return; }
        OfflinePlayer p = resolveOfflinePlayer(args[1]);
        if (p == null) { s.sendMessage(ConfigManager.color("&cJoueur introuvable.")); return; }
        double amount;
        try { amount = Double.parseDouble(args[2]); } catch (NumberFormatException e) {
            s.sendMessage(ConfigManager.color("&cMontant invalide.")); return;
        }
        EconomyHook eco = plugin.getEconomy();
        if (!eco.isReady()) { s.sendMessage(plugin.getConfigManager().msgVaultUnavailable()); return; }
        if (!eco.deposit(p.getUniqueId(), amount)) {
            s.sendMessage(ConfigManager.color("&cEchec du depot."));
            return;
        }
        s.sendMessage(ConfigManager.color("&a+" + eco.format(amount) + " depose sur le solde Vault de "
                + (p.getName() != null ? p.getName() : args[1]) + "."));
    }

    private void handleSetLevel(CommandSender s, String[] args) {
        if (args.length < 4) { s.sendMessage(ConfigManager.color("&cUsage : /ssa setlevel <joueur> <id> <level>")); return; }
        Spaceship ship = resolveShip(s, args[1], args[2]);
        if (ship == null) return;
        int level;
        try { level = Math.max(1, Integer.parseInt(args[3])); } catch (NumberFormatException e) {
            s.sendMessage(ConfigManager.color("&cNiveau invalide.")); return;
        }
        ship.setLevel(level);
        plugin.getDatabaseManager().updateSpaceship(ship);
        s.sendMessage(ConfigManager.color("&aNiveau de #" + ship.getId() + " : &e" + level));
    }

    private void handleSetName(CommandSender s, String[] args) {
        if (args.length < 4) { s.sendMessage(ConfigManager.color("&cUsage : /ssa setname <joueur> <id> <nom...>")); return; }
        Spaceship ship = resolveShip(s, args[1], args[2]);
        if (ship == null) return;
        StringBuilder sb = new StringBuilder();
        for (int i = 3; i < args.length; i++) {
            if (i > 3) sb.append(' ');
            sb.append(args[i]);
        }
        String name = sb.toString();
        if (name.length() > 32) name = name.substring(0, 32);
        ship.setName(name);
        plugin.getDatabaseManager().updateSpaceship(ship);
        s.sendMessage(ConfigManager.color("&aShip renomme : &b" + name));
    }

    private Spaceship resolveShip(CommandSender s, String playerName, String idStr) {
        OfflinePlayer p = resolveOfflinePlayer(playerName);
        if (p == null) { s.sendMessage(ConfigManager.color("&cJoueur introuvable.")); return null; }
        long id;
        try { id = Long.parseLong(idStr); } catch (NumberFormatException e) {
            s.sendMessage(ConfigManager.color("&cID invalide.")); return null;
        }
        Spaceship ship = plugin.getDatabaseManager().getSpaceship(id);
        if (ship == null) { s.sendMessage(ConfigManager.color("&cShip introuvable.")); return null; }
        if (!ship.getOwnerUuid().equals(p.getUniqueId())) {
            s.sendMessage(ConfigManager.color("&cLe ship #" + id + " n'appartient pas a " + playerName + ".")); return null;
        }
        return ship;
    }

    /* ============================ CONFIG ============================ */

    private void handleSetConfig(CommandSender s, String[] args) {
        if (args.length < 3) { s.sendMessage(ConfigManager.color("&cUsage : /ssa setconfig <chemin> <valeur>")); return; }
        String path = args[1];
        StringBuilder valueB = new StringBuilder();
        for (int i = 2; i < args.length; i++) { if (i > 2) valueB.append(' '); valueB.append(args[i]); }
        Object parsed = parseValue(valueB.toString());
        FileConfiguration cfg = plugin.getConfig();
        cfg.set(path, parsed);
        plugin.saveConfig();
        plugin.getConfigManager().reload();
        s.sendMessage(ConfigManager.color("&aConfig &f" + path + " &asetee a &f" + parsed));
    }

    private void handleGetConfig(CommandSender s, String[] args) {
        if (args.length < 2) { s.sendMessage(ConfigManager.color("&cUsage : /ssa getconfig <chemin>")); return; }
        Object v = plugin.getConfig().get(args[1]);
        s.sendMessage(ConfigManager.color("&b" + args[1] + " &7= &f" + v));
    }

    private Object parseValue(String s) {
        if (s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false")) return Boolean.parseBoolean(s);
        try { return Integer.parseInt(s); } catch (NumberFormatException ignored) {}
        try { return Double.parseDouble(s); } catch (NumberFormatException ignored) {}
        return s;
    }

    /* ============================ MODEL ============================ */

    private void handleLoadModel(CommandSender s, String[] args) {
        if (!(s instanceof Player player)) { s.sendMessage(ConfigManager.color("&cCommande joueur uniquement.")); return; }
        String modelName = args.length >= 2 ? args[1] : "default";
        plugin.getModelManager().loadForEdit(player, modelName);
    }

    private void handleSaveModel(CommandSender s) {
        if (!(s instanceof Player player)) { s.sendMessage(ConfigManager.color("&cCommande joueur uniquement.")); return; }
        plugin.getModelManager().saveEdit(player);
    }

    private void handleCancelModel(CommandSender s) {
        if (!(s instanceof Player player)) { s.sendMessage(ConfigManager.color("&cCommande joueur uniquement.")); return; }
        plugin.getModelManager().cancelEdit(player);
    }

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

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

    @Override
    public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
        if (!sender.hasPermission("spaceship.admin")) return new ArrayList<>();
        if (args.length == 1) {
            return Arrays.asList("help", "reload", "list", "delete", "addmoney", "setlevel",
                    "setname", "setconfig", "getconfig", "loadmodel", "savemodel", "cancelmodel");
        }
        if (args.length == 2 && (args[0].equalsIgnoreCase("list")
                || args[0].equalsIgnoreCase("addmoney")
                || args[0].equalsIgnoreCase("setlevel")
                || args[0].equalsIgnoreCase("setname"))) {
            List<String> out = new ArrayList<>();
            for (Player p : plugin.getServer().getOnlinePlayers()) out.add(p.getName());
            return out;
        }
        if (args.length == 3 && (args[0].equalsIgnoreCase("setlevel")
                || args[0].equalsIgnoreCase("setname"))) {
            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;
            }
        }
        if (args.length == 2 && args[0].equalsIgnoreCase("loadmodel")) {
            return Arrays.asList("default");
        }
        if (args.length == 2 && args[0].equalsIgnoreCase("setconfig")) {
            return Arrays.asList("max-ships-per-player", "default-size.x", "default-size.y", "default-size.z",
                    "summon-offset-y", "safety.check-collision", "safety.min-y-above-player");
        }
        return new ArrayList<>();
    }
}
