package com.tiedup.remake.items;

import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.items.base.ItemOwnerTarget;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper;
import com.tiedup.remake.v2.BodyRegionV2;
import java.util.List;
import java.util.UUID;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.jetbrains.annotations.Nullable;

/**
 * Collar Key - Used to lock/unlock bondage items via the Slave Management GUI.
 *
 * <p>Key-Lock System</p>
 * <ul>
 *   <li><b>Linking:</b> Right-click a player wearing a collar to link (claim) the key to them.</li>
 *   <li><b>Management:</b> Opens SlaveItemManagementScreen to lock/unlock individual items.</li>
 *   <li><b>Key UUID:</b> Each key has a unique UUID used to identify which locks it created.</li>
 *   <li><b>Security:</b> Only items locked with this key can be unlocked by it.</li>
 * </ul>
 */
public class ItemKey extends ItemOwnerTarget {

    private static final String NBT_KEY_UUID = "keyUUID";

    public ItemKey() {
        super(new net.minecraft.world.item.Item.Properties().durability(64));
    }

    // ========== Key UUID System ==========

    /**
     * Get the unique UUID for this key.
     * Generates one if it doesn't exist yet.
     * This UUID is used to identify locks created by this specific key.
     *
     * @param stack The key ItemStack
     * @return The key's unique UUID
     */
    public UUID getKeyUUID(ItemStack stack) {
        CompoundTag tag = stack.getOrCreateTag();
        if (!tag.hasUUID(NBT_KEY_UUID)) {
            // Generate a new UUID for this key
            tag.putUUID(NBT_KEY_UUID, UUID.randomUUID());
        }
        return tag.getUUID(NBT_KEY_UUID);
    }

    /**
     * Check if this key matches the given UUID.
     *
     * @param stack The key ItemStack
     * @param lockUUID The lock's UUID to check against
     * @return true if this key matches the lock
     */
    public boolean matchesLock(ItemStack stack, UUID lockUUID) {
        if (lockUUID == null) return false;
        return lockUUID.equals(getKeyUUID(stack));
    }

    /**
     * Shows ownership and target information when hovering over the item in inventory.
     */
    @Override
    public void appendHoverText(
        ItemStack stack,
        @Nullable Level level,
        List<Component> tooltip,
        TooltipFlag flag
    ) {
        super.appendHoverText(stack, level, tooltip, flag);

        if (hasOwner(stack)) {
            tooltip.add(
                Component.translatable("item.tiedup.key.owner", getOwnerName(stack))
                    .withStyle(ChatFormatting.GOLD)
            );
        } else {
            tooltip.add(
                Component.translatable("item.tiedup.key.unclaimed")
                    .withStyle(ChatFormatting.GRAY)
            );
        }

        if (hasTarget(stack)) {
            tooltip.add(
                Component.translatable("item.tiedup.key.target", getTargetName(stack))
                    .withStyle(ChatFormatting.BLUE)
            );
        }

        tooltip.add(
            Component.translatable("item.tiedup.key.hint")
                .withStyle(ChatFormatting.DARK_GRAY)
                .withStyle(ChatFormatting.ITALIC)
        );
    }

    /**
     * Logic for interacting with entities wearing collars.
     * Opens the Slave Item Management GUI to lock/unlock individual items.
     *
     */
    @Override
    public InteractionResult interactLivingEntity(
        ItemStack stack,
        Player player,
        LivingEntity target,
        InteractionHand hand
    ) {
        // Check if target can wear collars (Player, EntityDamsel, EntityKidnapper)
        IBondageState targetState = KidnappedHelper.getKidnappedState(target);

        // Target must be wearing a collar
        if (targetState == null || !targetState.hasCollar()) {
            if (!player.level().isClientSide) {
                SystemMessageManager.sendToPlayer(
                    player,
                    SystemMessageManager.MessageCategory.ERROR,
                    "Target is not wearing a collar!"
                );
            }
            return InteractionResult.FAIL;
        }

        // Server-side: Handle claiming and validation
        if (!player.level().isClientSide) {
            // 1. Claim logic - first interaction with a collar wearer links the key
            if (!hasOwner(stack)) {
                setOwner(stack, player);
                setTarget(stack, target);
                // Ensure key UUID is generated
                getKeyUUID(stack);

                // Also link the player to the collar (become collar owner)
                linkPlayerToCollar(player, target, targetState);

                SystemMessageManager.sendToPlayer(
                    player,
                    SystemMessageManager.MessageCategory.KEY_CLAIMED,
                    target
                );
                player.setItemInHand(hand, stack); // Sync NBT to client
                return InteractionResult.SUCCESS;
            }

            // 2. Ownership check - only the person who claimed the key can use it
            if (!isOwner(stack, player)) {
                SystemMessageManager.sendToPlayer(
                    player,
                    SystemMessageManager.MessageCategory.KEY_NOT_OWNER
                );
                return InteractionResult.FAIL;
            }

            // 3. Target check - this key only fits the entity it was first linked to
            if (
                target instanceof Player targetPlayer &&
                !isTarget(stack, targetPlayer)
            ) {
                SystemMessageManager.sendToPlayer(
                    player,
                    SystemMessageManager.MessageCategory.KEY_WRONG_TARGET
                );
                return InteractionResult.FAIL;
            } else if (
                !(target instanceof Player) &&
                !target.getUUID().equals(getTargetId(stack))
            ) {
                SystemMessageManager.sendToPlayer(
                    player,
                    SystemMessageManager.MessageCategory.KEY_WRONG_TARGET
                );
                return InteractionResult.FAIL;
            }

            // Server validation passed - client will open GUI
            return InteractionResult.SUCCESS;
        }

        // Client-side: Open the Slave Item Management GUI
        // Only open if key is already claimed and we're the owner (client trusts server validation)
        if (hasOwner(stack) && isOwner(stack, player)) {
            // Verify target matches (client-side check for responsiveness)
            boolean targetMatches = false;
            if (target instanceof Player targetPlayer) {
                targetMatches = isTarget(stack, targetPlayer);
            } else {
                targetMatches = target.getUUID().equals(getTargetId(stack));
            }

            if (targetMatches) {
                openUnifiedBondageScreen(target);
            }
        }

        return InteractionResult.SUCCESS;
    }

    /**
     * Opens the UnifiedBondageScreen in master mode targeting a specific entity.
     * Called from client-side code only.
     *
     * @param target The living entity to manage bondage for
     */
    @OnlyIn(Dist.CLIENT)
    private void openUnifiedBondageScreen(
        net.minecraft.world.entity.LivingEntity target
    ) {
        net.minecraft.client.Minecraft.getInstance().setScreen(
            new com.tiedup.remake.client.gui.screens.UnifiedBondageScreen(
                target
            )
        );
    }

    /**
     * Link a player to a collar - make them an owner.
     *
     * <p>When a key is claimed on a collared entity:
     * <ul>
     *   <li>Add player as owner to the collar item</li>
     *   <li>Register the relationship in CollarRegistry</li>
     * </ul>
     *
     * @param player The player claiming the key
     * @param target The collared entity
     * @param targetState The target's IBondageState state
     */
    private void linkPlayerToCollar(
        Player player,
        LivingEntity target,
        IBondageState targetState
    ) {
        ItemStack collarStack = targetState.getEquipment(BodyRegionV2.NECK);
        if (collarStack.isEmpty()) return;

        if (com.tiedup.remake.v2.bondage.CollarHelper.isCollar(collarStack)) {
            // Add player as owner to the collar (if not already)
            if (!com.tiedup.remake.v2.bondage.CollarHelper.isOwner(collarStack, player)) {
                com.tiedup.remake.v2.bondage.CollarHelper.addOwner(collarStack, player);

                // Update the collar in the target's inventory
                targetState.equip(BodyRegionV2.NECK, collarStack);
            }

            // Register in CollarRegistry (if on server)
            if (
                player.level() instanceof
                    net.minecraft.server.level.ServerLevel serverLevel
            ) {
                com.tiedup.remake.state.CollarRegistry registry =
                    com.tiedup.remake.state.CollarRegistry.get(serverLevel);
                if (registry != null) {
                    registry.registerCollar(target.getUUID(), player.getUUID());

                    // Sync the registry to the new owner
                    if (
                        player instanceof
                            net.minecraft.server.level.ServerPlayer serverPlayer
                    ) {
                        java.util.Set<UUID> slaves = registry.getSlaves(
                            player.getUUID()
                        );
                        com.tiedup.remake.network.ModNetwork.sendToPlayer(
                            new com.tiedup.remake.network.sync.PacketSyncCollarRegistry(
                                slaves
                            ),
                            serverPlayer
                        );
                    }
                }

                // Sync the target's inventory (collar was modified)
                if (
                    target instanceof
                        net.minecraft.server.level.ServerPlayer targetPlayer
                ) {
                    com.tiedup.remake.network.sync.SyncManager.syncInventory(
                        targetPlayer
                    );
                }
            }
        }
    }
}
