package com.tiedup.remake.state;

import com.tiedup.remake.v2.BodyRegionV2;
import java.util.UUID;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

/**
 * Base identity, lifecycle, and utility interface for kidnapped entities.
 *
 * <p>Provides the fundamental identity methods ({@link #asLivingEntity()},
 * {@link #getKidnappedUniqueId()}, etc.), death handling, and default
 * helper methods for communication and movement queries.</p>
 *
 * <p>Also hosts the V2 region-based equipment API defaults, which delegate
 * to {@code V2EquipmentHelper} and work automatically for Players.</p>
 *
 * @see ICapturable
 * @see IBondageState
 * @see ICoercible
 * @see IRestrainable
 */
public interface IRestrainableEntity {
    // ENTITY IDENTITY

    /**
     * Get the underlying LivingEntity.
     *
     * <p>For Players: return the player
     * <p>For NPCs: return this (cast to LivingEntity)
     *
     * @return The LivingEntity backing this IRestrainable instance
     */
    LivingEntity asLivingEntity();

    /**
     * Get the unique ID of this kidnapped entity.
     *
     * @return The entity's UUID
     */
    UUID getKidnappedUniqueId();

    /**
     * Get the display name of this kidnapped entity.
     * For players: player name. For NPCs: entity custom name or default name.
     *
     * @return The entity's name as string
     */
    String getKidnappedName();

    /**
     * Get the name from the collar's NBT tag (nickname).
     * If collar has no nickname, returns empty string or entity name.
     *
     * @return The collar nickname, or fallback name
     */
    String getNameFromCollar();

    // LIFECYCLE

    /**
     * Called when this entity dies while kidnapped.
     *
     * <p><b>From original (PlayerBindState.java:1395-1461):</b></p>
     * <ul>
     *   <li>Unlock all locked items</li>
     *   <li>Drop bondage items (if configured)</li>
     *   <li>Free from slavery</li>
     *   <li>Reset state</li>
     * </ul>
     *
     * @param world The world the entity died in
     * @return true if death was handled as kidnapped entity
     */
    boolean onDeathKidnapped(Level world);

    // UTILITY

    /**
     * Drop an item at this entity's position.
     * Helper method for dropping bondage items.
     *
     * @param stack The ItemStack to drop
     */
    void kidnappedDropItem(ItemStack stack);

    /**
     * Teleport this entity to a specific position.
     * Used by collar teleport commands and warp points.
     *
     * @param position The target position (x, y, z, dimension)
     */
    void teleportToPosition(com.tiedup.remake.util.teleport.Position position);

    // DEFAULT HELPER METHODS - COMMUNICATION & STATE

    /**
     * Send a message to this entity (if it can receive messages).
     *
     * <p>For Players: Uses displayClientMessage()
     * <p>For NPCs: No-op (NPCs don't need visual feedback)
     *
     * @param message The message component to send
     * @param actionBar If true, shows message in action bar; if false, shows in chat
     */
    default void sendMessage(Component message, boolean actionBar) {
        LivingEntity entity = asLivingEntity();
        if (entity instanceof Player player) {
            player.displayClientMessage(message, actionBar);
        }
        // NPCs: silent no-op (acceptable degradation)
    }

    /**
     * Check if entity is currently sprinting.
     *
     * <p>For Players: player.isSprinting()
     * <p>For NPCs: Checks movement speed
     *
     * @return true if entity is sprinting
     */
    default boolean isSprinting() {
        LivingEntity entity = asLivingEntity();
        if (entity instanceof Player player) {
            return player.isSprinting();
        }
        // For NPCs: check movement speed
        return entity.getDeltaMovement().horizontalDistanceSqr() > 0.1;
    }

    /**
     * Check if entity is currently swimming.
     *
     * @return true if entity is swimming
     */
    default boolean isSwimming() {
        return asLivingEntity().isSwimming();
    }

    // ==================== V2 REGION-BASED API ====================
    // These default methods delegate to V2EquipmentHelper.
    // They work automatically for Players (V2 capability attached since Epic 0).
    // For Damsels, requires IV2EquipmentHolder implementation (Epic 4B).

    /**
     * Get all V2 equipped items (de-duplicated).
     * @return Unmodifiable map of region to ItemStack, or empty map if no V2 support.
     */
    default java.util.Map<
        com.tiedup.remake.v2.BodyRegionV2,
        ItemStack
    > getAllEquippedV2() {
        com.tiedup.remake.v2.bondage.IV2BondageEquipment equip =
            com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.getEquipment(
                asLivingEntity()
            );
        return equip != null ? equip.getAllEquipped() : java.util.Map.of();
    }

    /**
     * Get V2 item in a specific body region.
     */
    default ItemStack getItemInRegion(
        com.tiedup.remake.v2.BodyRegionV2 region
    ) {
        return com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.getInRegion(
            asLivingEntity(),
            region
        );
    }

    /**
     * Equip a V2 item to its declared regions. Server-only.
     * @return The equip result.
     */
    default com.tiedup.remake.v2.bondage.V2EquipResult equipToRegion(
        ItemStack stack
    ) {
        return com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.equipItem(
            asLivingEntity(),
            stack
        );
    }

    /**
     * Unequip V2 item from a region. Server-only.
     */
    default ItemStack unequipFromRegion(
        com.tiedup.remake.v2.BodyRegionV2 region
    ) {
        return com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.unequipFromRegion(
            asLivingEntity(),
            region
        );
    }

    /**
     * Unequip V2 item from a region with force option. Server-only.
     */
    default ItemStack unequipFromRegion(
        com.tiedup.remake.v2.BodyRegionV2 region,
        boolean force
    ) {
        return com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.unequipFromRegion(
            asLivingEntity(),
            region,
            force
        );
    }

    /**
     * Whether this entity has V2 equipment support.
     */
    default boolean hasV2Support() {
        return (
            com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.getEquipment(
                asLivingEntity()
            ) !=
            null
        );
    }
}
