package com.tiedup.remake.state.struggle;

import com.tiedup.remake.core.SystemMessageManager.MessageCategory;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.base.IHasResistance;
import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
import com.tiedup.remake.v2.bondage.component.ComponentType;
import com.tiedup.remake.v2.bondage.component.ResistanceComponent;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;

/**
 *
 * Struggle mechanics specifically for locked collars.
 *
 * How it Works:
 * - Only locked collars can be struggled against
 * - Success: Collar becomes UNLOCKED (not removed)
 * - No items are dropped (unlike bind struggle)
 * - Uses collar-specific GameRules for probability and resistance
 *
 * Differences from StruggleBinds:
 * - Condition: hasLockedCollar() instead of isTiedUp()
 * - Success: unlock collar instead of untie + drop items
 * - Resistance source: collar NBT instead of bind NBT
 * - GameRules: STRUGGLE_COLLAR, PROBABILITY_STRUGGLE_COLLAR, etc.
 *
 * Usage:
 * - Slave wears locked collar
 * - Presses R (struggle key)
 * - Eventually unlocks collar (can then remove it)
 *
 * @see StruggleBinds
 * @see StruggleState
 */
public class StruggleCollar extends StruggleState {

    /**
     * Get the current resistance from the equipped collar.
     *
     * @param state The PlayerBindState
     * @return Current collar resistance, or 0 if no collar
     */
    @Override
    protected int getResistanceState(PlayerBindState state) {
        Player player = state.getPlayer();
        if (player == null) return 0;
        ItemStack collar = V2EquipmentHelper.getInRegion(player, BodyRegionV2.NECK);

        if (collar.isEmpty() || !CollarHelper.isCollar(collar)) return 0;

        if (collar.getItem() instanceof IHasResistance resistance) {
            return resistance.getCurrentResistance(collar, player);
        }
        return 0;
    }

    /**
     * Set the current resistance on the equipped collar.
     *
     * @param state The PlayerBindState
     * @param resistance The new resistance value
     */
    @Override
    protected void setResistanceState(PlayerBindState state, int resistance) {
        Player player = state.getPlayer();
        if (player == null) return;
        ItemStack collar = V2EquipmentHelper.getInRegion(player, BodyRegionV2.NECK);

        if (collar.isEmpty() || !CollarHelper.isCollar(collar)) return;

        if (collar.getItem() instanceof IHasResistance resistanceItem) {
            resistanceItem.setCurrentResistance(collar, resistance);
        }
    }

    /**
     * Check if the collar can be struggled against.
     *
     * Conditions:
     * - Must have collar equipped
     * - Collar must be LOCKED
     * - Collar must allow struggle (canBeStruggledOut)
     *
     * Note: Can struggle collar even if NOT tied up.
     *
     * @param state The PlayerBindState
     * @return true if can struggle collar
     */
    @Override
    protected boolean canStruggle(PlayerBindState state) {
        Player player = state.getPlayer();

        if (state.isTiedUp()) {
            return false;
        }

        ItemStack collar = V2EquipmentHelper.getInRegion(player, BodyRegionV2.NECK);

        if (collar.isEmpty() || !CollarHelper.isCollar(collar)) {
            TiedUpMod.LOGGER.debug("[StruggleCollar] No collar equipped");
            return false;
        }

        // Only require struggle if LOCKED or has BUILT_IN_LOCK.
        // Unlocked collars without built-in lock can be freely removed (no struggle needed).
        boolean isLocked = collar.getItem() instanceof ILockable lockable && lockable.isLocked(collar);
        boolean hasBuiltInLock = DataDrivenBondageItem.hasBuiltInLock(collar);
        if (!isLocked && !hasBuiltInLock) {
            TiedUpMod.LOGGER.debug("[StruggleCollar] Collar is not locked and has no built-in lock — no struggle needed");
            return false;
        }

        // Check if struggle is enabled (works for V1 and V2 via IHasResistance)
        if (collar.getItem() instanceof IHasResistance resistance) {
            if (!resistance.canBeStruggledOut(collar)) {
                TiedUpMod.LOGGER.debug("[StruggleCollar] Collar struggle is disabled");
                return false;
            }
        }

        return true;
    }

    /**
     * Action to perform when struggle is attempted.
     * Used for random shock chance on shock collars.
     */
    @Override
    protected boolean onAttempt(PlayerBindState state) {
        Player player = state.getPlayer();
        ItemStack collar = V2EquipmentHelper.getInRegion(player, BodyRegionV2.NECK);

        if (!collar.isEmpty() && CollarHelper.canShock(collar)) {
            // V2 shock collar — notify via IHasResistance
            if (collar.getItem() instanceof IHasResistance resistance) {
                resistance.notifyStruggle(player);
            }
        }
        return true;
    }

    /**
     * Action to perform when struggle succeeds (resistance = 0).
     *
     * For collars: Unlock the collar.
     * The player can then manually remove it.
     *
     * @param state The PlayerBindState
     */
    @Override
    protected void successAction(PlayerBindState state) {
        Player player = state.getPlayer();
        ItemStack collar = V2EquipmentHelper.getInRegion(player, BodyRegionV2.NECK);

        if (collar.isEmpty() || !CollarHelper.isCollar(collar)) {
            TiedUpMod.LOGGER.warn("[StruggleCollar] successAction called but no collar equipped");
            return;
        }

        // Unlock the collar (works for V1 and V2 via ILockable)
        if (collar.getItem() instanceof ILockable lockable) {
            lockable.setLocked(collar, false);
        }

        TiedUpMod.LOGGER.info("[StruggleCollar] {} unlocked their collar!", player.getName().getString());
    }

    @Override
    protected MessageCategory getSuccessCategory() {
        return MessageCategory.STRUGGLE_COLLAR_SUCCESS;
    }

    @Override
    protected MessageCategory getFailCategory() {
        return MessageCategory.STRUGGLE_COLLAR_FAIL;
    }

    /**
     * Tighten the collar (restore resistance to base value).
     * Called when a master tightens the slave's collar.
     *
     * Conditions:
     * - Collar must be locked
     * - Tightener must be different from wearer
     *
     * @param tightener The player tightening the collar
     * @param state The PlayerBindState of the collar wearer
     */
    public void tighten(Player tightener, PlayerBindState state) {
        Player target = state.getPlayer();

        if (tightener == null || target == null) {
            return;
        }

        // Can't tighten your own collar
        if (tightener.getUUID().equals(target.getUUID())) {
            TiedUpMod.LOGGER.debug(
                "[StruggleCollar] Cannot tighten own collar"
            );
            return;
        }

        ItemStack collar = V2EquipmentHelper.getInRegion(target, BodyRegionV2.NECK);

        if (collar.isEmpty() || !CollarHelper.isCollar(collar)) {
            TiedUpMod.LOGGER.debug("[StruggleCollar] No collar to tighten");
            return;
        }

        // Check if collar is locked (V1 and V2 via ILockable)
        if (collar.getItem() instanceof ILockable lockable) {
            if (!lockable.isLocked(collar)) {
                TiedUpMod.LOGGER.debug("[StruggleCollar] Collar must be locked to tighten");
                return;
            }
        } else {
            return;
        }

        // Get resistance — V2: read ResistanceComponent directly (avoids MAX-scan bug),
        // V1: use IHasResistance.getBaseResistance()
        if (!(collar.getItem() instanceof IHasResistance resistanceItem)) return;
        int baseResistance;
        ResistanceComponent comp = DataDrivenBondageItem.getComponent(
            collar, ComponentType.RESISTANCE, ResistanceComponent.class
        );
        if (comp != null) {
            baseResistance = comp.getBaseResistance();
        } else {
            baseResistance = resistanceItem.getBaseResistance(target);
        }
        int currentResistance = resistanceItem.getCurrentResistance(collar, target);

        // Only tighten if current resistance is lower than base
        if (currentResistance >= baseResistance) {
            TiedUpMod.LOGGER.debug(
                "[StruggleCollar] Collar already at max resistance"
            );
            return;
        }

        // Restore to base resistance
        resistanceItem.setCurrentResistance(collar, baseResistance);

        TiedUpMod.LOGGER.info(
            "[StruggleCollar] {} tightened {}'s collar (resistance {} -> {})",
            tightener.getName().getString(),
            target.getName().getString(),
            currentResistance,
            baseResistance
        );
    }
}
