package com.tiedup.remake.state.struggle;

import com.tiedup.remake.core.SettingsAccessor;
import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.core.SystemMessageManager.MessageCategory;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.util.ItemNBTHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;

/**
 *
 * Accessories have NO base resistance - only locked items can be struggled.
 * Lock adds 250 resistance. Struggle success destroys the padlock (lockable=false).
 *
 * Unlike binds, accessories are NOT automatically removed on struggle success.
 * The item remains equipped but unlocked, allowing manual removal.
 */
public class StruggleAccessory extends StruggleState {

    /** The V2 body region of the accessory being struggled against. */
    private final BodyRegionV2 accessoryRegion;

    public StruggleAccessory(BodyRegionV2 accessoryRegion) {
        if (accessoryRegion == BodyRegionV2.ARMS) {
            throw new IllegalArgumentException(
                "Use StruggleBinds for ARMS region, not StruggleAccessory"
            );
        }
        this.accessoryRegion = accessoryRegion;
    }

    /** NBT key for accessory struggle progress (replaces removed ILockable lock resistance). */
    private static final String NBT_ACCESSORY_STRUGGLE = "accessoryStruggleResistance";

    /**
     * Get the current resistance for this accessory.
     * Accessories have 0 base resistance -- when locked, resistance comes from
     * {@link SettingsAccessor#getPadlockResistance}. Stored in a dedicated NBT
     * key on the accessory stack to persist between attempts.
     *
     * @param state The player's bind state
     * @return Current resistance value (0 if not locked)
     */
    @Override
    protected int getResistanceState(PlayerBindState state) {
        ItemStack stack = getAccessoryStack(state);
        if (stack.isEmpty()) return 0;

        if (stack.getItem() instanceof ILockable lockable && lockable.isLocked(stack)) {
            // If no struggle progress stored yet, initialize from config
            if (!ItemNBTHelper.contains(stack, NBT_ACCESSORY_STRUGGLE)) {
                return SettingsAccessor.getPadlockResistance(null);
            }
            return ItemNBTHelper.getInt(stack, NBT_ACCESSORY_STRUGGLE);
        }
        return 0;
    }

    /**
     * Set the current resistance for this accessory struggle.
     * Stored in a dedicated NBT key on the accessory stack.
     *
     * @param state The player's bind state
     * @param resistance The new resistance value
     */
    @Override
    protected void setResistanceState(PlayerBindState state, int resistance) {
        ItemStack stack = getAccessoryStack(state);
        if (stack.isEmpty()) return;

        ItemNBTHelper.setInt(stack, NBT_ACCESSORY_STRUGGLE, resistance);
    }

    /**
     * Check if the player can struggle against this accessory.
     * Only locked accessories can be struggled against.
     *
     * @param state The player's bind state
     * @return True if the accessory is equipped and locked
     */
    @Override
    protected boolean canStruggle(PlayerBindState state) {
        Player player = state.getPlayer();
        if (player == null) {
            return false;
        }

        ItemStack stack = getAccessoryStack(state);
        if (stack.isEmpty()) {
            return false;
        }

        // Only require struggle if LOCKED or has BUILT_IN_LOCK.
        // Unlocked accessories without built-in lock can be freely removed (no struggle needed).
        boolean isLocked = stack.getItem() instanceof ILockable lockable && lockable.isLocked(stack);
        boolean hasBuiltInLock = DataDrivenBondageItem.hasBuiltInLock(stack);
        if (!isLocked && !hasBuiltInLock) {
            return false;
        }

        return true;
    }

    /**
     * Called when the player successfully struggles against the accessory.
     * Unlocks the item and DESTROYS the padlock (lockable=false).
     * The item remains equipped but can now be removed manually.
     *
     * @param state The player's bind state
     */
    @Override
    protected void successAction(PlayerBindState state) {
        Player player = state.getPlayer();
        if (player == null) return;

        ItemStack stack = getAccessoryStack(state);
        if (stack.isEmpty()) return;

        // Destroy the padlock (unlock + lockable=false)
        if (stack.getItem() instanceof ILockable lockable) {
            lockable.breakLock(stack);
            TiedUpMod.LOGGER.info(
                "[STRUGGLE] {} destroyed padlock on {} (region: {})",
                player.getName().getString(),
                stack.getDisplayName().getString(),
                accessoryRegion
            );
        }
    }

    @Override
    protected MessageCategory getSuccessCategory() {
        return MessageCategory.STRUGGLE_SUCCESS; // Used for color (green)
    }

    @Override
    protected MessageCategory getFailCategory() {
        return MessageCategory.STRUGGLE_FAIL; // Used for color (gray)
    }

    /**
     * Override to send custom success message per accessory type.
     */
    @Override
    protected void notifySuccess(Player player, int newResistance) {
        String message = switch (accessoryRegion) {
            case MOUTH -> "You manage to loosen the gag's lock...";
            case EYES -> "The blindfold's lock gives way...";
            case EARS -> "You feel the earplug lock breaking...";
            case NECK -> "The collar's lock snaps open...";
            case TORSO -> "The clothing lock breaks...";
            case HANDS -> "The mitten lock comes undone...";
            default -> "The lock breaks!";
        };
        SystemMessageManager.sendToPlayer(
            player,
            getSuccessCategory(),
            message + " (Resistance: " + newResistance + ")"
        );
    }

    /**
     * Override to send custom failure message per accessory type.
     */
    @Override
    protected void notifyFailure(Player player) {
        String message = switch (accessoryRegion) {
            case MOUTH -> "You struggle against the gag, but the lock holds.";
            case EYES -> "The blindfold's lock refuses to budge.";
            case EARS -> "The earplug lock stays firmly shut.";
            case NECK -> "The collar's lock resists your efforts.";
            case TORSO -> "The clothing lock holds tight.";
            case HANDS -> "The mitten lock won't give in.";
            default -> "The lock holds firm.";
        };
        SystemMessageManager.sendToPlayer(player, getFailCategory(), message);
    }

    /**
     */
    @Override
    protected boolean onAttempt(PlayerBindState state) {
        Player player = state.getPlayer();
        ItemStack collar = V2EquipmentHelper.getInRegion(
            player,
            BodyRegionV2.NECK
        );

        if (
            !collar.isEmpty() &&
            com.tiedup.remake.v2.bondage.CollarHelper.canShock(collar)
        ) {
            // V2 shock collar — notify via IHasResistance
            if (collar.getItem() instanceof com.tiedup.remake.items.base.IHasResistance resistance) {
                resistance.notifyStruggle(player);
            }
            return true;
        }
        return true; // No collar, proceed normally
    }

    /**
     * Get the accessory ItemStack from the player.
     */
    private ItemStack getAccessoryStack(PlayerBindState state) {
        Player player = state.getPlayer();
        if (player == null) return ItemStack.EMPTY;
        return V2EquipmentHelper.getInRegion(player, accessoryRegion);
    }

    /**
     * Get the V2 body region of the accessory this struggle targets.
     */
    public BodyRegionV2 getAccessoryRegion() {
        return accessoryRegion;
    }
}
