package com.tiedup.remake.blocks;

import com.tiedup.remake.blocks.entity.TrapBlockEntity;
import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.BondageItemLoaderUtility;
import com.tiedup.remake.util.KidnappedHelper;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;

/**
 * Rope Trap Block - Trap that ties up entities when they walk on it.
 *
 *
 * Features:
 * - Flat block (1 pixel tall) placed on solid surfaces
 * - Can be loaded with bondage items by right-clicking
 * - When armed and entity walks on it, applies all stored items
 * - Destroys itself after triggering
 * - Preserves NBT data when broken
 *
 * Based on original BlockRopesTrap from 1.12.2
 */
public class BlockRopeTrap extends Block implements EntityBlock, ICanBeLoaded {

    // Shape: 1 pixel tall carpet-like block
    protected static final VoxelShape TRAP_SHAPE = Block.box(
        0.0,
        0.0,
        0.0,
        16.0,
        1.0,
        16.0
    );

    public BlockRopeTrap() {
        super(
            BlockBehaviour.Properties.of()
                .strength(1.0f, 0.5f)
                .sound(SoundType.WOOL)
                .noOcclusion()
                .noCollission() // Entities can walk through/on it
        );
    }

    // SHAPE AND RENDERING

    @Override
    public VoxelShape getShape(
        BlockState state,
        BlockGetter level,
        BlockPos pos,
        CollisionContext context
    ) {
        return TRAP_SHAPE;
    }

    @Override
    public VoxelShape getCollisionShape(
        BlockState state,
        BlockGetter level,
        BlockPos pos,
        CollisionContext context
    ) {
        return Shapes.empty(); // No collision - entities walk through
    }

    @Override
    public RenderShape getRenderShape(BlockState state) {
        return RenderShape.MODEL;
    }

    // PLACEMENT RULES

    @Override
    public boolean canSurvive(
        BlockState state,
        LevelReader level,
        BlockPos pos
    ) {
        BlockPos below = pos.below();
        BlockState belowState = level.getBlockState(below);
        // Can only be placed on full solid blocks
        return belowState.isFaceSturdy(level, below, Direction.UP);
    }

    @Nullable
    @Override
    public BlockState getStateForPlacement(BlockPlaceContext context) {
        if (
            !canSurvive(
                defaultBlockState(),
                context.getLevel(),
                context.getClickedPos()
            )
        ) {
            return null;
        }
        return defaultBlockState();
    }

    @Override
    public BlockState updateShape(
        BlockState state,
        Direction facing,
        BlockState facingState,
        LevelAccessor level,
        BlockPos pos,
        BlockPos facingPos
    ) {
        // Break if support block is removed
        if (facing == Direction.DOWN && !canSurvive(state, level, pos)) {
            return Blocks.AIR.defaultBlockState();
        }
        return super.updateShape(
            state,
            facing,
            facingState,
            level,
            pos,
            facingPos
        );
    }

    // BLOCK ENTITY

    @Nullable
    @Override
    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
        return new TrapBlockEntity(pos, state);
    }

    @Nullable
    public TrapBlockEntity getTrapEntity(BlockGetter level, BlockPos pos) {
        BlockEntity be = level.getBlockEntity(pos);
        return be instanceof TrapBlockEntity ? (TrapBlockEntity) be : null;
    }

    // TRAP TRIGGER

    @Override
    public void entityInside(
        BlockState state,
        Level level,
        BlockPos pos,
        Entity entity
    ) {
        if (level.isClientSide) return;

        // Only affect living entities
        if (!(entity instanceof LivingEntity living)) return;

        // Get target's kidnapped state
        IBondageState targetState = KidnappedHelper.getKidnappedState(living);
        if (targetState == null) return;

        // Don't trigger if already tied
        if (targetState.isTiedUp()) return;

        // Get trap data
        TrapBlockEntity trap = getTrapEntity(level, pos);
        if (trap == null || !trap.isArmed()) return;

        // Apply all bondage items
        ItemStack bind = trap.getBind();
        ItemStack gag = trap.getGag();
        ItemStack blindfold = trap.getBlindfold();
        ItemStack earplugs = trap.getEarplugs();
        ItemStack collar = trap.getCollar();
        ItemStack clothes = trap.getClothes();

        targetState.applyBondage(
            bind,
            gag,
            blindfold,
            earplugs,
            collar,
            clothes
        );

        // Destroy the trap
        level.destroyBlock(pos, false);

        // Notify target
        if (entity instanceof Player player) {
            player.displayClientMessage(
                Component.translatable("tiedup.trap.triggered").withStyle(
                    ChatFormatting.RED
                ),
                true
            );
        }

        TiedUpMod.LOGGER.info(
            "[BlockRopeTrap] Trap triggered at {} on {}",
            pos,
            entity.getName().getString()
        );
    }

    // LOADING ITEMS

    @Override
    public InteractionResult use(
        BlockState state,
        Level level,
        BlockPos pos,
        Player player,
        InteractionHand hand,
        BlockHitResult hit
    ) {
        if (hand != InteractionHand.MAIN_HAND) {
            return InteractionResult.PASS;
        }

        ItemStack heldItem = player.getItemInHand(hand);

        // Empty hand = do nothing
        if (heldItem.isEmpty()) {
            return InteractionResult.PASS;
        }

        // Check if it's a bondage item
        if (!BondageItemLoaderUtility.isLoadableBondageItem(heldItem)) {
            return InteractionResult.PASS;
        }

        // Server-side only
        if (level.isClientSide) {
            return InteractionResult.SUCCESS;
        }

        TrapBlockEntity trap = getTrapEntity(level, pos);
        if (trap == null) {
            return InteractionResult.PASS;
        }

        // Try to load the held item into the appropriate slot
        if (
            BondageItemLoaderUtility.loadItemIntoHolder(trap, heldItem, player)
        ) {
            SystemMessageManager.sendToPlayer(
                player,
                "Item loaded into trap",
                ChatFormatting.YELLOW
            );
            return InteractionResult.SUCCESS;
        }

        return InteractionResult.PASS;
    }

    // DROPS WITH NBT

    @Override
    public List<ItemStack> getDrops(
        BlockState state,
        LootParams.Builder params
    ) {
        BlockEntity be = params.getOptionalParameter(
            LootContextParams.BLOCK_ENTITY
        );
        ItemStack stack = new ItemStack(this);

        if (be instanceof TrapBlockEntity trap) {
            CompoundTag beTag = new CompoundTag();
            trap.writeBondageData(beTag);

            if (!beTag.isEmpty()) {
                stack.addTagElement("BlockEntityTag", beTag);
            }
        }

        return List.of(stack);
    }

    // TOOLTIP

    @Override
    public void appendHoverText(
        ItemStack stack,
        @Nullable BlockGetter level,
        List<Component> tooltip,
        TooltipFlag flag
    ) {
        tooltip.add(
            Component.translatable("block.tiedup.rope_trap.desc").withStyle(
                ChatFormatting.GRAY
            )
        );

        CompoundTag nbt = stack.getTag();
        if (nbt != null && nbt.contains("BlockEntityTag")) {
            CompoundTag beTag = nbt.getCompound("BlockEntityTag");

            // Check if armed
            if (beTag.contains("bind")) {
                tooltip.add(
                    Component.translatable("block.tiedup.trap.armed").withStyle(
                        ChatFormatting.DARK_RED
                    )
                );

                // List loaded items
                BondageItemLoaderUtility.addItemToTooltip(
                    tooltip,
                    beTag,
                    "bind"
                );
                BondageItemLoaderUtility.addItemToTooltip(
                    tooltip,
                    beTag,
                    "gag"
                );
                BondageItemLoaderUtility.addItemToTooltip(
                    tooltip,
                    beTag,
                    "blindfold"
                );
                BondageItemLoaderUtility.addItemToTooltip(
                    tooltip,
                    beTag,
                    "earplugs"
                );
                BondageItemLoaderUtility.addItemToTooltip(
                    tooltip,
                    beTag,
                    "collar"
                );
                BondageItemLoaderUtility.addItemToTooltip(
                    tooltip,
                    beTag,
                    "clothes"
                );
            } else {
                tooltip.add(
                    Component.translatable("block.tiedup.trap.disarmed").withStyle(
                        ChatFormatting.GREEN
                    )
                );
            }
        } else {
            tooltip.add(
                Component.translatable("block.tiedup.trap.disarmed").withStyle(ChatFormatting.GREEN)
            );
        }
    }
}
