package com.spaceshipproject;

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

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

/**
 * Interface de parametres d'un spaceship (ouverte via shift + clic droit sur la telecommande).
 *
 * Layout (27 slots) :
 *  - 4   : Info (tete : nom, taille, etat)
 *  - 11  : Invoquer / Decharger
 *  - 13  : Teleporter en haut / redescendre
 *  - 15  : Definir le spawn ici (uniquement si charge et joueur dessus)
 *  - 22  : Renommer le spaceship
 *  - 26  : Supprimer le spaceship (confirmation)
 *  - reste : verre de remplissage
 */
public class SpaceshipGUI implements SpaceshipGuiPanel {

    private static final int SIZE = 36;
    private static final int SLOT_INFO        = 4;
    private static final int SLOT_TOGGLE      = 19;
    private static final int SLOT_TELEPORT    = 20;
    private static final int SLOT_SET_SPAWN   = 22;
    private static final int SLOT_SPACE_JUMP  = 24;
    private static final int SLOT_UPGRADE     = 25;
    private static final int SLOT_RENAME      = 31;
    private static final int SLOT_DELETE      = 35;

    private final SpaceShipProject plugin;
    private final Player player;
    private final Spaceship ship;
    private final SpaceshipGUIHolder holder;
    private Inventory inv;

    public SpaceshipGUI(SpaceShipProject plugin, Player player, Spaceship ship) {
        this.plugin = plugin;
        this.player = player;
        this.ship = ship;
        this.holder = new SpaceshipGUIHolder(this);
    }

    public void open() {
        String title = ConfigManager.color("&8\u26F0 &bSpaceship &8\u2014 &f" + ship.getName());
        inv = Bukkit.createInventory(holder, SIZE, title);
        holder.setInventory(inv);
        render();
        SpaceshipGUIListener.registerOpen(player, this);
        player.openInventory(inv);
    }

    public Spaceship getShip() { return ship; }
    public Player getPlayer() { return player; }

    private void render() {
        for (int i = 0; i < SIZE; i++) inv.setItem(i, filler());

        SpaceshipManager mgr = plugin.getSpaceshipManager();
        boolean loaded = mgr.isLoaded(ship.getId());
        boolean onShip = loaded && mgr.isPlayerOnShip(player, ship);

        inv.setItem(SLOT_INFO, infoItem(loaded));

        inv.setItem(SLOT_TOGGLE, item(
                loaded ? Material.REDSTONE_TORCH : Material.LEVER,
                loaded ? "&c\u25A0 Decharger le spaceship" : "&a\u25B6 Invoquer le spaceship",
                loaded
                        ? List.of("&7Les modifications seront sauvegardees.")
                        : List.of("&7Charge le spaceship dans le ciel,",
                                  "&7au-dessus du sol ou vous etes.")
        ));

        inv.setItem(SLOT_TELEPORT, item(
                Material.ENDER_PEARL,
                onShip ? "&a\u2B0B Redescendre au sol" : "&b\u2B06 Teleporter sur le spaceship",
                onShip
                        ? List.of("&7Retourne a votre position au sol.")
                        : List.of("&7Vous teleporte sur le point de spawn",
                                  "&7du spaceship (l'invoque si besoin).")
        ));

        if (onShip) {
            inv.setItem(SLOT_SET_SPAWN, item(
                    Material.RESPAWN_ANCHOR,
                    "&e\u2605 Definir le spawn ici",
                    List.of("&7Sauvegarde votre position actuelle",
                            "&7comme nouveau point d'apparition.")
            ));
        } else {
            inv.setItem(SLOT_SET_SPAWN, item(
                    Material.GRAY_DYE,
                    "&8Definir le spawn",
                    List.of("&8(Indisponible : vous n'etes pas",
                            "&8actuellement sur le spaceship)")
            ));
        }

        EconomyHook eco = plugin.getEconomy();
        double balance = eco.isReady() ? eco.getBalance(player.getUniqueId()) : 0;
        double cost = mgr.upgradeCost(ship.getLevel());
        boolean atMax = ship.getLevel() >= ShipSizing.maxUsefulLevel(plugin.getConfigManager());
        boolean canAfford = eco.isReady() && balance >= cost;
        int[] currentSize = {ship.getSizeX(), ship.getSizeY(), ship.getSizeZ()};
        int[] nextSize = ShipSizing.sizeForLevel(plugin.getConfigManager(), ship.getLevel() + 1);
        inv.setItem(SLOT_UPGRADE, item(
                atMax ? Material.BARRIER : (canAfford ? Material.EXPERIENCE_BOTTLE : Material.GLASS_BOTTLE),
                atMax
                        ? "&8&l\u2728 Niveau maximum atteint"
                        : (canAfford ? "&a&l\u2728 Ameliorer (Lv " : "&7&l\u2728 Ameliorer (Lv ")
                            + ship.getLevel() + " \u279C " + (ship.getLevel() + 1) + ")",
                atMax ? List.of("&7Le ship est deja a sa taille maximale.")
                      : List.of(
                        "&7Niveau actuel : &e" + ship.getLevel(),
                        "&7Taille : &f" + currentSize[0] + "x" + currentSize[1] + "x" + currentSize[2]
                                + " &7\u279C &f" + nextSize[0] + "x" + nextSize[1] + "x" + nextSize[2],
                        "&7Cout : &6" + (eco.isReady() ? eco.format(cost) : cost),
                        "&7Solde : &6" + (eco.isReady() ? eco.format(balance) : "-"),
                        "",
                        canAfford ? "&aClic &7pour ameliorer." : "&cFonds insuffisants."
                )
        ));

        // Bouton Saut Spatial : actif uniquement quand le joueur est sur le ship.
        int jumpMax = mgr.spaceJumpMax(ship.getLevel());
        if (onShip) {
            inv.setItem(SLOT_SPACE_JUMP, item(
                    Material.ENDER_EYE,
                    "&d&l\u27FC Saut Spatial",
                    List.of(
                            "&7Deplace le spaceship le long d'un axe.",
                            "&7Distance max : &f" + jumpMax + " &7blocs",
                            "&7Cout : &6" + (eco.isReady() ? eco.format(1) : "1") + " &7par bloc",
                            "",
                            "&eClic pour ouvrir le panneau de saut."
                    )
            ));
        } else {
            inv.setItem(SLOT_SPACE_JUMP, item(
                    Material.GRAY_DYE,
                    "&8\u27FC Saut Spatial",
                    List.of("&8(Indisponible : vous n'etes pas",
                            "&8actuellement sur le spaceship)")
            ));
        }

        inv.setItem(SLOT_RENAME, item(
                Material.NAME_TAG,
                "&e\u270F Renommer",
                List.of("&7Tapez le nouveau nom dans le chat.",
                        "&7Tapez &ccancel &7pour annuler.")
        ));

        inv.setItem(SLOT_DELETE, item(
                Material.BARRIER,
                "&c\u2620 Supprimer le spaceship",
                List.of("&7Suppression definitive (telecommande",
                        "&7incluse). Decharge le ship d'abord.",
                        "&cShift + clic pour confirmer.")
        ));
    }

    private ItemStack infoItem(boolean loaded) {
        ItemStack head = new ItemStack(Material.NETHER_STAR);
        ItemMeta meta = head.getItemMeta();
        if (meta != null) {
            meta.setDisplayName(ConfigManager.color("&b&l\u2730 &f" + ship.getName()));
            EconomyHook eco = plugin.getEconomy();
            double balance = eco.isReady() ? eco.getBalance(player.getUniqueId()) : 0;
            List<String> lore = new ArrayList<>();
            lore.add(ConfigManager.color("&7ID : &f#" + ship.getId()));
            lore.add(ConfigManager.color("&7Niveau : &e" + ship.getLevel()));
            lore.add(ConfigManager.color("&7Votre solde : &6" + (eco.isReady() ? eco.format(balance) : "-")));
            lore.add(ConfigManager.color("&7Taille : &f"
                    + ship.getSizeX() + "x" + ship.getSizeY() + "x" + ship.getSizeZ()));
            lore.add(ConfigManager.color("&7Spawn (rel.) : &f"
                    + ship.getSpawnX() + ", " + ship.getSpawnY() + ", " + ship.getSpawnZ()));
            lore.add(ConfigManager.color("&7Statut : " + (loaded ? "&aCHARGE" : "&7decharge")));
            meta.setLore(lore);
            head.setItemMeta(meta);
        }
        return head;
    }

    private ItemStack filler() {
        ItemStack stack = new ItemStack(Material.BLACK_STAINED_GLASS_PANE);
        ItemMeta meta = stack.getItemMeta();
        if (meta != null) {
            meta.setDisplayName(" ");
            stack.setItemMeta(meta);
        }
        return stack;
    }

    private ItemStack item(Material mat, String name, List<String> lore) {
        ItemStack stack = new ItemStack(mat);
        ItemMeta meta = stack.getItemMeta();
        if (meta != null) {
            meta.setDisplayName(ConfigManager.color(name));
            List<String> colored = new ArrayList<>(lore.size());
            for (String s : lore) colored.add(ConfigManager.color(s));
            meta.setLore(colored);
            stack.setItemMeta(meta);
        }
        return stack;
    }

    public void handleClick(InventoryClickEvent event) {
        int slot = event.getRawSlot();
        SpaceshipManager mgr = plugin.getSpaceshipManager();

        switch (slot) {
            case SLOT_TOGGLE -> {
                if (mgr.isLoaded(ship.getId())) {
                    if (mgr.isPlayerOnShip(player, ship)) {
                        mgr.teleportDown(player, ship);
                    }
                    mgr.unload(player, ship);
                } else {
                    mgr.summon(player, ship);
                }
                player.closeInventory();
            }
            case SLOT_TELEPORT -> {
                if (!mgr.isLoaded(ship.getId())) {
                    if (mgr.summon(player, ship)) mgr.teleportToShip(player, ship);
                } else if (mgr.isPlayerOnShip(player, ship)) {
                    mgr.teleportDown(player, ship);
                } else {
                    mgr.teleportToShip(player, ship);
                }
                player.closeInventory();
            }
            case SLOT_SET_SPAWN -> {
                if (!mgr.isLoaded(ship.getId()) || !mgr.isPlayerOnShip(player, ship)) return;
                LoadedSpaceship loaded = mgr.getLoaded(ship.getId());
                if (loaded == null) return;
                int rx = player.getLocation().getBlockX() - loaded.getOriginX();
                int ry = player.getLocation().getBlockY() - loaded.getOriginY();
                int rz = player.getLocation().getBlockZ() - loaded.getOriginZ();
                ship.setSpawn(rx, ry, rz);
                plugin.getDatabaseManager().updateSpaceship(ship);
                player.sendMessage(plugin.getConfigManager().prefix()
                        + ConfigManager.color("&aNouveau spawn enregistre."));
                render();
            }
            case SLOT_UPGRADE -> {
                double cost = mgr.upgradeCost(ship.getLevel());
                if (mgr.upgradeLevel(player, ship)) {
                    EconomyHook eco = plugin.getEconomy();
                    String costStr = eco.isReady() ? eco.format(cost) : String.valueOf(cost);
                    player.sendMessage(plugin.getConfigManager().prefix()
                            + ConfigManager.color("&aSpaceship ameliore au niveau &e" + ship.getLevel() + " &a(-&6" + costStr + "&a)."));
                    refreshHandRemote();
                    render();
                }
            }
            case SLOT_SPACE_JUMP -> {
                if (mgr.isPlayerOnShip(player, ship)) {
                    new SpaceJumpGUI(plugin, player, ship).open();
                }
            }
            case SLOT_RENAME -> {
                SpaceshipGUIListener.registerPendingRename(player, ship);
                player.closeInventory();
                player.sendMessage(plugin.getConfigManager().prefix()
                        + ConfigManager.color("&eTapez le nouveau nom dans le chat (&ccancel&e pour annuler)."));
            }
            case SLOT_DELETE -> {
                if (!event.isShiftClick()) {
                    player.sendMessage(plugin.getConfigManager().prefix()
                            + ConfigManager.color("&cShift + clic pour confirmer la suppression."));
                    return;
                }
                mgr.delete(ship);
                player.sendMessage(plugin.getConfigManager().msgDeleted());
                player.closeInventory();
            }
            default -> { /* ignore */ }
        }
    }

    private void refreshHandRemote() {
        ItemStack mainHand = player.getInventory().getItemInMainHand();
        if (plugin.getRemoteManager().isRemote(mainHand)
                && plugin.getRemoteManager().getShipId(mainHand) == ship.getId()) {
            plugin.getRemoteManager().refreshRemote(mainHand, ship);
            player.getInventory().setItemInMainHand(mainHand);
        }
    }
}
