package com.spaceshipproject;

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
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;

/**
 * GUI "Saut Spatial".
 *
 * Layout (36 slots) :
 *   Slot 4   : info (niveau, max, cout courant)
 *   Slots 11..16 : selection de direction (X-, X+, Z-, Z+, Y-, Y+)
 *   Slots 19..25 : ajustement de distance (-50 -10 -1 [val] +1 +10 +50)
 *   Slot 31  : confirmer
 *   Slot 35  : annuler
 */
public class SpaceJumpGUI implements SpaceshipGuiPanel {

    private static final int SIZE = 36;
    private static final int SLOT_INFO = 4;
    private static final int SLOT_X_MINUS = 11;
    private static final int SLOT_X_PLUS  = 12;
    private static final int SLOT_Z_MINUS = 13;
    private static final int SLOT_Z_PLUS  = 14;
    private static final int SLOT_Y_MINUS = 15;
    private static final int SLOT_Y_PLUS  = 16;
    private static final int SLOT_M50 = 19, SLOT_M10 = 20, SLOT_M1 = 21;
    private static final int SLOT_DIST = 22;
    private static final int SLOT_P1 = 23, SLOT_P10 = 24, SLOT_P50 = 25;
    private static final int SLOT_CONFIRM = 31;
    private static final int SLOT_CANCEL  = 35;

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

    private char axis = 'X';
    private int signedDistance = 10;

    public SpaceJumpGUI(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\u27FC &bSaut Spatial &8\u2014 &f" + ship.getName());
        inv = Bukkit.createInventory(holder, SIZE, title);
        holder.setInventory(inv);
        render();
        SpaceshipGUIListener.registerOpenJump(player, this);
        player.openInventory(inv);
    }

    public Spaceship getShip() { return ship; }

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

        int max = plugin.getSpaceshipManager().spaceJumpMax(ship.getLevel());
        if (Math.abs(signedDistance) > max) {
            signedDistance = (signedDistance < 0 ? -1 : 1) * max;
        }
        if (Math.abs(signedDistance) < 1) signedDistance = 1;

        double cost = plugin.getSpaceshipManager().spaceJumpCost(Math.abs(signedDistance));
        EconomyHook eco = plugin.getEconomy();
        String balance = eco.isReady() ? eco.format(eco.getBalance(player.getUniqueId())) : "-";
        String costStr = eco.isReady() ? eco.format(cost) : String.valueOf(cost);

        inv.setItem(SLOT_INFO, item(Material.ENDER_EYE,
                "&b&l\u2730 Saut Spatial",
                List.of(
                        "&7Spaceship : &f" + ship.getName(),
                        "&7Niveau : &e" + ship.getLevel() + " &7(max &f" + max + " &7blocs)",
                        "&7Direction : &b" + dirLabel(),
                        "&7Distance : &f" + Math.abs(signedDistance),
                        "&7Cout : &6" + costStr,
                        "&7Solde : &6" + balance
                )));

        inv.setItem(SLOT_X_MINUS, dirButton('X', -1, "&aX-", "Ouest"));
        inv.setItem(SLOT_X_PLUS,  dirButton('X',  1, "&aX+", "Est"));
        inv.setItem(SLOT_Z_MINUS, dirButton('Z', -1, "&aZ-", "Nord"));
        inv.setItem(SLOT_Z_PLUS,  dirButton('Z',  1, "&aZ+", "Sud"));
        inv.setItem(SLOT_Y_MINUS, dirButton('Y', -1, "&aY-", "Bas"));
        inv.setItem(SLOT_Y_PLUS,  dirButton('Y',  1, "&aY+", "Haut"));

        inv.setItem(SLOT_M50, item(Material.RED_CONCRETE,    "&c-50",  List.of("&7Reduit la distance.")));
        inv.setItem(SLOT_M10, item(Material.RED_CONCRETE,    "&c-10",  List.of("&7Reduit la distance.")));
        inv.setItem(SLOT_M1,  item(Material.RED_CONCRETE,    "&c-1",   List.of("&7Reduit la distance.")));
        inv.setItem(SLOT_DIST, item(Material.PAPER,
                "&f&lDistance : " + Math.abs(signedDistance),
                List.of("&7Cout : &6" + costStr,
                        "&7Max : &f" + max,
                        "&7Direction : &b" + dirLabel())));
        inv.setItem(SLOT_P1,  item(Material.LIME_CONCRETE,   "&a+1",   List.of("&7Augmente la distance.")));
        inv.setItem(SLOT_P10, item(Material.LIME_CONCRETE,   "&a+10",  List.of("&7Augmente la distance.")));
        inv.setItem(SLOT_P50, item(Material.LIME_CONCRETE,   "&a+50",  List.of("&7Augmente la distance.")));

        boolean canAfford = !eco.isReady() || eco.has(player.getUniqueId(), cost);
        inv.setItem(SLOT_CONFIRM, item(
                canAfford ? Material.EMERALD_BLOCK : Material.REDSTONE_BLOCK,
                canAfford ? "&a&l\u2714 CONFIRMER" : "&c\u2718 Fonds insuffisants",
                List.of(
                        "&7Direction : &b" + dirLabel(),
                        "&7Distance : &f" + Math.abs(signedDistance),
                        "&7Cout : &6" + costStr,
                        "",
                        canAfford ? "&aClic pour lancer le saut." : "&cVotre solde est trop bas."
                )
        ));
        inv.setItem(SLOT_CANCEL, item(Material.BARRIER, "&c\u2718 Annuler", List.of("&7Ferme la fenetre.")));
    }

    private String dirLabel() {
        return switch (axis) {
            case 'X' -> signedDistance >= 0 ? "Est (X+)"  : "Ouest (X-)";
            case 'Y' -> signedDistance >= 0 ? "Haut (Y+)" : "Bas (Y-)";
            case 'Z' -> signedDistance >= 0 ? "Sud (Z+)"  : "Nord (Z-)";
            default  -> "?";
        };
    }

    private ItemStack dirButton(char a, int sign, String name, String label) {
        boolean selected = axis == a && Integer.signum(signedDistance) == sign;
        return item(selected ? Material.LIME_STAINED_GLASS_PANE : Material.GRAY_STAINED_GLASS_PANE,
                (selected ? "&a&l" : "&7") + name + " &7(" + label + ")",
                List.of(selected ? "&aSelectionne" : "&7Clic pour selectionner"));
    }

    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();
        switch (slot) {
            case SLOT_X_MINUS -> { axis = 'X'; signedDistance = -Math.abs(currentDist()); render(); }
            case SLOT_X_PLUS  -> { axis = 'X'; signedDistance =  Math.abs(currentDist()); render(); }
            case SLOT_Z_MINUS -> { axis = 'Z'; signedDistance = -Math.abs(currentDist()); render(); }
            case SLOT_Z_PLUS  -> { axis = 'Z'; signedDistance =  Math.abs(currentDist()); render(); }
            case SLOT_Y_MINUS -> { axis = 'Y'; signedDistance = -Math.abs(currentDist()); render(); }
            case SLOT_Y_PLUS  -> { axis = 'Y'; signedDistance =  Math.abs(currentDist()); render(); }
            case SLOT_M50 -> { adjust(-50, event.getClick()); }
            case SLOT_M10 -> { adjust(-10, event.getClick()); }
            case SLOT_M1  -> { adjust(-1,  event.getClick()); }
            case SLOT_P1  -> { adjust( 1,  event.getClick()); }
            case SLOT_P10 -> { adjust( 10, event.getClick()); }
            case SLOT_P50 -> { adjust( 50, event.getClick()); }
            case SLOT_CONFIRM -> {
                int sign = Integer.signum(signedDistance);
                if (sign == 0) sign = 1;
                int abs = Math.abs(signedDistance);
                player.closeInventory();
                plugin.getSpaceshipManager().spaceJump(player, ship, axis, sign * abs);
            }
            case SLOT_CANCEL -> player.closeInventory();
            default -> { /* ignore */ }
        }
    }

    private int currentDist() { int d = Math.abs(signedDistance); return d == 0 ? 1 : d; }

    private void adjust(int delta, ClickType click) {
        // Shift = x10 pour aller plus vite.
        if (click == ClickType.SHIFT_LEFT || click == ClickType.SHIFT_RIGHT) delta *= 10;
        int sign = Integer.signum(signedDistance);
        if (sign == 0) sign = 1;
        int abs = Math.abs(signedDistance) + delta;
        if (abs < 1) abs = 1;
        int max = plugin.getSpaceshipManager().spaceJumpMax(ship.getLevel());
        if (abs > max) abs = max;
        signedDistance = sign * abs;
        render();
    }
}
