package me.trouper.sentinel.data.storage;

import io.github.itzispyder.pdk.plugin.builders.ItemBuilder;
import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable;
import me.trouper.sentinel.Sentinel;
import me.trouper.sentinel.utils.Text;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class NBTStorage implements JsonSerializable<NBTStorage> {

    // Mapping from file name to owner UUID (as a String)
    public Map<String, String> caughtItems = new HashMap<>();
    
    /**
     * Stores an ItemStack's serialized NBT to a unique file
     * and maps the generated file name to the owner UUID.
     *
     * @param item  the ItemStack to store
     * @param owner the owner's UUID
     */
    public void storeItem(ItemStack item, UUID owner) {
        // Generate a unique file name with a .nbt extension
        File storageDir = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "storage/nbt");
        String fileName = UUID.randomUUID().toString() + ".nbt";
        File file = new File(storageDir, fileName);
        try (FileOutputStream fos = new FileOutputStream(file);
             OutputStreamWriter writer = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {

            String nbt = serializeItem(item);
            writer.write(nbt);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Add mapping: file name -> owner UUID (as string)
        caughtItems.put(fileName, owner.toString());
        save();
    }
    
    public boolean deleteItem(String fileName) {
        File storageDir = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "storage/nbt");
        File file = new File(storageDir, fileName);
        caughtItems.remove(fileName);
        save();
        return file.delete();
    }

    public static ItemStack getItem(String fileName) {
        File storageDir = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "storage/nbt");
        File file = new File(storageDir, fileName);
        try (FileInputStream fis = new FileInputStream(file)) {
            StringBuilder b64 = new StringBuilder();
            int content;
            while ((content = fis.read()) != -1) {
                b64.append((char) content);
            }
            //ServerUtils.verbose("Getting item with fis: " + b64);
            return deserializeItem(b64.toString());
        } catch (FileNotFoundException e) {
            Sentinel.getInstance().getDirector().io.nbtStorage.caughtItems.remove(fileName);
            Sentinel.getInstance().getDirector().io.nbtStorage.save();
            return new ItemBuilder().material(Material.STRUCTURE_VOID)
                    .name(Text.color("&cFile not found."))
                    .lore(Text.color("&7This item no longer exists and has been removed from the list."))
                    .build();
        } catch (IOException e) {
            e.printStackTrace();
            return new ItemBuilder().material(Material.STRUCTURE_VOID)
                    .name(Text.color("&cUnknown IO exception."))
                    .lore(Text.color("&4Check Console."))
                    .build();
        }
    }
    
    public static String serializeItem(ItemStack item) {
        if (item == null) {
            return null;
        }
        try {
            // Serialize ItemStack to a Map
            Map<String, Object> serializedItem = item.serialize();

            // Save the Map into a YAML configuration
            YamlConfiguration config = new YamlConfiguration();
            config.set("item", serializedItem);
            String yamlString = config.saveToString();

            // Encode YAML string to Base64
            return Base64.getEncoder().encodeToString(yamlString.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static ItemStack deserializeItem(String data) {
        if (data == null || data.isEmpty()) {
            return null;
        }
        try {
            // Decode Base64 to YAML string
            byte[] decodedData = Base64.getDecoder().decode(data);
            String yamlString = new String(decodedData, StandardCharsets.UTF_8);

            // Load YAML configuration from string
            YamlConfiguration config = new YamlConfiguration();
            config.loadFromString(yamlString);

            // Extract the serialized Map from the configuration
            ConfigurationSection itemSection = config.getConfigurationSection("item");
            if (itemSection == null) {
                return null; // Invalid data
            }

            // Convert ConfigurationSection to a nested Map
            Map<String, Object> serializedItem = itemSection.getValues(true);

            // Deserialize the Map back into an ItemStack
            return ItemStack.deserialize(serializedItem);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public File getFile() {
        File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "storage/nbt.json");
        new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "storage/nbt").mkdirs();
        file.getParentFile().mkdirs();
        return file;
    }
}