/*
 * Copyright (c) 2026 盐灯水母
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

package com.remains_cave.block;

import com.remains_cave.block.entity.TombDoorBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
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;
import org.jetbrains.annotations.NotNull;

import java.util.List;

public class TombDoorPartBlock extends Block {
    public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;

    public TombDoorPartBlock() {
        super(Properties.of()
                .strength(20.0F, 20.0F)
                .noOcclusion()
                .sound(SoundType.TUFF_BRICKS)
                .requiresCorrectToolForDrops()
                .isRedstoneConductor((state, level, pos) -> false)
        );
        this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH));
    }

    @Override
    protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
        builder.add(FACING);
    }

    @Override
    public @NotNull InteractionResult useWithoutItem(@NotNull BlockState state, @NotNull Level level, @NotNull BlockPos pos,
                                                     @NotNull Player player, @NotNull BlockHitResult hitResult) {
        BlockPos corePos = findCoreBlock(level, pos, state.getValue(FACING));
        if (corePos != null) {
            if (level.getBlockEntity(corePos) instanceof TombDoorBlockEntity door) {
                return door.onUse(level.getBlockState(corePos), player, hitResult);
            }
        }
        return InteractionResult.PASS;
    }

    private BlockPos findCoreBlock(BlockGetter level, BlockPos partPos, Direction facing) {
        for (int dx = -2; dx <= 2; dx++) {
            for (int dy = -3; dy <= 3; dy++) {
                for (int dz = -2; dz <= 2; dz++) {
                    BlockPos checkPos = partPos.offset(dx, dy, dz);
                    BlockState state = level.getBlockState(checkPos);
                    if (state.getBlock() instanceof TombDoorCoreBlock) {
                        Direction coreFacing = state.getValue(TombDoorCoreBlock.FACING);
                        List<BlockPos> partPositions = TombDoorCoreBlock.getPartPositions(checkPos, coreFacing);
                        if (partPositions.contains(partPos)) {
                            return checkPos;
                        }
                    }
                }
            }
        }
        return null;
    }

    @Override
    public void onRemove(@NotNull BlockState state, Level level, @NotNull BlockPos pos, @NotNull BlockState newState, boolean isMoving) {
        if (!level.isClientSide && !state.is(newState.getBlock())) {
            Direction facing = state.getValue(FACING);
            BlockPos corePos = findCoreBlock(level, pos, facing);
            if (corePos != null && level.getBlockState(corePos).getBlock() instanceof TombDoorCoreBlock) {
                level.destroyBlock(corePos, true);
            }
        }
        super.onRemove(state, level, pos, newState, isMoving);
    }

    private static VoxelShape getDoorShape(Direction facing) {
        double minX = 0.0, maxX = 16.0, minY = 0.0, maxY = 16.0, minZ = 4.0, maxZ = 12.0;
        return switch (facing) {
            case NORTH -> Shapes.box(minX/16, minY/16, minZ/16, maxX/16, maxY/16, maxZ/16);
            case SOUTH -> Shapes.box(minX/16, minY/16, 1 - maxZ/16, maxX/16, maxY/16, 1 - minZ/16);
            case WEST -> Shapes.box(minZ/16, minY/16, minX/16, maxZ/16, maxY/16, maxX/16);
            case EAST -> Shapes.box(1 - maxZ/16, minY/16, minX/16, 1 - minZ/16, maxY/16, maxX/16);
            default -> Shapes.block();
        };
    }

    @Override
    public @NotNull VoxelShape getShape(@NotNull BlockState state, @NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull CollisionContext context) {
        return getDoorShape(state.getValue(FACING));
    }

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

    @Override
    public @NotNull VoxelShape getCollisionShape(BlockState state, @NotNull BlockGetter level, @NotNull BlockPos pos, @NotNull CollisionContext context) {
        Direction facing = state.getValue(FACING);
        BlockPos corePos = findCoreBlock(level, pos, facing);
        if (corePos != null) {
            BlockState coreState = level.getBlockState(corePos);
            if (coreState.getBlock() instanceof TombDoorCoreBlock) {
                return coreState.getCollisionShape(level, corePos, context);
            }
        }
        return getDoorShape(facing);
    }
}