package com.tiedup.remake.compat.mca.event;

import com.tiedup.remake.compat.mca.MCACompat;
import com.tiedup.remake.compat.mca.capability.MCAKidnappedProvider;
import com.tiedup.remake.core.SettingsAccessor;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.ItemKey;
import com.tiedup.remake.items.ItemMasterKey;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.tasks.UntyingPlayerTask;
import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageItem;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
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;

/**
 * Event handlers for MCA compatibility.
 *
 * - Attaches bondage capability to MCA villagers when they spawn.
 * - Handles death of tied MCA villagers.
 * - Intercepts MCA menu interaction when holding TiedUp items or untying.
 */
@Mod.EventBusSubscriber(modid = TiedUpMod.MOD_ID)
public class MCACompatEvents {

    /**
     * Map to track ongoing untying tasks for MCA villagers.
     * Key: Villager UUID, Value: The active untying task
     */
    private static final Map<UUID, UntyingPlayerTask> mcaUntyingTasks =
        new HashMap<>();

    /**
     * Attach bondage capability to MCA villagers.
     *
     * Called whenever an entity is created and capabilities are attached.
     */
    @SubscribeEvent
    public static void onAttachCapabilities(
        AttachCapabilitiesEvent<Entity> event
    ) {
        // Only process if MCA is loaded
        if (!MCACompat.isMCALoaded()) {
            return;
        }

        Entity entity = event.getObject();

        // Check if this is an MCA villager
        if (MCACompat.shouldAttachCapability(entity)) {
            event.addCapability(
                MCACompat.MCA_KIDNAPPED_CAP_ID,
                new MCAKidnappedProvider()
            );

            TiedUpMod.LOGGER.debug(
                "[MCA Compat] Attached bondage capability to MCA villager: {} (type: {})",
                entity.getName().getString(),
                entity.getType().toString()
            );
        }
    }

    /**
     * Handle death of MCA villagers.
     * Drops bondage items and frees captive.
     */
    @SubscribeEvent
    public static void onLivingDeath(LivingDeathEvent event) {
        if (!MCACompat.isMCALoaded()) return;

        LivingEntity entity = event.getEntity();
        if (!MCACompat.isMCAVillager(entity)) return;

        IBondageState state = MCACompat.getKidnappedState(entity);
        if (state != null) {
            // Trigger death logic (drops items, frees captive)
            state.onDeathKidnapped(entity.level());
        }
    }

    /**
     * Intercept MCA villager INTERACT_AT (hitbox interaction) when holding TiedUp bondage items.
     *
     * MCA handles interactAt() which is triggered by INTERACT_AT packets.
     * This event fires BEFORE EntityInteract and is where MCA opens their menu.
     *
     * Uses HIGHEST priority to run before anything else.
     */
    @SubscribeEvent(priority = EventPriority.HIGHEST)
    public static void onEntityInteractSpecific(
        PlayerInteractEvent.EntityInteractSpecific event
    ) {
        if (
            !handleMCAInteraction(
                event,
                event.getTarget(),
                event.getEntity(),
                event.getHand()
            )
        ) {
            return;
        }
        // Event was handled and canceled in handleMCAInteraction
    }

    /**
     * Intercept MCA villager INTERACT (normal interaction) when holding TiedUp bondage items.
     *
     * This is a backup in case interactAt doesn't catch it.
     *
     * Uses HIGHEST priority to run before anything else.
     */
    @SubscribeEvent(priority = EventPriority.HIGHEST)
    public static void onEntityInteract(
        PlayerInteractEvent.EntityInteract event
    ) {
        if (
            !handleMCAInteraction(
                event,
                event.getTarget(),
                event.getEntity(),
                event.getHand()
            )
        ) {
            return;
        }
        // Event was handled and canceled in handleMCAInteraction
    }

    /**
     * Common handler for both interaction types.
     *
     * @return true if interaction was handled and event should be considered processed
     */
    private static boolean handleMCAInteraction(
        PlayerInteractEvent event,
        Entity target,
        Player player,
        InteractionHand hand
    ) {
        // Only process if MCA is loaded
        if (!MCACompat.isMCALoaded()) {
            return false;
        }

        // Only intercept for MCA villagers
        if (!MCACompat.isMCAVillager(target)) {
            return false;
        }

        // Target must be a LivingEntity for bondage items
        if (
            !(target instanceof
                    net.minecraft.world.entity.LivingEntity livingTarget)
        ) {
            return false;
        }

        ItemStack heldItem = player.getItemInHand(hand);

        // 1. Check for TiedUp interaction items (Bondage, Keys)
        boolean isTiedUpItem =
            heldItem.getItem() instanceof IV2BondageItem ||
            heldItem.getItem() instanceof ItemKey ||
            heldItem.getItem() instanceof ItemMasterKey;

        // 2. Check for Shift-Click Untying logic
        // If player is crouching AND target is tied/gagged/collared, shift-click should untie/interact
        // regardless of held item (unless it's a specific item that overrides shift-click)
        boolean isShiftClickUntying = false;
        if (player.isCrouching()) {
            IBondageState state = MCACompat.getKidnappedState(livingTarget);
            if (
                state != null &&
                (state.isTiedUp() ||
                    state.isGagged() ||
                    state.isBlindfolded() ||
                    state.hasCollar())
            ) {
                isShiftClickUntying = true;
            }
        }

        // If neither case applies, let MCA handle it
        if (!isTiedUpItem && !isShiftClickUntying) {
            return false;
        }

        // Cancel the event FIRST to prevent MCA from handling it
        event.setCanceled(true);

        // Manually trigger interaction logic
        net.minecraft.world.InteractionResult result =
            net.minecraft.world.InteractionResult.PASS;

        if (isTiedUpItem) {
            // Let the item handle it
            result = heldItem.interactLivingEntity(player, livingTarget, hand);
        } else if (isShiftClickUntying) {
            // Shift-click interaction logic for untying/ungagging
            IBondageState state = MCACompat.getKidnappedState(livingTarget);
            if (state != null) {
                // Priority: Untie > Ungag > Unblindfold > etc.
                // This mimics EntityDamsel logic or TyingInteractionHelper logic for untying

                // No collar ownership check — any player can untie MCA villagers by design
                // (MCA villagers use a separate relationship system, not TiedUp collars)

                boolean actionTaken = false;

                // Try to remove items in order
                if (state.isTiedUp()) {
                    // Check if player can untie (e.g. has knife if needed, or if resistance allows)
                    // For now, allow simple untying
                    if (!state.getEquipment(BodyRegionV2.ARMS).isEmpty()) {
                        // Ensure there is a bind
                        // Check lock
                        ItemStack bind = state.getEquipment(BodyRegionV2.ARMS);
                        if (
                            bind.getItem() instanceof
                                com.tiedup.remake.items.base.ILockable lockable &&
                            lockable.isLocked(bind)
                        ) {
                            // Locked - can't untie without key
                            // Maybe send message?
                        } else {
                            // Use timed untying task (same as Damsels - 10 seconds by default)
                            UUID villagerUuid = livingTarget.getUUID();
                            UntyingPlayerTask existingTask =
                                mcaUntyingTasks.get(villagerUuid);

                            int untyingSeconds =
                                SettingsAccessor.getUntyingPlayerTime(
                                    player.level().getGameRules()
                                );

                            if (
                                existingTask == null ||
                                existingTask.isOutdated() ||
                                existingTask.getTargetEntity() != livingTarget
                            ) {
                                // Create new untying task
                                UntyingPlayerTask newTask =
                                    new UntyingPlayerTask(
                                        state,
                                        livingTarget,
                                        untyingSeconds,
                                        player.level(),
                                        player
                                    );
                                mcaUntyingTasks.put(villagerUuid, newTask);
                                existingTask = newTask;

                                TiedUpMod.LOGGER.debug(
                                    "[MCA Compat] Started untying task for {} ({} seconds)",
                                    livingTarget.getName().getString(),
                                    untyingSeconds
                                );
                            } else {
                                // Continue existing task, update helper reference
                                existingTask.setHelper(player);
                            }

                            // Update task progress (sends progress packets, completes if timer expired)
                            existingTask.update();

                            // Clean up completed tasks
                            if (existingTask.isStopped()) {
                                mcaUntyingTasks.remove(villagerUuid);
                            }

                            actionTaken = true;
                        }
                    }
                } else if (state.isGagged()) {
                    // Check lock
                    ItemStack gag = state.getEquipment(BodyRegionV2.MOUTH);
                    if (
                        gag.getItem() instanceof
                            com.tiedup.remake.items.base.ILockable lockable &&
                        lockable.isLocked(gag)
                    ) {
                        // Locked
                    } else {
                        state.unequip(BodyRegionV2.MOUTH);
                        state.kidnappedDropItem(gag);
                        actionTaken = true;
                    }
                }
                // Add other removal logic as needed

                if (actionTaken) {
                    result = net.minecraft.world.InteractionResult.SUCCESS;
                    player.swing(hand, true);
                } else {
                    // If we couldn't remove anything (e.g. locked), maybe open GUI?
                    // Or simply PASS but keep event canceled to stop MCA menu
                    result = net.minecraft.world.InteractionResult.CONSUME;
                }
            }
        }

        event.setCancellationResult(result);

        TiedUpMod.LOGGER.debug(
            "[MCA Compat] Intercepted MCA interaction - {} on {} (Item: {}, Shift: {}, Result: {})",
            player.getName().getString(),
            target.getName().getString(),
            isTiedUpItem
                ? heldItem.getItem().getClass().getSimpleName()
                : "Other",
            isShiftClickUntying,
            result
        );

        return true;
    }
}
