package com.tiedup.remake.util;

import com.tiedup.remake.blocks.entity.IBondageItemHolder;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.BindModeHelper;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.bondage.component.ComponentType;
import com.tiedup.remake.v2.bondage.component.GaggingComponent;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry;
import java.util.List;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;

/**
 * Utility class for loading bondage items into block entity holders.
 *
 * <p>This centralizes the logic for:
 * <ul>
 *   <li>Loading items into IBondageItemHolder (traps, bombs, chests)</li>
 *   <li>Checking if an item is a loadable bondage item</li>
 *   <li>Adding item tooltips from NBT data</li>
 * </ul>
 *
 * <p>Used by BlockKidnapBomb, BlockRopeTrap, and BlockTrappedChest.
 */
public final class BondageItemLoaderUtility {

    private BondageItemLoaderUtility() {}

    /**
     * Load a bondage item into the holder.
     *
     * <p>Checks the item type and loads it into the appropriate slot
     * if that slot is empty. Consumes one item from the stack (unless creative).
     *
     * @param holder The bondage item holder (block entity)
     * @param stack The item stack to load
     * @param player The player loading the item
     * @return true if item was loaded, false if slot was occupied or wrong item type
     */
    public static boolean loadItemIntoHolder(
        IBondageItemHolder holder,
        ItemStack stack,
        Player player
    ) {
        if (BindModeHelper.isBindItem(stack) && holder.getBind().isEmpty()) {
            holder.setBind(stack.copyWithCount(1));
            if (!player.isCreative()) stack.shrink(1);
            return true;
        }
        if (DataDrivenBondageItem.getComponent(stack, ComponentType.GAGGING, GaggingComponent.class) != null
                && holder.getGag().isEmpty()) {
            holder.setGag(stack.copyWithCount(1));
            if (!player.isCreative()) stack.shrink(1);
            return true;
        }
        if (isDataDrivenForRegion(stack, BodyRegionV2.EYES)
                && holder.getBlindfold().isEmpty()) {
            holder.setBlindfold(stack.copyWithCount(1));
            if (!player.isCreative()) stack.shrink(1);
            return true;
        }
        if (isDataDrivenForRegion(stack, BodyRegionV2.EARS)
                && holder.getEarplugs().isEmpty()) {
            holder.setEarplugs(stack.copyWithCount(1));
            if (!player.isCreative()) stack.shrink(1);
            return true;
        }
        if (CollarHelper.isCollar(stack)
                && holder.getCollar().isEmpty()) {
            holder.setCollar(stack.copyWithCount(1));
            if (!player.isCreative()) stack.shrink(1);
            return true;
        }
        return false;
    }

    /**
     * Check if an item is a loadable bondage item.
     *
     * <p>Returns true for: Bind, Gag, Blindfold, Earplugs, Collar.
     *
     * @param stack The item stack to check
     * @return true if the item can be loaded into a bondage item holder
     */
    public static boolean isLoadableBondageItem(ItemStack stack) {
        if (stack.isEmpty()) return false;
        // V2 data-driven items: bind, gag, blindfold, earplugs, collar
        if (BindModeHelper.isBindItem(stack)) return true;
        if (DataDrivenBondageItem.getComponent(stack, ComponentType.GAGGING, GaggingComponent.class) != null) return true;
        if (isDataDrivenForRegion(stack, BodyRegionV2.EYES)) return true;
        if (isDataDrivenForRegion(stack, BodyRegionV2.EARS)) return true;
        if (CollarHelper.isCollar(stack)) return true;
        return false;
    }

    /** Check if a stack is a data-driven item occupying the given body region. */
    private static boolean isDataDrivenForRegion(ItemStack stack, BodyRegionV2 region) {
        DataDrivenItemDefinition def = DataDrivenItemRegistry.get(stack);
        return def != null && def.occupiedRegions().contains(region);
    }

    /**
     * Add item to tooltip if present in NBT.
     *
     * <p>Reads an item from the given NBT key and adds it to the tooltip
     * with a "- ItemName" format in gold color.
     *
     * @param tooltip The tooltip list to add to
     * @param beTag The BlockEntity NBT tag
     * @param key The NBT key to read (e.g., "bind", "gag")
     */
    public static void addItemToTooltip(
        List<Component> tooltip,
        CompoundTag beTag,
        String key
    ) {
        if (beTag.contains(key)) {
            ItemStack item = ItemStack.of(beTag.getCompound(key));
            if (!item.isEmpty()) {
                tooltip.add(
                    Component.literal("- ")
                        .append(item.getHoverName())
                        .withStyle(ChatFormatting.GOLD)
                );
            }
        }
    }
}
