package com.tiedup.remake.util;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.state.PlayerBindState;
import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import org.jetbrains.annotations.Nullable;

/**
 * Kidnap Explosion - Applies bondage to entities in an area.
 *
 *
 * Used by EntityKidnapBomb when it explodes.
 * Applies stored bondage items to all kidnappable entities in radius.
 *
 * Based on original KidnapExplosion from 1.12.2
 */
public class KidnapExplosion {

    private final Level level;
    private final BlockPos pos;
    private final int radius;
    private final ItemStack bind;
    private final ItemStack gag;
    private final ItemStack blindfold;
    private final ItemStack earplugs;
    private final ItemStack collar;
    private final ItemStack clothes;

    public KidnapExplosion(
        Level level,
        BlockPos pos,
        int radius,
        ItemStack bind,
        ItemStack gag,
        ItemStack blindfold,
        ItemStack earplugs,
        ItemStack collar,
        ItemStack clothes
    ) {
        this.level = level;
        this.pos = pos;
        this.radius = radius;
        this.bind = bind;
        this.gag = gag;
        this.blindfold = blindfold;
        this.earplugs = earplugs;
        this.collar = collar;
        this.clothes = clothes;
    }

    /**
     * Execute the explosion effect.
     */
    public void explode() {
        explode(null);
    }

    /**
     * Execute the explosion effect, optionally excluding a player.
     *
     * @param toExclude Player to exclude from effect (usually the one who placed the bomb)
     */
    public void explode(@Nullable Player toExclude) {
        if (level == null || level.isClientSide || pos == null) {
            return;
        }

        // Play explosion sound
        level.playSound(
            null,
            pos,
            SoundEvents.GENERIC_EXPLODE,
            SoundSource.BLOCKS,
            4.0f,
            (1.0f +
                    (level.random.nextFloat() - level.random.nextFloat()) *
                    0.2f) *
                0.7f
        );

        // Spawn explosion particle
        if (level instanceof ServerLevel serverLevel) {
            serverLevel.sendParticles(
                ParticleTypes.EXPLOSION,
                pos.getX() + 0.5,
                pos.getY() + 0.5,
                pos.getZ() + 0.5,
                1,
                0,
                0,
                0,
                0
            );
        }

        // Find all kidnappable entities in radius
        AABB area = new AABB(pos).inflate(radius);
        List<LivingEntity> entities = level.getEntitiesOfClass(
            LivingEntity.class,
            area
        );

        int affected = 0;
        for (LivingEntity entity : entities) {
            // Skip excluded player
            if (toExclude != null && entity.equals(toExclude)) {
                continue;
            }

            // Skip spectators
            if (entity instanceof Player player && player.isSpectator()) {
                continue;
            }

            // Get kidnapped state
            IBondageState kidnappedState = KidnappedHelper.getKidnappedState(
                entity
            );
            if (kidnappedState == null) {
                continue;
            }

            // Skip already tied entities
            if (kidnappedState.isTiedUp()) {
                continue;
            }

            // Apply bondage
            kidnappedState.applyBondage(
                bind,
                gag,
                blindfold,
                earplugs,
                collar,
                clothes
            );
            affected++;
        }

        TiedUpMod.LOGGER.info(
            "[KidnapExplosion] Explosion at {} affected {} entities (radius: {})",
            pos,
            affected,
            radius
        );
    }
}
