/*
 *  Copyright 2025-2026 R3944Realms
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package top.r3944realms.eroticdungeongame.content.item;

import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
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.state.BlockState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.eroticdungeongame.EroticDungeon;
import top.r3944realms.eroticdungeongame.api.workspace.Services;
import top.r3944realms.eroticdungeongame.content.block.ISeatBlock;
import top.r3944realms.eroticdungeongame.content.block.blockentity.BaseSeatBlockEntity;
import top.r3944realms.eroticdungeongame.content.block.multiply.IHasPrimaryPart;
import top.r3944realms.eroticdungeongame.core.register.EDGSoundEvents;

import java.util.List;
import java.util.Objects;

public class DeviceKeyItem extends Item {
    public static final String LOCK_CODE ="lockCode";
    public DeviceKeyItem(Properties properties) {
        super(properties);
    }
    private static final int keyLong = 9;
    private static final String[] keyString = new String[]{
            "║","╒","╓","╔","╕","╖","╗",
            "╘","╙","╚","╛","╜","╝","╞",
            "╟","╠","╡","╢","╣","╤","╥",
            "╦","╧","╨","╩","╪","╫","╬"
    };

    public static long generateLockCode(@NotNull LivingEntity entity) {
        long base = 1;
        long result = 0;
        RandomSource randomSource = entity.getRandom();
        for (int i = 0; i < keyLong - 1; i++, base *= 100) {
            int random = randomSource.nextInt(keyString.length);
            result += base * random;
        }
        int color = randomSource.nextInt(16);
        return result + color * base;
    }

    public static @NotNull Component turnLockCodeToComponent(long lockCode){
        long base = 1;
        MutableComponent component = Component.literal("");
        for (int i = 0; i < keyLong - 1; i++, base *= 100) {
            int result = (int) (lockCode / base % 100);
            try {component.append(Component.literal(keyString[result]));
            }catch (Exception ignored){}
        }
        int color = (int) (lockCode / base % 100);
        ChatFormatting componentColor = ChatFormatting.getById(color);
        if(componentColor == null) componentColor = ChatFormatting.WHITE;
        component.withStyle(componentColor);
        return component;
    }

    @Override
    public @NotNull InteractionResult interactLivingEntity(@NotNull ItemStack stack, @NotNull Player player, @NotNull LivingEntity interactionTarget, @NotNull InteractionHand usedHand) {
        if (player.level().isClientSide()) {
            return InteractionResult.PASS;
        }
        return Services.WORK_SPACE.tryToDoIfInDeviceAndRet(interactionTarget, i -> {
            if (player.level().getBlockEntity(i.getDeviceMainBlockPos()) instanceof BaseSeatBlockEntity base) {
                return keyBindLogic(player.level().getBlockState(i.getDeviceMainBlockPos()), i.getDeviceMainBlockPos(), player.level(), player.getItemInHand(InteractionHand.MAIN_HAND), player);
            } return InteractionResult.PASS;
        }, () -> InteractionResult.PASS);
    }

    @Override
    public @NotNull InteractionResult useOn(@NotNull UseOnContext context) {
        Level level = context.getLevel();
        if(context.getHand() == InteractionHand.MAIN_HAND && !level.isClientSide()) {
            Player player = context.getPlayer();
            if(player != null) {
               BlockPos pos = context.getClickedPos();
                ItemStack itemInHand = context.getItemInHand();
               BlockState state = level.getBlockState(pos);
                InteractionResult success = keyBindLogic(state, pos, level, itemInHand, player);
                if (success != null) return success;
            }
        }
        return InteractionResult.PASS;
    }

    private static @Nullable InteractionResult keyBindLogic(@NotNull BlockState state, BlockPos pos, Level level, ItemStack itemInHand, Player player) {
        if (state.getBlock() instanceof ISeatBlock seatBlock) {
            if (seatBlock instanceof IHasPrimaryPart<?> part) {
                pos = part.getPrimaryPartPos(state, pos);
            }
            if (level.getBlockEntity(pos) instanceof BaseSeatBlockEntity seat) {
                CompoundTag tag = itemInHand.getOrCreateTag();
                if (seat.hasLockCode()) {
                    if (tag.contains(LOCK_CODE)) {
                        if (Objects.equals(tag.getLong(LOCK_CODE), seat.getLockCode())) {
                            seat.setLockCode(-1);
                            seat.setChanged();
                            player.displayClientMessage(Component.translatable("eroticdungeongame.message.key.success.unlock").withStyle(ChatFormatting.GREEN) ,true);
                            level.playSound( null, pos, EDGSoundEvents.UNLOCKING.get(), SoundSource.BLOCKS);
                            return InteractionResult.SUCCESS;
                        } else {
                            player.displayClientMessage(Component.translatable("eroticdungeongame.message.key.failed.mismatch").withStyle(ChatFormatting.RED) ,true);
                            level.playSound( null, pos, SoundEvents.ITEM_BREAK, SoundSource.BLOCKS);
                            return InteractionResult.FAIL;
                        }
                    } else {
                        player.displayClientMessage(Component.translatable("eroticdungeongame.message.key.failed.mismatch").withStyle(ChatFormatting.RED) ,true);
                    }
                } else {
                    long lockCode = -1;
                    if (tag.contains(LOCK_CODE)) {
                        if (tag.getLong(LOCK_CODE) != -1) {
                            lockCode = tag.getLong(LOCK_CODE);
                        }
                    }
                    if (lockCode == -1) {
                        lockCode = generateLockCode(player);
                        tag.putLong(LOCK_CODE, lockCode);
                    }
                    seat.setLockCode(lockCode);
                    seat.setChanged();
                    player.displayClientMessage(Component.translatable("eroticdungeongame.message.key.success.locked").withStyle(ChatFormatting.GREEN) ,true);
                    level.playSound(null, pos, EDGSoundEvents.LOCKING.get(), SoundSource.BLOCKS);
                    return InteractionResult.SUCCESS;
                }
            }
        }
        return null;
    }
    /**
     * 为ItemStack设置指定密码
     */
    public static void setCode(ItemStack stack, long code) {
        if (!(stack.getItem() instanceof DeviceKeyItem)) {
            throw new IllegalArgumentException("Item must be a DeviceKeyItem");
        }
        stack.getOrCreateTag().putLong(LOCK_CODE, code);
    }

    /**
     * 获取ItemStack的密码
     */
    public static long getCode(ItemStack stack) {
        if (!(stack.getItem() instanceof DeviceKeyItem)) {
            return 0L;
        }
        CompoundTag tag = stack.getTag();
        return tag != null && tag.contains(LOCK_CODE) ? tag.getLong(LOCK_CODE) : 0L;
    }

    /**
     * 清除ItemStack的密码
     */
    public static void clearCode(@NotNull ItemStack stack) {
        if (!(stack.getItem() instanceof DeviceKeyItem)) {
            return;
        }
        CompoundTag tag = stack.getTag();
        if (tag != null && tag.contains(LOCK_CODE)) {
            tag.remove(LOCK_CODE);
            if (tag.isEmpty()) {
                stack.setTag(null);
            }
        }
    }

    /**
     * 检查是否有密码
     */
    public static boolean hasCode(@NotNull ItemStack stack) {
        if (!(stack.getItem() instanceof DeviceKeyItem)) {
            return false;
        }
        CompoundTag tag = stack.getTag();
        return tag != null && tag.contains(LOCK_CODE) && tag.getLong(LOCK_CODE) != 0L;
    }

    /**
     * 匹配密码
     */
    public static boolean isMatch(@NotNull ItemStack stack, long code) {
        return stack.getItem() instanceof DeviceKeyItem && stack.getOrCreateTag().contains(LOCK_CODE) && Objects.equals(stack.getOrCreateTag().getLong(LOCK_CODE), code);
    }

    @Override
    public void appendHoverText(
            @NotNull ItemStack pStack,
            @Nullable Level pLevel,
            @NotNull List<Component> pTooltipComponents,
            @NotNull TooltipFlag pIsAdvanced
    ) {
        CompoundTag tag = pStack.getOrCreateTag();
        boolean isEmpty = tag.isEmpty();
        if (!isEmpty && tag.contains(LOCK_CODE)) {
            long lockCode = tag.getLong(LOCK_CODE);
            MutableComponent component = Component.translatable(
                    "description." + EroticDungeon.MOD_ID + ".key_content"
            );
            Component keyLockComponent = turnLockCodeToComponent(lockCode);
            component.append(keyLockComponent);
            pTooltipComponents.add(Component.translatable("message.eroticdungeongame.dungeon_key_02").withStyle(ChatFormatting.GRAY));
            pTooltipComponents.add(Component.translatable("message.eroticdungeongame.dungeon_key_03").withStyle(ChatFormatting.GRAY));
            pTooltipComponents.add(component);

        }else pTooltipComponents.add(Component.translatable("message.eroticdungeongame.dungeon_key_01").withStyle(ChatFormatting.GRAY));
        super.appendHoverText(pStack, pLevel, pTooltipComponents, pIsAdvanced);
    }
}
