package com.tiedup.remake.mixin;

import com.tiedup.remake.compat.mca.MCACompat;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.items.ItemKey;
import com.tiedup.remake.items.ItemMasterKey;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageItem;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

/**
 * Mixin to manage TiedUp vs MCA interaction priority.
 *
 * <p>Handles TiedUp interactions DIRECTLY instead of just blocking MCA,
 * because vanilla leash/item handling happens at different points in the
 * interaction chain that MCA may bypass.
 *
 * <p>Priority rules:
 * <ol>
 *   <li>Empty hand + leashed → detach leash</li>
 *   <li>Holding lead + (tied OR collar owner) → attach leash</li>
 *   <li>Holding key + collared → call key.interactLivingEntity()</li>
 *   <li>Shift+click + tied + empty hand → let event handler untie</li>
 *   <li>Holding bondage item → let item handle tying</li>
 *   <li>Otherwise → let MCA handle</li>
 * </ol>
 *
 * <p>Uses @Pseudo - mixin is optional and will be skipped if MCA is not installed.
 */
@Pseudo
@Mixin(targets = "forge.net.mca.entity.VillagerEntityMCA", remap = false)
public abstract class MixinMCAVillagerInteraction {

    /**
     * Inject at HEAD of mobInteract to handle TiedUp interactions.
     * Method: InteractionResult mobInteract(Player, InteractionHand)
     */
    @Inject(
        method = "m_6071_",
        at = @At("HEAD"),
        cancellable = true,
        remap = false
    )
    private void tiedup$handleMobInteract(
        Player player,
        InteractionHand hand,
        CallbackInfoReturnable<InteractionResult> cir
    ) {
        InteractionResult result = tiedup$handleInteraction(player, hand);
        if (result != null) {
            cir.setReturnValue(result);
        }
    }

    /**
     * Inject at HEAD of interactAt to handle TiedUp interactions BEFORE MCA opens its menu.
     * Method: InteractionResult interactAt(Player, Vec3, InteractionHand)
     */
    @Inject(
        method = "m_7111_",
        at = @At("HEAD"),
        cancellable = true,
        remap = false
    )
    private void tiedup$handleInteractAt(
        Player player,
        net.minecraft.world.phys.Vec3 vec,
        InteractionHand hand,
        CallbackInfoReturnable<InteractionResult> cir
    ) {
        InteractionResult result = tiedup$handleInteraction(player, hand);
        if (result != null) {
            cir.setReturnValue(result);
        }
    }

    /**
     * Common interaction handling logic for both mobInteract and interactAt.
     *
     * @param player The player interacting
     * @param hand The hand used for interaction
     * @return InteractionResult to return, or null to let MCA handle
     */
    @Unique
    private InteractionResult tiedup$handleInteraction(
        Player player,
        InteractionHand hand
    ) {
        Mob mob = (Mob) (Object) this;
        IBondageState state = MCACompat.getKidnappedState(mob);
        ItemStack heldItem = player.getItemInHand(hand);
        boolean isClientSide = player.level().isClientSide;

        // 1. LEASH DETACHMENT: Empty hand + leashed → drop leash
        if (mob.isLeashed() && heldItem.isEmpty()) {
            if (!isClientSide) {
                mob.dropLeash(true, !player.getAbilities().instabuild);
                TiedUpMod.LOGGER.debug("[MCA] Detached leash from villager");
            }
            return InteractionResult.sidedSuccess(isClientSide);
        }

        // 2. LEASH ATTACHMENT: Holding lead + (tied OR collar owner)
        if (heldItem.is(Items.LEAD) && !mob.isLeashed()) {
            if (tiedup$canLeash(player, state)) {
                if (!isClientSide) {
                    mob.setLeashedTo(player, true);
                    if (!player.getAbilities().instabuild) {
                        heldItem.shrink(1);
                    }
                    TiedUpMod.LOGGER.debug("[MCA] Attached leash to villager");
                }
                return InteractionResult.sidedSuccess(isClientSide);
            }
        }

        // 3. KEY INTERACTION: Key + collared → call key's interactLivingEntity
        if (state != null && state.hasCollar()) {
            if (heldItem.getItem() instanceof ItemKey key) {
                return key.interactLivingEntity(heldItem, player, mob, hand);
            }
            if (heldItem.getItem() instanceof ItemMasterKey masterKey) {
                return masterKey.interactLivingEntity(
                    heldItem,
                    player,
                    mob,
                    hand
                );
            }
        }

        // 4. UNTYING: Shift+click + tied + empty hand → let event handler process
        if (
            state != null &&
            state.isTiedUp() &&
            heldItem.isEmpty() &&
            player.isShiftKeyDown()
        ) {
            return InteractionResult.PASS;
        }

        // 5. BONDAGE ITEM: Let TiedUp item's interactLivingEntity handle tying
        if (heldItem.getItem() instanceof IV2BondageItem) {
            return InteractionResult.PASS;
        }

        // Let MCA handle
        return null;
    }

    /**
     * Check if a player can leash this MCA villager.
     *
     * @param player The player trying to leash
     * @param state The villager's IBondageState state (may be null)
     * @return true if leashing is allowed
     */
    @Unique
    private boolean tiedup$canLeash(Player player, IBondageState state) {
        if (state == null) {
            return false;
        }

        // Can leash if villager is tied up
        if (state.isTiedUp()) {
            return true;
        }

        // Can leash if player is a collar owner
        if (state.hasCollar()) {
            ItemStack collar = state.getEquipment(BodyRegionV2.NECK);
            if (CollarHelper.isCollar(collar)) {
                return CollarHelper.isOwner(collar, player);
            }
        }

        return false;
    }
}
