package com.tiedup.remake.blocks;

import com.tiedup.remake.blocks.entity.CellCoreBlockEntity;
import com.tiedup.remake.cells.*;
import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.cell.PacketOpenCoreMenu;
import java.util.UUID;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
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.material.MapColor;
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.Nullable;

/**
 * Cell Core block - the anchor for a Cell System V2 cell.
 *
 * Placed into a wall of an enclosed room. On placement, runs flood-fill to
 * detect the room boundaries and registers a new cell. On removal, destroys
 * the cell.
 *
 * Obsidian-tier hardness to prevent easy breaking by prisoners.
 */
public class BlockCellCore extends BaseEntityBlock {

    public BlockCellCore() {
        super(
            BlockBehaviour.Properties.of()
                .mapColor(MapColor.STONE)
                .strength(50.0f, 1200.0f)
                .requiresCorrectToolForDrops()
                .sound(SoundType.STONE)
                .noOcclusion()
                .dynamicShape()
        );
    }

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

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

    // ==================== DYNAMIC SHAPE (disguise-aware) ====================

    @SuppressWarnings("deprecation")
    @Override
    public VoxelShape getShape(
        BlockState state,
        BlockGetter level,
        BlockPos pos,
        CollisionContext context
    ) {
        if (level.getBlockEntity(pos) instanceof CellCoreBlockEntity core) {
            BlockState disguise = core.getDisguiseState();
            if (disguise == null) disguise = core.resolveDisguise();
            if (disguise != null) {
                return disguise.getShape(level, pos, context);
            }
        }
        return Shapes.block();
    }

    @SuppressWarnings("deprecation")
    @Override
    public VoxelShape getCollisionShape(
        BlockState state,
        BlockGetter level,
        BlockPos pos,
        CollisionContext context
    ) {
        if (level.getBlockEntity(pos) instanceof CellCoreBlockEntity core) {
            BlockState disguise = core.getDisguiseState();
            if (disguise == null) disguise = core.resolveDisguise();
            if (disguise != null) {
                return disguise.getCollisionShape(level, pos, context);
            }
        }
        return Shapes.block();
    }

    /**
     * Right-click handler: open the Cell Core menu for the cell owner.
     */
    @SuppressWarnings("deprecation")
    @Override
    public InteractionResult use(
        BlockState state,
        Level level,
        BlockPos pos,
        Player player,
        InteractionHand hand,
        BlockHitResult hit
    ) {
        if (level.isClientSide) {
            return InteractionResult.SUCCESS;
        }

        if (!(player instanceof ServerPlayer serverPlayer)) {
            return InteractionResult.PASS;
        }

        BlockEntity be = level.getBlockEntity(pos);
        if (
            !(be instanceof CellCoreBlockEntity core) ||
            core.getCellId() == null
        ) {
            return InteractionResult.PASS;
        }

        CellRegistryV2 registry = CellRegistryV2.get((ServerLevel) level);
        CellDataV2 cell = registry.getCell(core.getCellId());
        if (cell == null) {
            return InteractionResult.PASS;
        }

        // Check ownership (owner, camp cell, or OP level 2)
        if (!cell.canPlayerManage(player.getUUID(), player.hasPermissions(2))) {
            player.displayClientMessage(
                Component.translatable("msg.tiedup.cell_core.not_owner"),
                true
            );
            return InteractionResult.CONSUME;
        }

        // Send packet with all cell stats
        ModNetwork.sendToPlayer(
            new PacketOpenCoreMenu(
                pos,
                cell.getId(),
                cell.getName() != null ? cell.getName() : "",
                cell.getState().getSerializedName(),
                cell.getInteriorBlocks().size(),
                cell.getWallBlocks().size(),
                cell.getBreachedPositions().size(),
                cell.getPrisonerCount(),
                cell.getBeds().size(),
                cell.getDoors().size(),
                cell.getAnchors().size(),
                core.getSpawnPoint() != null,
                core.getDeliveryPoint() != null,
                core.getDisguiseState() != null
            ),
            serverPlayer
        );

        return InteractionResult.CONSUME;
    }

    /**
     * On placement: run flood-fill to detect the room, create a cell if successful.
     * If the room cannot be detected, break the block back and show an error.
     */
    @Override
    public void setPlacedBy(
        Level level,
        BlockPos pos,
        BlockState state,
        @Nullable LivingEntity placer,
        ItemStack stack
    ) {
        super.setPlacedBy(level, pos, state, placer, stack);

        if (
            level instanceof ServerLevel serverLevel &&
            placer instanceof Player player
        ) {
            BlockEntity be = level.getBlockEntity(pos);
            if (!(be instanceof CellCoreBlockEntity core)) return;

            FloodFillResult result = FloodFillAlgorithm.tryFill(level, pos);
            if (result.isSuccess()) {
                CellRegistryV2 registry = CellRegistryV2.get(serverLevel);
                CellDataV2 cell = registry.createCell(
                    pos,
                    result,
                    player.getUUID()
                );

                core.setCellId(cell.getId());
                core.setInteriorFace(result.getInteriorFace());

                player.displayClientMessage(
                    Component.translatable(
                        "msg.tiedup.cell_core.created",
                        result.getInterior().size(),
                        result.getWalls().size()
                    ),
                    true
                );
            } else {
                // Failed — break the block back (can't form a cell here)
                level.destroyBlock(pos, true);
                player.displayClientMessage(
                    Component.translatable(result.getErrorKey()),
                    true
                );
            }
        }
    }

    /**
     * On removal: destroy the cell in the registry.
     */
    @SuppressWarnings("deprecation")
    @Override
    public void onRemove(
        BlockState state,
        Level level,
        BlockPos pos,
        BlockState newState,
        boolean movedByPiston
    ) {
        if (!state.is(newState.getBlock())) {
            if (level instanceof ServerLevel serverLevel) {
                BlockEntity be = level.getBlockEntity(pos);
                if (
                    be instanceof CellCoreBlockEntity core &&
                    core.getCellId() != null
                ) {
                    CellRegistryV2 registry = CellRegistryV2.get(serverLevel);
                    CellDataV2 cell = registry.getCell(core.getCellId());
                    if (cell != null) {
                        cell.setState(CellState.COMPROMISED);

                        // Free all prisoners
                        for (UUID prisonerId : cell.getPrisonerIds()) {
                            registry.releasePrisoner(
                                cell.getId(),
                                prisonerId,
                                serverLevel.getServer()
                            );
                        }

                        // Notify owner
                        if (cell.getOwnerId() != null) {
                            ServerPlayer owner = serverLevel
                                .getServer()
                                .getPlayerList()
                                .getPlayer(cell.getOwnerId());
                            if (owner != null) {
                                String cellName =
                                    cell.getName() != null
                                        ? cell.getName()
                                        : "Cell " +
                                          cell
                                              .getId()
                                              .toString()
                                              .substring(0, 8);
                                SystemMessageManager.sendToPlayer(
                                    owner,
                                    SystemMessageManager.MessageCategory.WARNING,
                                    cellName + " has been destroyed!"
                                );
                            }
                        }

                        registry.removeCell(cell.getId());
                    }
                }
            }
        }
        super.onRemove(state, level, pos, newState, movedByPiston);
    }
}
