package shop.morpheusnox.backpackInfinita;

import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class Backpack {

    private final Player player;
    private final Inventory inventoryView;
    private final List<ItemStack> internalContents;
    private int currentPage;
    public static final int ITEMS_PER_PAGE = 45; // 54 slots no total - 9 para navegação

    public Backpack(Player player) {
        this.player = player;
        this.inventoryView = Bukkit.createInventory(null, 54, "Mochila");
        this.internalContents = new ArrayList<>();
        this.currentPage = 0;
    }

    public Inventory getInventoryView() {
        return inventoryView;
    }

    public List<ItemStack> getInternalContents() {
        return internalContents;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getTotalPages() {
        return (int) Math.ceil((double) internalContents.size() / ITEMS_PER_PAGE);
    }

    public void open() {
        inventoryView.clear();

        int startIndex = currentPage * ITEMS_PER_PAGE;
        int endIndex = Math.min(startIndex + ITEMS_PER_PAGE, internalContents.size());

        for (int i = startIndex; i < endIndex; i++) {
            ItemStack item = internalContents.get(i);
            ItemStack displayItem = item.clone();
            if (displayItem.getAmount() > displayItem.getMaxStackSize()) {
                // Adiciona lore para mostrar a quantidade real
                List<String> lore = displayItem.hasItemMeta() && displayItem.getItemMeta().hasLore() ? displayItem.getItemMeta().getLore() : new ArrayList<>();
                lore.add("§7Quantidade: §a" + item.getAmount());
                ItemMeta meta = displayItem.getItemMeta();
                meta.setLore(lore);
                displayItem.setItemMeta(meta);
                displayItem.setAmount(displayItem.getMaxStackSize()); // Exibe o tamanho máximo da pilha na GUI
            }
            inventoryView.addItem(displayItem);
        }

        // Adiciona botões de navegação
        addNavigationButtons();

        player.openInventory(inventoryView);
    }

    private void addNavigationButtons() {
        // Botão Página Anterior
        ItemStack prevPage = new ItemStack(Material.ARROW);
        ItemMeta prevMeta = prevPage.getItemMeta();
        prevMeta.setDisplayName("§aPágina Anterior");
        prevPage.setItemMeta(prevMeta);
        inventoryView.setItem(45, prevPage);

        // Informação da Página Atual
        ItemStack pageInfo = new ItemStack(Material.PAPER);
        ItemMeta infoMeta = pageInfo.getItemMeta();
        infoMeta.setDisplayName("§ePágina " + (currentPage + 1) + "/" + (getTotalPages() == 0 ? 1 : getTotalPages()));
        pageInfo.setItemMeta(infoMeta);
        inventoryView.setItem(49, pageInfo);

        // Botão Próxima Página
        ItemStack nextPage = new ItemStack(Material.ARROW);
        ItemMeta nextMeta = nextPage.getItemMeta();
        nextMeta.setDisplayName("§aPróxima Página");
        nextPage.setItemMeta(nextMeta);
        inventoryView.setItem(53, nextPage);
    }

    public void nextPage() {
        if (currentPage < getTotalPages() - 1) {
            currentPage++;
            open();
        }
    }

    public void previousPage() {
        if (currentPage > 0) {
            currentPage--;
            open();
        }
    }

    public void addItem(ItemStack item) {
        for (ItemStack existingItem : internalContents) {
            if (existingItem.isSimilar(item)) {
                existingItem.setAmount(existingItem.getAmount() + item.getAmount());
                return;
            }
        }
        internalContents.add(item.clone()); // Adiciona um clone para evitar modificar o itemstack original
    }

    public void removeItem(ItemStack itemToRemove) {
        Iterator<ItemStack> iterator = internalContents.iterator();
        while (iterator.hasNext()) {
            ItemStack existingItem = iterator.next();
            if (existingItem.isSimilar(itemToRemove)) {
                if (existingItem.getAmount() <= itemToRemove.getAmount()) {
                    iterator.remove();
                } else {
                    existingItem.setAmount(existingItem.getAmount() - itemToRemove.getAmount());
                }
                return;
            }
        }
    }

    public String toBase64() {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream);
            dataOutput.writeInt(internalContents.size());
            for (ItemStack item : internalContents) {
                // Armazena a quantidade original
                int originalAmount = item.getAmount();
                // Define a quantidade como 1 para serialização para evitar IllegalStateException
                item.setAmount(1);
                dataOutput.writeObject(item);
                // Escreve a quantidade original separadamente
                dataOutput.writeInt(originalAmount);
                // Restaura a quantidade original (opcional, mas boa prática)
                item.setAmount(originalAmount);
            }
            dataOutput.close();
            return Base64Coder.encodeLines(outputStream.toByteArray());
        } catch (Exception e) {
            throw new IllegalStateException("Não foi possível salvar os itens da mochila.", e);
        }
    }

    public void fromBase64(String data) throws IOException {
        if (data == null || data.isEmpty()) {
            return;
        }
        try {
            ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data));
            BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream);
            int size = dataInput.readInt();
            for (int i = 0; i < size; i++) {
                ItemStack item = (ItemStack) dataInput.readObject();
                int trueAmount = dataInput.readInt();
                item.setAmount(trueAmount);
                internalContents.add(item);
            }
            dataInput.close();
        } catch (ClassNotFoundException e) {
            throw new IOException("Não foi possível decodificar o tipo da classe.", e);
        }
    }
}
