package com.tiedup.remake.events.restriction;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityLaborGuard;
import com.tiedup.remake.prison.LaborRecord;
import com.tiedup.remake.prison.PrisonerManager;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.ShulkerBoxBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.event.entity.item.ItemTossEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.jetbrains.annotations.Nullable;

/**
 * Event handler for labor tool protection.
 *
 * Prevents prisoners from:
 * - Dropping labor tools
 * - Storing labor tools in containers
 *
 * Note: Death handling removed - if prisoner dies, they're no longer working anyway.
 *
 * This is extracted from CampLaborEventHandler after the refactoring to remove event-driven task tracking.
 * Only the essential protection mechanisms remain.
 */
@Mod.EventBusSubscriber(modid = TiedUpMod.MOD_ID)
public class LaborToolProtectionHandler {

    private static final Map<UUID, Long> lastDropWarningTick = new HashMap<>();
    private static final long DROP_WARNING_COOLDOWN = 60; // 3 seconds

    /** Remove player entry on disconnect to prevent memory leak. */
    public static void cleanupPlayer(java.util.UUID playerId) {
        lastDropWarningTick.remove(playerId);
    }

    /**
     * Prevent dropping labor tools.
     * Forge removes the item from inventory before firing ItemTossEvent,
     * so we must restore it after canceling.
     */
    @SubscribeEvent
    public static void onItemToss(ItemTossEvent event) {
        ItemStack stack = event.getEntity().getItem();
        if (!isLaborTool(stack)) return;

        // Cancel + restore (Forge removes from inventory before event fires)
        event.setCanceled(true);
        event.getPlayer().getInventory().add(stack);

        Player player = event.getPlayer();
        if (!(player instanceof ServerPlayer serverPlayer)) return;
        if (!(player.level() instanceof ServerLevel level)) return;

        // Cooldown
        long tick = level.getGameTime();
        Long last = lastDropWarningTick.get(player.getUUID());
        if (last != null && (tick - last) < DROP_WARNING_COOLDOWN) return;
        lastDropWarningTick.put(player.getUUID(), tick);

        // Guard reaction
        EntityLaborGuard guard = findGuardForPlayer(level, player.getUUID());
        if (guard != null && guard.isAlive()) {
            guard.getLookControl().setLookAt(player);
            guard.guardSay(
                serverPlayer,
                "guard.labor.drop_tool",
                "Stupid! Don't drop your tools!"
            );
        } else {
            player.displayClientMessage(
                Component.translatable("msg.tiedup.event.cant_drop_labor_tools"),
                true
            );
        }
    }

    /**
     * Prevent storing labor tools in containers.
     */
    @SubscribeEvent
    public static void onRightClickBlock(
        PlayerInteractEvent.RightClickBlock event
    ) {
        Player player = event.getEntity();
        ItemStack held = player.getMainHandItem();
        if (!isLaborTool(held)) return;

        BlockState state = event.getLevel().getBlockState(event.getPos());
        if (
            !(state.getBlock() instanceof ChestBlock) &&
            !(state.getBlock() instanceof ShulkerBoxBlock)
        ) return;

        event.setCanceled(true);

        if (
            player instanceof ServerPlayer sp &&
            player.level() instanceof ServerLevel sl
        ) {
            // Reuse same cooldown
            long tick = sl.getGameTime();
            Long last = lastDropWarningTick.get(player.getUUID());
            if (last != null && (tick - last) < DROP_WARNING_COOLDOWN) return;
            lastDropWarningTick.put(player.getUUID(), tick);

            EntityLaborGuard guard = findGuardForPlayer(sl, player.getUUID());
            if (guard != null && guard.isAlive()) {
                guard.getLookControl().setLookAt(player);
                guard.guardSay(
                    sp,
                    "guard.labor.hide_tool",
                    "Don't try to hide your tools!"
                );
            } else {
                player.displayClientMessage(
                    Component.translatable("msg.tiedup.event.cant_store_labor_tools"),
                    true
                );
            }
        }
    }

    @Nullable
    private static EntityLaborGuard findGuardForPlayer(
        ServerLevel level,
        UUID playerUUID
    ) {
        PrisonerManager manager = PrisonerManager.get(level);
        LaborRecord labor = manager.getLaborRecord(playerUUID);
        UUID guardId = labor.getGuardId();
        if (guardId == null) return null;
        net.minecraft.world.entity.Entity entity = level.getEntity(guardId);
        if (entity instanceof EntityLaborGuard guard) return guard;
        return null;
    }

    /**
     * Check if an item is a labor tool (tagged as LaborTool).
     */
    private static boolean isLaborTool(ItemStack stack) {
        return stack.hasTag() && stack.getTag().getBoolean("LaborTool");
    }
}
