package com.tiedup.remake.util.tasks;

import javax.annotation.Nullable;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.ForgeRegistries;

/**
 * Represents an item task (for jobs and sales).
 *
 *
 * An ItemTask defines:
 * - What item is needed (by registry name)
 * - How many are needed
 *
 * Used by:
 * - Sale system: Price to buy a slave
 * - Job system: Items slave must fetch
 *
 * Based on original ItemTask from 1.12.2
 */
public class ItemTask {

    /** The item registry name (e.g., "minecraft:iron_ingot") */
    private final String itemId;

    /** The amount required */
    private final int amount;

    /** Cached item reference */
    @Nullable
    private transient Item cachedItem;

    /**
     * Create a new item task.
     *
     * @param itemId The item registry name
     * @param amount The amount required
     */
    public ItemTask(String itemId, int amount) {
        this.itemId = itemId;
        this.amount = Math.max(1, amount);
        this.cachedItem = null;
    }

    /**
     * Create a new item task from an Item.
     *
     * @param item The item
     * @param amount The amount required
     */
    public ItemTask(Item item, int amount) {
        ResourceLocation key = ForgeRegistries.ITEMS.getKey(item);
        this.itemId = key != null ? key.toString() : "minecraft:air";
        this.amount = Math.max(1, amount);
        this.cachedItem = item;
    }

    /**
     * Create a new item task from an ItemStack.
     *
     * @param stack The item stack (amount is used)
     */
    public ItemTask(ItemStack stack) {
        this(stack.getItem(), stack.getCount());
    }

    // GETTERS

    public String getItemId() {
        return itemId;
    }

    public int getAmount() {
        return amount;
    }

    /**
     * Get the Item instance.
     *
     * @return The Item or null if not found
     */
    @Nullable
    public Item getItem() {
        if (this.cachedItem == null) {
            ResourceLocation loc = ResourceLocation.tryParse(this.itemId);
            if (loc != null) {
                this.cachedItem = ForgeRegistries.ITEMS.getValue(loc);
            }
        }
        return this.cachedItem;
    }

    /**
     * Create an ItemStack of the required amount.
     *
     * @return ItemStack or empty if item not found
     */
    public ItemStack createStack() {
        Item item = getItem();
        if (item == null) {
            return ItemStack.EMPTY;
        }
        return new ItemStack(item, this.amount);
    }

    /**
     * Get display name for the item.
     *
     * @return Display name or item ID if not found
     */
    public String getDisplayName() {
        Item item = getItem();
        if (item == null) {
            return this.itemId;
        }
        return new ItemStack(item).getHoverName().getString();
    }

    // VALIDATION

    /**
     * Check if an ItemStack matches this task (same item type).
     *
     * @param stack The stack to check
     * @return true if same item type
     */
    public boolean matchesItem(ItemStack stack) {
        if (stack.isEmpty()) return false;

        Item item = getItem();
        if (item == null) return false;

        return stack.getItem() == item;
    }

    /**
     * Check if an ItemStack completes this task (same item, enough amount).
     *
     * @param stack The stack to check
     * @return true if completes the task
     */
    public boolean isCompletedBy(ItemStack stack) {
        return matchesItem(stack) && stack.getCount() >= this.amount;
    }

    /**
     * Consume the required items from a stack.
     *
     * @param stack The stack to consume from
     * @return true if consumed successfully
     */
    public boolean consumeFrom(ItemStack stack) {
        if (!isCompletedBy(stack)) {
            return false;
        }
        stack.shrink(this.amount);
        return true;
    }

    // NBT SERIALIZATION

    /**
     * Save this task to NBT.
     *
     * @return CompoundTag with task data
     */
    public CompoundTag save() {
        CompoundTag tag = new CompoundTag();
        tag.putString("item", this.itemId);
        tag.putInt("amount", this.amount);
        return tag;
    }

    /**
     * Load a task from NBT.
     *
     * @param tag The CompoundTag to load from
     * @return ItemTask or null if invalid
     */
    @Nullable
    public static ItemTask load(CompoundTag tag) {
        if (tag == null || !tag.contains("item")) {
            return null;
        }

        String itemId = tag.getString("item");
        int amount = tag.contains("amount") ? tag.getInt("amount") : 1;

        return new ItemTask(itemId, amount);
    }

    // DISPLAY

    /**
     * Get a display string for this task.
     *
     * @return String like "20x Iron Ingot"
     */
    public String toDisplayString() {
        return this.amount + "x " + getDisplayName();
    }

    @Override
    public String toString() {
        return "ItemTask{" + this.amount + "x " + this.itemId + "}";
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof ItemTask other)) return false;
        return this.amount == other.amount && this.itemId.equals(other.itemId);
    }

    @Override
    public int hashCode() {
        return 31 * this.itemId.hashCode() + this.amount;
    }
}
