package com.tiedup.remake.items.base;

import com.tiedup.remake.v2.bondage.component.AdjustableComponent;
import com.tiedup.remake.v2.bondage.component.ComponentType;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;

/**
 * Helper class for reading/writing adjustment values to ItemStack NBT.
 *
 * Adjustment values represent vertical offset in pixels (-4.0 to +4.0).
 * These are stored in the ItemStack's NBT and automatically synced to clients
 * via the equipment sync system (PacketSyncV2Equipment).
 */
public class AdjustmentHelper {

    /** NBT key for Y adjustment value */
    public static final String NBT_ADJUSTMENT_Y = "AdjustY";

    /** NBT key for scale adjustment value */
    public static final String NBT_ADJUSTMENT_SCALE = "AdjustScale";

    /** Default adjustment value (no offset) */
    public static final float DEFAULT_VALUE = 0.0f;

    /** Minimum allowed adjustment value */
    public static final float MIN_VALUE = -4.0f;

    /** Maximum allowed adjustment value */
    public static final float MAX_VALUE = 4.0f;

    /** Minimum allowed scale value */
    public static final float MIN_SCALE = 0.5f;

    /** Maximum allowed scale value */
    public static final float MAX_SCALE = 2.0f;

    /** Default scale value (no scaling) */
    public static final float DEFAULT_SCALE = 1.0f;

    /** Scale adjustment step */
    public static final float SCALE_STEP = 0.1f;

    /**
     * Get the Y adjustment value from an ItemStack.
     *
     * @param stack The ItemStack to read from
     * @return adjustment in pixels (-4.0 to +4.0), or default if not set
     */
    public static float getAdjustment(ItemStack stack) {
        if (stack.isEmpty()) {
            return DEFAULT_VALUE;
        }

        CompoundTag tag = stack.getTag();
        if (tag != null && tag.contains(NBT_ADJUSTMENT_Y)) {
            return tag.getFloat(NBT_ADJUSTMENT_Y);
        }

        // Fallback to item's default adjustment from V2 AdjustableComponent
        AdjustableComponent comp = DataDrivenBondageItem.getComponent(
            stack, ComponentType.ADJUSTABLE, AdjustableComponent.class
        );
        if (comp != null) {
            return comp.getDefaultValue();
        }

        return DEFAULT_VALUE;
    }

    /**
     * Set the Y adjustment value on an ItemStack.
     * Value is clamped to the valid range.
     *
     * @param stack The ItemStack to modify
     * @param value The adjustment value in pixels
     */
    public static void setAdjustment(ItemStack stack, float value) {
        if (stack.isEmpty()) {
            return;
        }

        float clamped = Mth.clamp(value, MIN_VALUE, MAX_VALUE);
        stack.getOrCreateTag().putFloat(NBT_ADJUSTMENT_Y, clamped);
    }

    /**
     * Check if an ItemStack has a custom adjustment set.
     *
     * @param stack The ItemStack to check
     * @return true if a custom adjustment is stored in NBT
     */
    public static boolean hasAdjustment(ItemStack stack) {
        if (stack.isEmpty()) {
            return false;
        }
        CompoundTag tag = stack.getTag();
        return tag != null && tag.contains(NBT_ADJUSTMENT_Y);
    }

    /**
     * Remove custom adjustment from an ItemStack, reverting to item default.
     *
     * @param stack The ItemStack to modify
     */
    public static void clearAdjustment(ItemStack stack) {
        if (stack.isEmpty()) {
            return;
        }
        CompoundTag tag = stack.getTag();
        if (tag != null) {
            tag.remove(NBT_ADJUSTMENT_Y);
        }
    }

    /**
     * Convert pixel adjustment to Minecraft units for PoseStack.translate().
     * 1 pixel = 1/16 block in Minecraft's coordinate system.
     *
     * Note: The result is negated because positive adjustment values should
     * move the item UP (negative Y in model space).
     *
     * @param pixels Adjustment value in pixels
     * @return Offset in Minecraft units for PoseStack.translate()
     */
    public static double toMinecraftUnits(float pixels) {
        return -pixels / 16.0;
    }

    /**
     * Check if an ItemStack's item supports adjustment.
     *
     * @param stack The ItemStack to check
     * @return true if the item has an AdjustableComponent
     */
    public static boolean isAdjustable(ItemStack stack) {
        if (stack.isEmpty()) {
            return false;
        }
        return DataDrivenBondageItem.getComponent(
            stack, ComponentType.ADJUSTABLE, AdjustableComponent.class
        ) != null;
    }

    /**
     * Get the scale adjustment value from an ItemStack.
     *
     * @param stack The ItemStack to read from
     * @return scale factor (0.5 to 2.0), or 1.0 if not set
     */
    public static float getScale(ItemStack stack) {
        if (stack.isEmpty()) {
            return DEFAULT_SCALE;
        }
        CompoundTag tag = stack.getTag();
        if (tag != null && tag.contains(NBT_ADJUSTMENT_SCALE)) {
            return tag.getFloat(NBT_ADJUSTMENT_SCALE);
        }
        return DEFAULT_SCALE;
    }

    /**
     * Set the scale adjustment value on an ItemStack.
     * Value is clamped to the valid range.
     *
     * @param stack The ItemStack to modify
     * @param value The scale value (0.5 to 2.0)
     */
    public static void setScale(ItemStack stack, float value) {
        if (stack.isEmpty()) {
            return;
        }
        float clamped = Mth.clamp(value, MIN_SCALE, MAX_SCALE);
        stack.getOrCreateTag().putFloat(NBT_ADJUSTMENT_SCALE, clamped);
    }
}
