package com.tiedup.remake.items;

import com.tiedup.remake.core.SettingsAccessor;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityDamsel;
import com.tiedup.remake.entities.EntityKidnapper;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.util.TiedUpSounds;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;

/**
 * Whip - Tool for discipline
 * Right-click a tied entity to deal damage and decrease their resistance.
 *
 *
 * Effects:
 * - Deals damage (configurable)
 * - Decreases bind resistance (configurable)
 * - Plays whip crack sound
 * - Shows damage particles
 * - Consumes durability
 *
 * Opposite of paddle (which increases resistance).
 */
public class ItemWhip extends Item {

    public ItemWhip() {
        super(new Item.Properties().stacksTo(1).durability(256));
    }

    /**
     * Called when player right-clicks another entity with the whip.
     * Deals damage and decreases resistance if target is restrained.
     *
     * @param stack The item stack
     * @param player The player using the whip
     * @param target The entity being interacted with
     * @param hand The hand holding the whip
     * @return SUCCESS if whipping happened, PASS otherwise
     */
    @Override
    public InteractionResult interactLivingEntity(
        ItemStack stack,
        Player player,
        LivingEntity target,
        InteractionHand hand
    ) {
        // Only run on server side
        if (player.level().isClientSide) {
            return InteractionResult.SUCCESS;
        }

        // NPC whip - visual/sound feedback only (no personality effect)
        if (target instanceof EntityDamsel damsel) {
            // Set whip time for anti-flee system (stops fleeing for ~10 seconds)
            damsel.setLastWhipTime(player.level().getGameTime());

            // Visual feedback
            TiedUpSounds.playWhipSound(target);
            if (player.level() instanceof ServerLevel serverLevel) {
                serverLevel.sendParticles(
                    ParticleTypes.CRIT,
                    target.getX(),
                    target.getY() + target.getBbHeight() / 2.0,
                    target.getZ(),
                    10,
                    0.5,
                    0.5,
                    0.5,
                    0.1
                );
            }

            // Consume durability
            stack.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(hand));
            return InteractionResult.SUCCESS;
        }

        // Check if target can be restrained (Player, EntityDamsel, EntityKidnapper)
        IBondageState targetState = KidnappedHelper.getKidnappedState(target);
        if (targetState == null || !targetState.isTiedUp()) {
            return InteractionResult.PASS;
        }

        float damage = SettingsAccessor.getWhipDamage();
        int resistanceDecrease = SettingsAccessor.getWhipResistanceDecrease();

        // 1. Play whip sound
        TiedUpSounds.playWhipSound(target);

        // 2. Deal damage
        DamageSource damageSource = player.damageSources().playerAttack(player);
        target.hurt(damageSource, damage);

        // 3. Show damage particles (critical hit particles)
        if (player.level() instanceof ServerLevel serverLevel) {
            serverLevel.sendParticles(
                ParticleTypes.CRIT,
                target.getX(),
                target.getY() + target.getBbHeight() / 2.0,
                target.getZ(),
                10, // count
                0.5,
                0.5,
                0.5, // spread
                0.1 // speed
            );
        }

        // 4. Decrease resistance
        decreaseResistance(targetState, target, resistanceDecrease);

        // 5. Damage the whip (consume durability)
        stack.hurtAndBreak(1, player, p -> {
            p.broadcastBreakEvent(hand);
        });

        TiedUpMod.LOGGER.debug(
            "[ItemWhip] {} whipped {} (damage: {}, resistance -{})",
            player.getName().getString(),
            target.getName().getString(),
            damage,
            resistanceDecrease
        );

        return InteractionResult.SUCCESS;
    }

    /**
     * Decrease the target's bind resistance.
     * Works for both players (via PlayerBindState) and NPCs.
     *
     * @param targetState The target's IBondageState state
     * @param target The target entity
     * @param amount The amount to decrease
     */
    private void decreaseResistance(
        IBondageState targetState,
        LivingEntity target,
        int amount
    ) {
        if (target instanceof Player player) {
            // For players, use PlayerBindState
            PlayerBindState bindState = PlayerBindState.getInstance(player);
            int currentResistance = bindState.getCurrentBindResistance();
            int newResistance = Math.max(0, currentResistance - amount);
            bindState.setCurrentBindResistance(newResistance);

            // MEDIUM FIX: Sync resistance change to client
            // Resistance is stored in bind item NBT, so we must sync inventory
            // Without this, client still shows old resistance value in UI
            // Sync V2 equipment (resistance NBT changed on the stored ItemStack)
            if (
                player instanceof
                    net.minecraft.server.level.ServerPlayer serverPlayer
            ) {
                com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.sync(
                    serverPlayer
                );
            }

            TiedUpMod.LOGGER.debug(
                "[ItemWhip] Player resistance: {} -> {}",
                currentResistance,
                newResistance
            );
        } else {
            // For NPCs, resistance is not tracked the same way
            // Just log the whip action (NPC doesn't struggle, so resistance is less relevant)
            TiedUpMod.LOGGER.debug(
                "[ItemWhip] Whipped NPC (resistance not tracked for NPCs)"
            );
        }
    }
}
