package com.tiedup.remake.network.slave;

import com.tiedup.remake.network.PacketRateLimiter;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageItem;
import com.tiedup.remake.v2.bondage.V2EquipResult;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
import java.util.UUID;
import java.util.function.Supplier;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.network.NetworkEvent;

/**
 * Client→Server: Master equips an item from their inventory onto a slave's body region.
 */
public class PacketMasterEquip {

    private final UUID targetEntityUUID;
    private final BodyRegionV2 region;
    private final int inventorySlot;

    public PacketMasterEquip(
        UUID targetEntityUUID,
        BodyRegionV2 region,
        int inventorySlot
    ) {
        this.targetEntityUUID = targetEntityUUID;
        this.region = region;
        this.inventorySlot = inventorySlot;
    }

    public static void encode(PacketMasterEquip msg, FriendlyByteBuf buf) {
        buf.writeUUID(msg.targetEntityUUID);
        buf.writeEnum(msg.region);
        buf.writeVarInt(msg.inventorySlot);
    }

    public static PacketMasterEquip decode(FriendlyByteBuf buf) {
        return new PacketMasterEquip(
            buf.readUUID(),
            buf.readEnum(BodyRegionV2.class),
            buf.readVarInt()
        );
    }

    public static void handle(
        PacketMasterEquip msg,
        Supplier<NetworkEvent.Context> ctxSupplier
    ) {
        NetworkEvent.Context ctx = ctxSupplier.get();
        ctx.enqueueWork(() -> {
            ServerPlayer sender = ctx.getSender();
            if (sender == null) return;
            if (!PacketRateLimiter.allowPacket(sender, "action")) return;

            // Find target entity (reuse package-private method from PacketSlaveItemManage)
            LivingEntity target = PacketSlaveItemManage.findTargetEntity(
                sender,
                msg.targetEntityUUID
            );
            if (target == null) return;

            // Distance check (5 blocks)
            if (sender.distanceTo(target) > 5.0f) return;

            // Collar ownership check
            IBondageState targetState = KidnappedHelper.getKidnappedState(
                target
            );
            if (targetState == null || !targetState.hasCollar()) return;
            ItemStack collarStack = targetState.getEquipment(BodyRegionV2.NECK);
            if (CollarHelper.isCollar(collarStack)) {
                if (
                    !CollarHelper.isOwner(collarStack, sender) &&
                    !sender.hasPermissions(2)
                ) return;
            }

            // Validate sender's inventory slot
            if (
                msg.inventorySlot < 0 ||
                msg.inventorySlot >= sender.getInventory().getContainerSize()
            ) return;
            ItemStack stack = sender.getInventory().getItem(msg.inventorySlot);
            if (stack.isEmpty()) return;
            if (
                !(stack.getItem() instanceof IV2BondageItem bondageItem)
            ) return;
            if (
                !bondageItem.getOccupiedRegions(stack).contains(msg.region)
            ) return;

            // Furniture seat blocks this region
            if (
                target.isPassenger() &&
                target.getVehicle() instanceof
                    com.tiedup.remake.v2.furniture.ISeatProvider provider
            ) {
                com.tiedup.remake.v2.furniture.SeatDefinition seat =
                    provider.getSeatForPassenger(target);
                if (
                    seat != null && seat.blockedRegions().contains(msg.region)
                ) {
                    return; // Region blocked by furniture
                }
            }

            // Equip on target
            V2EquipResult result = V2EquipmentHelper.equipItem(target, stack);
            if (result.isSuccess()) {
                sender.getInventory().removeItem(msg.inventorySlot, 1);
                // Return any displaced items to master's inventory
                if (result.displaced() != null) {
                    for (ItemStack displaced : result.displaced()) {
                        if (!displaced.isEmpty()) {
                            sender
                                .getInventory()
                                .placeItemBackInInventory(displaced);
                        }
                    }
                }
            }
        });
        ctx.setPacketHandled(true);
    }
}
