package com.tiedup.remake.entities.armorstand;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.armorstand.PacketSyncArmorStandBondage;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageItem;
import java.util.Set;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

/**
 * Handles player interaction with armor stands for bondage item equipping.
 *
 * Right-click with bondage item: Equip to armor stand
 * Shift+Right-click (empty hand): Remove bondage items from armor stand
 *
 * Uses EntityInteractSpecific event which is what armor stands use for position-based interactions.
 */
@Mod.EventBusSubscriber(modid = TiedUpMod.MOD_ID)
public class ArmorStandInteractionHandler {

    static {
        TiedUpMod.LOGGER.info(
            "[ArmorStandInteractionHandler] Event handler class loaded!"
        );
    }

    /**
     * Handle armor stand interaction via EntityInteractSpecific event.
     * This is the event that armor stands use for position-based interactions.
     */
    @SubscribeEvent(priority = EventPriority.HIGHEST)
    public static void onArmorStandInteract(
        PlayerInteractEvent.EntityInteractSpecific event
    ) {
        // Server-side only
        if (event.getLevel().isClientSide()) return;
        if (!(event.getTarget() instanceof ArmorStand armorStand)) return;

        Player player = event.getEntity();
        ItemStack heldItem = player.getItemInHand(event.getHand());

        // Shift+click with empty hand to remove items
        if (player.isShiftKeyDown() && heldItem.isEmpty()) {
            if (tryRemoveBondageItem(player, armorStand)) {
                event.setCanceled(true);
                event.setCancellationResult(InteractionResult.SUCCESS);
            }
            return;
        }

        // Try to equip bondage item
        if (heldItem.getItem() instanceof IV2BondageItem bondageItem) {
            // Use primary region (first occupied region)
            Set<BodyRegionV2> regions = bondageItem.getOccupiedRegions(
                heldItem
            );
            if (regions.isEmpty()) return; // Data-driven item with missing definition
            BodyRegionV2 region = regions.iterator().next();

            ItemStack existing = ArmorStandBondageHelper.getStackInSlot(
                armorStand,
                region
            );
            ItemStack toEquip = heldItem.copy();
            toEquip.setCount(1);

            // Set the item in the slot
            ArmorStandBondageHelper.setStackInSlot(armorStand, region, toEquip);

            // Consume item from player
            if (!player.isCreative()) {
                heldItem.shrink(1);
            }

            // Give back existing item if swapping
            if (!existing.isEmpty()) {
                if (!player.addItem(existing)) {
                    player.drop(existing, false);
                }
            }

            // Sync to clients
            syncSlotToClients(armorStand, region, toEquip);

            TiedUpMod.LOGGER.debug(
                "[ArmorStandInteraction] Player {} equipped {} on armor stand",
                player.getName().getString(),
                region.name()
            );

            event.setCanceled(true);
            event.setCancellationResult(InteractionResult.SUCCESS);
        }
    }

    /**
     * Try to remove a bondage item from an armor stand.
     * Removes items in reverse priority (accessories first, then bind/ARMS).
     *
     * @param player The player removing items
     * @param armorStand The armor stand
     * @return True if an item was removed
     */
    private static boolean tryRemoveBondageItem(
        Player player,
        ArmorStand armorStand
    ) {
        // Remove items in reverse priority (accessories first, then bind)
        BodyRegionV2[] removeOrder = {
            BodyRegionV2.HANDS,
            BodyRegionV2.EARS,
            BodyRegionV2.EYES,
            BodyRegionV2.MOUTH,
            BodyRegionV2.NECK,
            BodyRegionV2.TORSO,
            BodyRegionV2.ARMS,
        };

        for (BodyRegionV2 region : removeOrder) {
            ItemStack stack = ArmorStandBondageHelper.getStackInSlot(
                armorStand,
                region
            );
            if (!stack.isEmpty()) {
                // Clear the slot
                ArmorStandBondageHelper.setStackInSlot(
                    armorStand,
                    region,
                    ItemStack.EMPTY
                );

                // Give item to player
                if (!player.addItem(stack)) {
                    player.drop(stack, false);
                }

                // Sync to clients
                syncSlotToClients(armorStand, region, ItemStack.EMPTY);

                TiedUpMod.LOGGER.debug(
                    "[ArmorStandInteraction] Player {} removed {} from armor stand",
                    player.getName().getString(),
                    region.name()
                );

                return true; // Remove one item per click
            }
        }

        return false;
    }

    /**
     * Sync a bondage slot to all tracking clients.
     *
     * @param armorStand The armor stand
     * @param region The body region
     * @param stack The item in the slot
     */
    private static void syncSlotToClients(
        ArmorStand armorStand,
        BodyRegionV2 region,
        ItemStack stack
    ) {
        PacketSyncArmorStandBondage packet = new PacketSyncArmorStandBondage(
            armorStand.getId(),
            region,
            stack
        );
        ModNetwork.sendToAllTrackingEntity(packet, armorStand);
    }

    /**
     * Sync bondage data when a player starts tracking an armor stand.
     * This ensures data is synced when:
     * - Player joins the world and armor stands are in range
     * - Player moves into range of an armor stand
     * - Armor stand is loaded from save
     */
    @SubscribeEvent
    public static void onStartTracking(PlayerEvent.StartTracking event) {
        if (!(event.getTarget() instanceof ArmorStand armorStand)) return;
        if (!(event.getEntity() instanceof ServerPlayer serverPlayer)) return;

        // Check if this armor stand has any bondage items
        if (!ArmorStandBondageHelper.hasBondageItems(armorStand)) return;

        // Sync all bondage slots to the player
        for (BodyRegionV2 region : ArmorStandBondageHelper.VALID_REGIONS) {
            ItemStack stack = ArmorStandBondageHelper.getStackInSlot(
                armorStand,
                region
            );
            if (!stack.isEmpty()) {
                PacketSyncArmorStandBondage packet =
                    new PacketSyncArmorStandBondage(
                        armorStand.getId(),
                        region,
                        stack
                    );
                ModNetwork.sendToPlayer(packet, serverPlayer);
            }
        }
    }
}
