package com.tiedup.remake.items;

import com.tiedup.remake.cells.CellDataV2;
import com.tiedup.remake.cells.CellRegistryV2;
import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.entities.EntityDamsel;
import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.network.personality.PacketOpenCommandWandScreen;
import com.tiedup.remake.personality.HomeType;
import com.tiedup.remake.personality.JobExperience;
import com.tiedup.remake.personality.NpcCommand;
import com.tiedup.remake.personality.NpcNeeds;
import com.tiedup.remake.personality.PersonalityState;
import com.tiedup.remake.v2.BodyRegionV2;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
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.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.state.BlockState;

/**
 * Command Wand - Used to give commands to collared NPCs.
 *
 * Personality System Phase E: Command Wand Item
 *
 * <p><b>Usage:</b></p>
 * <ul>
 *   <li>Right-click on a collared NPC you own to open command GUI</li>
 *   <li>Shows personality info, needs, and available commands</li>
 *   <li>Only works on NPCs wearing a collar you own</li>
 * </ul>
 */
public class ItemCommandWand extends Item {

    // NBT tags for selection mode
    private static final String TAG_SELECTING_FOR = "SelectingFor";
    private static final String TAG_JOB_TYPE = "JobType";
    // Two-click selection for TRANSFER
    private static final String TAG_SELECTING_STEP = "SelectingStep"; // 1 = chest A, 2 = chest B
    private static final String TAG_FIRST_CHEST_POS = "FirstChestPos"; // BlockPos of chest A

    public ItemCommandWand() {
        super(new Item.Properties().stacksTo(1));
    }

    // ========== Selection Mode Methods ==========

    /**
     * Check if wand is in selection mode (waiting for chest click).
     */
    public static boolean isInSelectionMode(ItemStack stack) {
        return stack.hasTag() && stack.getTag().contains(TAG_SELECTING_FOR);
    }

    /**
     * Enter selection mode - waiting for player to click a chest.
     *
     * HIGH FIX: Now uses UUID instead of entity ID for persistence across restarts.
     *
     * @param stack The wand item stack
     * @param entityUUID The NPC entity UUID (persistent)
     * @param job The job command to assign
     */
    public static void enterSelectionMode(
        ItemStack stack,
        java.util.UUID entityUUID,
        NpcCommand job
    ) {
        stack.getOrCreateTag().putUUID(TAG_SELECTING_FOR, entityUUID);
        stack.getOrCreateTag().putString(TAG_JOB_TYPE, job.name());
        // For TRANSFER, we need two clicks
        if (job == NpcCommand.TRANSFER) {
            stack.getOrCreateTag().putInt(TAG_SELECTING_STEP, 1);
        }
    }

    /**
     * Exit selection mode.
     */
    public static void exitSelectionMode(ItemStack stack) {
        if (stack.hasTag()) {
            stack.getTag().remove(TAG_SELECTING_FOR);
            stack.getTag().remove(TAG_JOB_TYPE);
            stack.getTag().remove(TAG_SELECTING_STEP);
            stack.getTag().remove(TAG_FIRST_CHEST_POS);
        }
    }

    /**
     * Get the current selection step (1 = first chest, 2 = second chest).
     * Returns 0 if not in multi-step selection.
     */
    public static int getSelectingStep(ItemStack stack) {
        return stack.hasTag() ? stack.getTag().getInt(TAG_SELECTING_STEP) : 0;
    }

    /**
     * Get the first chest position (for TRANSFER).
     */
    @Nullable
    public static BlockPos getFirstChestPos(ItemStack stack) {
        if (!stack.hasTag() || !stack.getTag().contains(TAG_FIRST_CHEST_POS)) {
            return null;
        }
        return BlockPos.of(stack.getTag().getLong(TAG_FIRST_CHEST_POS));
    }

    /**
     * Set the first chest position and advance to step 2.
     */
    public static void setFirstChestAndAdvance(ItemStack stack, BlockPos pos) {
        stack.getOrCreateTag().putLong(TAG_FIRST_CHEST_POS, pos.asLong());
        stack.getOrCreateTag().putInt(TAG_SELECTING_STEP, 2);
    }

    /**
     * Get the entity UUID being selected for.
     *
     * HIGH FIX: Returns UUID instead of entity ID for persistence.
     */
    @Nullable
    public static java.util.UUID getSelectingForEntity(ItemStack stack) {
        if (!stack.hasTag() || !stack.getTag().hasUUID(TAG_SELECTING_FOR)) {
            return null;
        }
        return stack.getTag().getUUID(TAG_SELECTING_FOR);
    }

    /**
     * Get the job type being assigned.
     */
    @Nullable
    public static NpcCommand getSelectingJobType(ItemStack stack) {
        if (!stack.hasTag() || !stack.getTag().contains(TAG_JOB_TYPE)) {
            return null;
        }
        return NpcCommand.fromString(stack.getTag().getString(TAG_JOB_TYPE));
    }

    // ========== Block Interaction (Chest Selection) ==========

    @Override
    public InteractionResult useOn(UseOnContext context) {
        ItemStack stack = context.getItemInHand();
        Player player = context.getPlayer();

        if (player == null) {
            return InteractionResult.PASS;
        }

        BlockPos clickedPos = context.getClickedPos();
        Level level = context.getLevel();
        BlockState blockState = level.getBlockState(clickedPos);

        // Selection mode for job commands
        if (!isInSelectionMode(stack)) {
            return InteractionResult.PASS;
        }

        // Must click on a chest
        if (!(blockState.getBlock() instanceof ChestBlock)) {
            if (!level.isClientSide) {
                SystemMessageManager.sendToPlayer(
                    player,
                    SystemMessageManager.MessageCategory.ERROR,
                    "You must click on a chest to set the work zone!"
                );
            }
            return InteractionResult.FAIL;
        }

        // Server-side: directly apply the command (we're already on server)
        if (!level.isClientSide) {
            // HIGH FIX: Use UUID instead of entity ID for persistence
            java.util.UUID entityUUID = getSelectingForEntity(stack);
            NpcCommand command = getSelectingJobType(stack);
            int selectingStep = getSelectingStep(stack);

            if (command != null && entityUUID != null) {
                // TRANSFER requires two chests
                if (command == NpcCommand.TRANSFER) {
                    if (selectingStep == 1) {
                        // First click: store source chest A
                        setFirstChestAndAdvance(stack, clickedPos);
                        SystemMessageManager.sendToPlayer(
                            player,
                            SystemMessageManager.MessageCategory.INFO,
                            "Source chest set at " +
                                clickedPos.toShortString() +
                                ". Now click on the DESTINATION chest."
                        );
                        return InteractionResult.SUCCESS;
                    } else if (selectingStep == 2) {
                        // Second click: apply command with both chests
                        BlockPos sourceChest = getFirstChestPos(stack);
                        if (sourceChest == null) {
                            SystemMessageManager.sendToPlayer(
                                player,
                                SystemMessageManager.MessageCategory.ERROR,
                                "Error: Source chest not set. Try again."
                            );
                            exitSelectionMode(stack);
                            return InteractionResult.FAIL;
                        }

                        // Prevent selecting same chest twice
                        if (sourceChest.equals(clickedPos)) {
                            SystemMessageManager.sendToPlayer(
                                player,
                                SystemMessageManager.MessageCategory.ERROR,
                                "Destination must be different from source chest!"
                            );
                            return InteractionResult.FAIL;
                        }

                        // Find the NPC entity (HIGH FIX: lookup by UUID)
                        net.minecraft.world.entity.Entity entity = (
                            (net.minecraft.server.level.ServerLevel) level
                        ).getEntity(entityUUID);
                        if (entity instanceof EntityDamsel damsel) {
                            // Give TRANSFER command with source (commandTarget) and dest (commandTarget2)
                            boolean success = damsel.giveCommandWithTwoTargets(
                                player,
                                command,
                                sourceChest, // Source chest A
                                clickedPos // Destination chest B
                            );

                            if (success) {
                                SystemMessageManager.sendToPlayer(
                                    player,
                                    SystemMessageManager.MessageCategory.INFO,
                                    damsel.getNpcName() +
                                        " will transfer items from " +
                                        sourceChest.toShortString() +
                                        " to " +
                                        clickedPos.toShortString()
                                );

                                TiedUpMod.LOGGER.debug(
                                    "[ItemCommandWand] {} set TRANSFER for {} from {} to {}",
                                    player.getName().getString(),
                                    damsel.getNpcName(),
                                    sourceChest,
                                    clickedPos
                                );
                            } else {
                                SystemMessageManager.sendToPlayer(
                                    player,
                                    SystemMessageManager.MessageCategory.ERROR,
                                    damsel.getNpcName() + " refused the job!"
                                );
                            }
                        }
                        exitSelectionMode(stack);
                        return InteractionResult.SUCCESS;
                    }
                }

                // Standard single-chest job commands (FARM, COOK, SHEAR, etc.) (HIGH FIX: lookup by UUID)
                net.minecraft.world.entity.Entity entity = (
                    (net.minecraft.server.level.ServerLevel) level
                ).getEntity(entityUUID);
                if (entity instanceof EntityDamsel damsel) {
                    // Give command directly (already validated acceptance in PacketNpcCommand)
                    boolean success = damsel.giveCommand(
                        player,
                        command,
                        clickedPos
                    );

                    if (success) {
                        SystemMessageManager.sendToPlayer(
                            player,
                            SystemMessageManager.MessageCategory.INFO,
                            "Work zone set! " +
                                damsel.getNpcName() +
                                " will " +
                                command.name() +
                                " at " +
                                clickedPos.toShortString()
                        );

                        TiedUpMod.LOGGER.debug(
                            "[ItemCommandWand] {} set work zone for {} at {}",
                            player.getName().getString(),
                            damsel.getNpcName(),
                            clickedPos
                        );
                    } else {
                        SystemMessageManager.sendToPlayer(
                            player,
                            SystemMessageManager.MessageCategory.ERROR,
                            damsel.getNpcName() + " refused the job!"
                        );
                    }
                }

                // Exit selection mode
                exitSelectionMode(stack);
            }
        }

        return InteractionResult.SUCCESS;
    }

    // ========== Entity Interaction ==========

    @Override
    public InteractionResult interactLivingEntity(
        ItemStack stack,
        Player player,
        LivingEntity target,
        InteractionHand hand
    ) {
        // Only works on EntityDamsel (and subclasses like EntityKidnapper)
        if (!(target instanceof EntityDamsel damsel)) {
            return InteractionResult.PASS;
        }

        // Server-side only
        if (player.level().isClientSide) {
            return InteractionResult.SUCCESS;
        }

        // Must have collar
        if (!damsel.hasCollar()) {
            SystemMessageManager.sendToPlayer(
                player,
                SystemMessageManager.MessageCategory.ERROR,
                damsel.getNpcName() + " is not wearing a collar!"
            );
            return InteractionResult.FAIL;
        }

        // Get collar and verify ownership
        ItemStack collar = damsel.getEquipment(BodyRegionV2.NECK);
        if (!CollarHelper.isCollar(collar)) {
            return InteractionResult.PASS;
        }

        if (!CollarHelper.isOwner(collar, player)) {
            SystemMessageManager.sendToPlayer(
                player,
                SystemMessageManager.MessageCategory.ERROR,
                "You don't own " + damsel.getNpcName() + "'s collar!"
            );
            return InteractionResult.FAIL;
        }

        // Get personality data
        PersonalityState state = damsel.getPersonalityState();
        if (state == null) {
            TiedUpMod.LOGGER.warn(
                "[ItemCommandWand] No personality state for {}",
                damsel.getNpcName()
            );
            return InteractionResult.FAIL;
        }

        // Always show personality (discovery system removed)
        String personalityName = state.getPersonality().name();

        // Get home type
        String homeType = state.getHomeType().name();

        // Cell info for GUI
        String cellName = "";
        String cellQualityName = "";
        if (
            state.getCellId() != null &&
            player.level() instanceof net.minecraft.server.level.ServerLevel sl
        ) {
            CellDataV2 cell = CellRegistryV2.get(sl).getCell(state.getCellId());
            if (cell != null) {
                cellName =
                    cell.getName() != null
                        ? cell.getName()
                        : "Cell " + cell.getId().toString().substring(0, 8);
            }
        }
        cellQualityName =
            state.getCellQuality() != null ? state.getCellQuality().name() : "";

        // Get needs
        NpcNeeds needs = state.getNeeds();

        // Get job experience for active command
        JobExperience jobExp = state.getJobExperience();
        NpcCommand activeCmd = state.getActiveCommand();
        String activeJobLevelName = "";
        int activeJobXp = 0;
        int activeJobXpMax = 10;
        if (activeCmd.isActiveJob()) {
            JobExperience.JobLevel level = jobExp.getJobLevel(activeCmd);
            activeJobLevelName = level.name();
            activeJobXp = jobExp.getExperience(activeCmd);
            activeJobXpMax = level.maxExp;
        }

        // Send packet to open GUI (HIGH FIX: pass UUID instead of entity ID)
        if (player instanceof ServerPlayer sp) {
            ModNetwork.sendToPlayer(
                new PacketOpenCommandWandScreen(
                    damsel.getUUID(),
                    damsel.getNpcName(),
                    personalityName,
                    activeCmd.name(),
                    needs.getHunger(),
                    needs.getRest(),
                    state.getMood(),
                    state.getFollowDistance().name(),
                    homeType,
                    state.isAutoRestEnabled(),
                    cellName,
                    cellQualityName,
                    activeJobLevelName,
                    activeJobXp,
                    activeJobXpMax
                ),
                sp
            );
        }

        TiedUpMod.LOGGER.debug(
            "[ItemCommandWand] {} opened command wand for {}",
            player.getName().getString(),
            damsel.getNpcName()
        );

        return InteractionResult.SUCCESS;
    }

    @Override
    public void appendHoverText(
        ItemStack stack,
        @Nullable Level level,
        List<Component> tooltip,
        TooltipFlag flag
    ) {
        if (isInSelectionMode(stack)) {
            NpcCommand job = getSelectingJobType(stack);
            int step = getSelectingStep(stack);
            tooltip.add(
                Component.literal("SELECTION MODE").withStyle(
                    ChatFormatting.GOLD,
                    ChatFormatting.BOLD
                )
            );
            // Different messages for TRANSFER two-step selection
            if (job == NpcCommand.TRANSFER) {
                if (step == 1) {
                    tooltip.add(
                        Component.literal("Click SOURCE chest (1/2)").withStyle(
                            ChatFormatting.YELLOW
                        )
                    );
                } else if (step == 2) {
                    BlockPos source = getFirstChestPos(stack);
                    tooltip.add(
                        Component.literal(
                            "Click DESTINATION chest (2/2)"
                        ).withStyle(ChatFormatting.YELLOW)
                    );
                    if (source != null) {
                        tooltip.add(
                            Component.literal(
                                "Source: " + source.toShortString()
                            ).withStyle(ChatFormatting.GRAY)
                        );
                    }
                }
            } else {
                tooltip.add(
                    Component.literal(
                        "Click a chest to set work zone"
                    ).withStyle(ChatFormatting.YELLOW)
                );
            }
            if (job != null) {
                tooltip.add(
                    Component.literal("Job: " + job.name()).withStyle(
                        ChatFormatting.AQUA
                    )
                );
            }
            tooltip.add(Component.literal(""));
            tooltip.add(
                Component.literal("Right-click empty to cancel").withStyle(
                    ChatFormatting.RED
                )
            );
        } else {
            tooltip.add(
                Component.literal("Right-click a collared NPC").withStyle(
                    ChatFormatting.GRAY
                )
            );
            tooltip.add(
                Component.literal("to give commands").withStyle(
                    ChatFormatting.GRAY
                )
            );
            tooltip.add(Component.literal(""));
            tooltip.add(
                Component.literal("Commands: FOLLOW, STAY, HEEL...").withStyle(
                    ChatFormatting.DARK_PURPLE
                )
            );
            tooltip.add(
                Component.literal("Jobs: FARM, COOK, STORE").withStyle(
                    ChatFormatting.GREEN
                )
            );
        }
    }

    @Override
    public boolean isFoil(ItemStack stack) {
        // Enchantment glint when in selection mode
        return isInSelectionMode(stack);
    }
}
