package de.simolzimol.mclogger.paper.listeners;

import de.simolzimol.mclogger.paper.PaperLoggerPlugin;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.inventory.*;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.HashMap;
import java.util.Map;

/**
 * Logs inventory events: item pickup, item drop,
 * crafting, enchanting, trading, etc.
 *
 * @author SimolZimol
 */
public class InventoryListener implements Listener {

    private final PaperLoggerPlugin plugin;

    public InventoryListener(PaperLoggerPlugin plugin) {
        this.plugin = plugin;
    }

    // -------------------------------------------------------
    // Item Pickup
    // -------------------------------------------------------
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onPickup(EntityPickupItemEvent event) {
        if (!(event.getEntity() instanceof Player p)) return;
        ItemStack item = event.getItem().getItemStack();

        plugin.getDb().insertInventoryEvent(
                "pickup",
                p.getUniqueId().toString(), p.getName(),
                p.getWorld().getName(),
                p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ(),
                item.getType().name(), item.getAmount(),
                buildItemMeta(item), -1,
                "player"
        );
    }

    // -------------------------------------------------------
    // Item Drop
    // -------------------------------------------------------
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onDrop(PlayerDropItemEvent event) {
        Player p = event.getPlayer();
        ItemStack item = event.getItemDrop().getItemStack();

        plugin.getDb().insertInventoryEvent(
                "drop",
                p.getUniqueId().toString(), p.getName(),
                p.getWorld().getName(),
                p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ(),
                item.getType().name(), item.getAmount(),
                buildItemMeta(item), -1,
                "player"
        );
    }

    // -------------------------------------------------------
    // Inventory Clicks (player inventories only)
    // -------------------------------------------------------
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onInventoryClick(InventoryClickEvent event) {
        if (!(event.getWhoClicked() instanceof Player p)) return;
        if (event.getCurrentItem() == null) return;
        // Only crafting, enchanting, anvil -> trade, etc.
        InventoryType type = event.getInventory().getType();
        if (type == InventoryType.PLAYER || type == InventoryType.CREATIVE) return; // too much noise

        ItemStack item = event.getCurrentItem();
        String invTypeName = type.name();
        String logType = switch (type) {
            case CRAFTING, WORKBENCH -> "craft";
            case ENCHANTING -> "enchant";
            case ANVIL -> "anvil";
            case MERCHANT -> "trade";
            default -> "click";
        };

        plugin.getDb().insertInventoryEvent(
                logType,
                p.getUniqueId().toString(), p.getName(),
                p.getWorld().getName(),
                p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ(),
                item.getType().name(), item.getAmount(),
                buildItemMeta(item),
                event.getSlot(),
                invTypeName
        );
    }

    // -------------------------------------------------------
    // Helper method: item meta as Map
    // -------------------------------------------------------
    private Map<String, Object> buildItemMeta(ItemStack item) {
        if (!item.hasItemMeta()) return null;
        ItemMeta meta = item.getItemMeta();
        Map<String, Object> m = new HashMap<>();
        if (meta.hasDisplayName() && meta.displayName() != null) {
            m.put("name", PlainTextComponentSerializer.plainText().serialize(meta.displayName()));
        }
        if (meta.hasEnchants()) {
            Map<String, Integer> enc = new HashMap<>();
            meta.getEnchants().forEach((e, lvl) -> enc.put(e.getKey().getKey(), lvl));
            m.put("enchants", enc);
        }
        if (meta.hasLore() && meta.lore() != null) {
            m.put("lore_lines", meta.lore().size());
        }
        if (meta.isUnbreakable()) m.put("unbreakable", true);
        return m.isEmpty() ? null : m;
    }
}
