package com.tiedup.remake.events.camp;

import com.tiedup.remake.blocks.BlockMarker;
import com.tiedup.remake.blocks.entity.MarkerBlockEntity;
import com.tiedup.remake.cells.CampOwnership;
import com.tiedup.remake.cells.CampOwnership.CampData;
import com.tiedup.remake.cells.MarkerType;
import com.tiedup.remake.core.TiedUpMod;
import java.util.UUID;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

/**
 * Event handler for camp chest access control.
 *
 * Chests with a LOOT marker above them are locked while the camp trader is alive.
 * Only camp members (trader, maid, kidnappers) can access them.
 */
@Mod.EventBusSubscriber(
    modid = TiedUpMod.MOD_ID,
    bus = Mod.EventBusSubscriber.Bus.FORGE
)
public class CampChestHandler {

    @SubscribeEvent
    public static void onChestOpen(PlayerInteractEvent.RightClickBlock event) {
        if (event.getLevel().isClientSide()) {
            return;
        }

        BlockPos pos = event.getPos();
        ServerLevel level = (ServerLevel) event.getLevel();

        // Only check if clicking a chest
        if (!(level.getBlockState(pos).getBlock() instanceof ChestBlock)) {
            return;
        }

        // Check if there's a LOOT marker above this chest
        BlockPos markerPos = pos.above();
        if (
            !(level.getBlockState(markerPos).getBlock() instanceof BlockMarker)
        ) {
            return; // No marker above, allow normal access
        }

        BlockEntity be = level.getBlockEntity(markerPos);
        if (!(be instanceof MarkerBlockEntity marker)) {
            return;
        }

        // Check if it's a LOOT marker
        if (marker.getMarkerType() != MarkerType.LOOT) {
            return; // Not a LOOT marker, allow normal access
        }

        // Find the nearest camp
        CampOwnership registry = CampOwnership.get(level);
        CampData camp = registry.findNearestAliveCamp(pos, 100);

        if (camp == null) {
            return; // No camp nearby, allow access
        }

        // Camp dead = chest accessible
        if (!camp.isAlive()) {
            return; // Trader dead, chest unlocked
        }

        // Check if the entity has camp access
        Entity entity = event.getEntity();
        if (hasCampAccess(camp, entity)) {
            return; // Camp member, allow access
        }

        // Deny access
        event.setCanceled(true);
        event.setCancellationResult(InteractionResult.FAIL);

        if (entity instanceof Player player) {
            player.displayClientMessage(
                Component.translatable(
                    "msg.tiedup.event.chest_locked_by_camp"
                ).withStyle(ChatFormatting.RED),
                true
            );
        }

        TiedUpMod.LOGGER.debug(
            "[CampChestHandler] Denied access to LOOT chest at {} for {}",
            pos.toShortString(),
            entity.getName().getString()
        );
    }

    /**
     * Check if an entity has access to the camp's resources.
     *
     * @param camp The camp data
     * @param entity The entity trying to access
     * @return true if the entity is allowed access
     */
    private static boolean hasCampAccess(CampData camp, Entity entity) {
        UUID entityId = entity.getUUID();

        // Trader has access
        if (entityId.equals(camp.getTraderUUID())) {
            return true;
        }

        // Maid has access
        if (entityId.equals(camp.getMaidUUID())) {
            return true;
        }

        // Kidnapper linked to this camp has access
        if (camp.hasKidnapper(entityId)) {
            return true;
        }

        return false;
    }
}
