/*
 *  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.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.server.level.ServerPlayer;
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.level.Level;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import top.r3944realms.eroticdungeongame.core.register.EDGItems;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 过滤器物品
 * 支持白名单/黑名单模式、游戏模式过滤、标签过滤、队伍过滤和工作坐标点
 */
public class FilterItem extends Item {

    // NBT 键名常量
    private static final String TAG_FILTER_MODE = "FilterMode";
    private static final String TAG_GAME_MODES = "GameModes";
    private static final String TAG_TAGS = "Tags";
    private static final String TAG_TEAMS = "Teams";
    private static final String TAG_WORK_POS = "WorkPos";
    private static final String TAG_WORK_DIMENSION = "WorkDimension";
    private static final String TAG_WHITELIST_PLAYERS = "WhitelistPlayers";
    private static final String TAG_BLACKLIST_PLAYERS = "BlacklistPlayers";


    public enum FilterMode {
        WHITELIST("whitelist"),  // 白名单模式：只有符合条件的才允许
        BLACKLIST("blacklist");  // 黑名单模式：符合条件的被禁止

        private final String name;

        FilterMode(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public static FilterMode fromName(String name) {
            for (FilterMode mode : values()) {
                if (mode.name.equals(name)) {
                    return mode;
                }
            }
            return WHITELIST; // 默认白名单
        }
    }

    public enum GameMode {
        SURVIVAL("survival"),
        CREATIVE("creative"),
        ADVENTURE("adventure"),
        SPECTATOR("spectator");

        private final String name;

        GameMode(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }

    public FilterItem(Properties properties) {
        super(properties);
    }

    /**
     * 初始化过滤器数据
     */
    public static @NotNull ItemStack createFilter(@NotNull FilterMode mode) {
        ItemStack stack = new ItemStack(EDGItems.FILTER.get());
        CompoundTag tag = stack.getOrCreateTag();
        tag.putString(TAG_FILTER_MODE, mode.getName());
        tag.put(TAG_GAME_MODES, new ListTag());
        tag.put(TAG_TAGS, new ListTag());
        tag.put(TAG_TEAMS, new ListTag());
        tag.put(TAG_WHITELIST_PLAYERS, new ListTag());
        tag.put(TAG_BLACKLIST_PLAYERS, new ListTag());
        return stack;
    }

    // ==================== 设置方法 ====================

    /**
     * 设置过滤器模式
     */
    public static void setFilterMode(@NotNull ItemStack stack, @NotNull FilterMode mode) {
        stack.getOrCreateTag().putString(TAG_FILTER_MODE, mode.getName());
    }

    /**
     * 添加游戏模式过滤
     */
    public static void addGameMode(@NotNull ItemStack stack, @NotNull GameMode mode) {
        CompoundTag tag = stack.getOrCreateTag();
        ListTag list = tag.getList(TAG_GAME_MODES, 8); // 8 是 String 的 ID
        if (isNotContains(list, mode.getName())) {
            list.add(StringTag.valueOf(mode.getName()));
            tag.put(TAG_GAME_MODES, list);
        }
    }

    /**
     * 移除游戏模式过滤
     */
    public static void removeGameMode(@NotNull ItemStack stack, GameMode mode) {
        CompoundTag tag = stack.getOrCreateTag();
        ListTag list = tag.getList(TAG_GAME_MODES, 8);
        list.removeIf(t -> t.getAsString().equals(mode.getName()));
        tag.put(TAG_GAME_MODES, list);
    }

    /**
     * 添加标签
     */
    public static void addTag(@NotNull ItemStack stack, String tag) {
        CompoundTag nbt = stack.getOrCreateTag();
        ListTag list = nbt.getList(TAG_TAGS, 8);
        if (isNotContains(list, tag)) {
            list.add(StringTag.valueOf(tag));
            nbt.put(TAG_TAGS, list);
        }
    }

    /**
     * 添加队伍
     */
    public static void addTeam(@NotNull ItemStack stack, String team) {
        CompoundTag nbt = stack.getOrCreateTag();
        ListTag list = nbt.getList(TAG_TEAMS, 8);
        if (isNotContains(list, team)) {
            list.add(StringTag.valueOf(team));
            nbt.put(TAG_TEAMS, list);
        }
    }

    /**
     * 设置工作坐标点
     */
    public static void setWorkPosition(@NotNull ItemStack stack, @NotNull BlockPos pos, String dimension) {
        CompoundTag tag = stack.getOrCreateTag();
        CompoundTag posTag = new CompoundTag();
        posTag.putInt("x", pos.getX());
        posTag.putInt("y", pos.getY());
        posTag.putInt("z", pos.getZ());
        tag.put(TAG_WORK_POS, posTag);
        tag.putString(TAG_WORK_DIMENSION, dimension);
    }

    public static void removeWorkPosition(@NotNull ItemStack stack) {
        CompoundTag tag = stack.getOrCreateTag();
        tag.remove(TAG_WORK_POS);
        tag.remove(TAG_WORK_DIMENSION);
    }

    /**
     * 添加白名单玩家
     */
    public static void addWhitelistPlayer(ItemStack stack, String playerUUID) {
        addToStringList(stack, TAG_WHITELIST_PLAYERS, playerUUID);
    }

    /**
     * 添加黑名单玩家
     */
    public static void addBlacklistPlayer(ItemStack stack, String playerUUID) {
        addToStringList(stack, TAG_BLACKLIST_PLAYERS, playerUUID);
    }

    /**
     * 移除白名单玩家
     */
    public static void removeWhitelistPlayer(ItemStack stack, String playerUUID) {
        removeFromStringList(stack, TAG_WHITELIST_PLAYERS, playerUUID);
    }

    /**
     * 移除黑名单玩家
     */
    public static void removeBlacklistPlayer(ItemStack stack, String playerUUID) {
        removeFromStringList(stack, TAG_BLACKLIST_PLAYERS, playerUUID);
    }

    // ==================== 读取方法 ====================

    /**
     * 获取过滤器模式
     */
    public static FilterMode getFilterMode(@NotNull ItemStack stack) {
        CompoundTag tag = stack.getTag();
        if (tag != null && tag.contains(TAG_FILTER_MODE)) {
            return FilterMode.fromName(tag.getString(TAG_FILTER_MODE));
        }
        return FilterMode.WHITELIST; // 默认白名单
    }

    /**
     * 获取游戏模式列表
     */
    public static @NotNull Set<GameMode> getGameModes(@NotNull ItemStack stack) {
        Set<GameMode> modes = new HashSet<>();
        CompoundTag tag = stack.getTag();
        if (tag != null && tag.contains(TAG_GAME_MODES)) {
            ListTag list = tag.getList(TAG_GAME_MODES, 8);
            for (int i = 0; i < list.size(); i++) {
                String modeName = list.getString(i);
                for (GameMode mode : GameMode.values()) {
                    if (mode.getName().equals(modeName)) {
                        modes.add(mode);
                        break;
                    }
                }
            }
        }
        return modes;
    }

    /**
     * 获取标签列表
     */
    public static @NotNull Set<String> getTags(ItemStack stack) {
        return getStringSet(stack, TAG_TAGS);
    }

    /**
     * 获取队伍列表
     */
    public static @NotNull Set<String> getTeams(ItemStack stack) {
        return getStringSet(stack, TAG_TEAMS);
    }

    /**
     * 获取工作坐标点
     */
    @Nullable
    public static BlockPos getWorkPosition(@NotNull ItemStack stack) {
        CompoundTag tag = stack.getTag();
        if (tag != null && tag.contains(TAG_WORK_POS)) {
            CompoundTag posTag = tag.getCompound(TAG_WORK_POS);
            return new BlockPos(
                    posTag.getInt("x"),
                    posTag.getInt("y"),
                    posTag.getInt("z")
            );
        }
        return null;
    }

    /**
     * 获取工作维度
     */
    @Nullable
    public static String getWorkDimension(@NotNull ItemStack stack) {
        CompoundTag tag = stack.getTag();
        if (tag != null && tag.contains(TAG_WORK_DIMENSION)) {
            return tag.getString(TAG_WORK_DIMENSION);
        }
        return null;
    }

    /**
     * 获取白名单玩家列表
     */
    public static @NotNull Set<String> getWhitelistPlayers(ItemStack stack) {
        return getStringSet(stack, TAG_WHITELIST_PLAYERS);
    }

    /**
     * 获取黑名单玩家列表
     */
    public static @NotNull Set<String> getBlacklistPlayers(ItemStack stack) {
        return getStringSet(stack, TAG_BLACKLIST_PLAYERS);
    }

    // ==================== 检查方法 ====================

    /**
     * 检查玩家是否被允许使用
     */
    public static boolean isPlayerAllowed(ItemStack stack, @NotNull ServerPlayer player) {
        FilterMode mode = getFilterMode(stack);
        String playerUUID = player.getUUID().toString();

        // 检查玩家名单
        Set<String> whitelist = getWhitelistPlayers(stack);
        Set<String> blacklist = getBlacklistPlayers(stack);

        boolean inWhitelist = whitelist.contains(playerUUID);
        boolean inBlacklist = blacklist.contains(playerUUID);

        // 黑名单模式：在黑名单中的禁止
        if (mode == FilterMode.BLACKLIST && inBlacklist) {
            return false;
        }

        // 白名单模式：不在白名单中的禁止（如果白名单不为空）
        if (mode == FilterMode.WHITELIST && !whitelist.isEmpty() && !inWhitelist) {
            return false;
        }

        // 检查游戏模式
        Set<GameMode> allowedModes = getGameModes(stack);
        if (!allowedModes.isEmpty()) {
            GameMode playerMode = getPlayerGameMode(player);
            if (!allowedModes.contains(playerMode)) {
                return false;
            }
        }

        // 检查标签
        Set<String> requiredTags = getTags(stack);
        if (!requiredTags.isEmpty()) {
            // 这里需要根据你的标签系统来实现
            if (!hasRequiredTags(player, requiredTags)) {
                return false;
            }
        }

        // 检查队伍
        Set<String> allowedTeams = getTeams(stack);
        if (!allowedTeams.isEmpty()) {
            String playerTeam = getPlayerTeam(player);
            return playerTeam != null && allowedTeams.contains(playerTeam);
        }

        return true;
    }

    /**
     * 检查坐标是否在工作点附近
     */
    public static boolean isNearWorkPosition(ItemStack stack, BlockPos pos, int radius) {
        BlockPos workPos = getWorkPosition(stack);
        if (workPos == null) return true; // 没有设置工作点则通过

        return workPos.distSqr(pos) <= radius * radius;
    }

    // ==================== 辅助方法 ====================

    private static boolean isNotContains(@NotNull ListTag list, String value) {
        for (int i = 0; i < list.size(); i++) {
            if (list.getString(i).equals(value)) {
                return false;
            }
        }
        return true;
    }

    private static void addToStringList(@NotNull ItemStack stack, String key, String value) {
        CompoundTag tag = stack.getOrCreateTag();
        ListTag list = tag.getList(key, 8);
        if (isNotContains(list, value)) {
            list.add(StringTag.valueOf(value));
            tag.put(key, list);
        }
    }

    private static void removeFromStringList(@NotNull ItemStack stack, String key, String value) {
        CompoundTag tag = stack.getOrCreateTag();
        if (tag.contains(key)) {
            ListTag list = tag.getList(key, 8);
            list.removeIf(t -> t.getAsString().equals(value));
            if (list.isEmpty()) {
                tag.remove(key);
            } else {
                tag.put(key, list);
            }
        }
    }

    private static @NotNull Set<String> getStringSet(@NotNull ItemStack stack, String key) {
        Set<String> set = new HashSet<>();
        CompoundTag tag = stack.getTag();
        if (tag != null && tag.contains(key)) {
            ListTag list = tag.getList(key, 8);
            for (int i = 0; i < list.size(); i++) {
                set.add(list.getString(i));
            }
        }
        return set;
    }


    public static GameMode getPlayerGameMode(@NotNull ServerPlayer player) {
        return switch (player.gameMode.getGameModeForPlayer()) {
            case SURVIVAL -> GameMode.SURVIVAL;
            case CREATIVE -> GameMode.CREATIVE;
            case ADVENTURE -> GameMode.ADVENTURE;
            case SPECTATOR -> GameMode.SPECTATOR;
        };
    }

    private static boolean hasRequiredTags(Player player, @NotNull Set<String> requiredTags) {
        for (String requiredTag : requiredTags) {
            if (!player.getTags().contains(requiredTag)) {
                return false;
            }
        }
        return true;
    }

    @Nullable
    private static String getPlayerTeam(@NotNull Player player) {
        // 实现获取玩家队伍的方法
        if (player.getTeam() != null) {
            return player.getTeam().getName();
        }
        return null;
    }

    @Override
    public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level, @NotNull List<Component> tooltip, @NotNull TooltipFlag flag) {
        super.appendHoverText(stack, level, tooltip, flag);

        FilterMode mode = getFilterMode(stack);
        // 模式: 白名单/黑名单
        String modeKey = mode == FilterMode.WHITELIST ? "whitelist" : "blacklist";
        tooltip.add(Component.translatable("tooltip.eroticdungeongame.filter.mode",
                Component.translatable("filter.eroticdungeongame.mode." + modeKey)));

        Set<GameMode> gameModes = getGameModes(stack);
        if (!gameModes.isEmpty()) {
            // 游戏模式列表
            List<MutableComponent> modeComponents = gameModes.stream()
                    .map(gm -> Component.translatable("tooltip.eroticdungeongame.filter.gamemodes", gm.getName()))
                    .toList();
            tooltip.add(Component.translatable("tooltip.eroticdungeongame.filter.gamemodes",
                    Component.literal(formatList(modeComponents))));
        }

        Set<String> tags = getTags(stack);
        if (!tags.isEmpty()) {
            // 标签列表
            tooltip.add(Component.translatable("tooltip.eroticdungeongame.filter.tags",
                    Component.literal(String.join(", ", tags))));
        }

        Set<String> teams = getTeams(stack);
        if (!teams.isEmpty()) {
            // 队伍列表
            tooltip.add(Component.translatable("tooltip.eroticdungeongame.filter.teams",
                    Component.literal(String.join(", ", teams))));
        }

        BlockPos workPos = getWorkPosition(stack);
        if (workPos != null) {
            String dim = getWorkDimension(stack);
            // 工作点坐标
            String dimKey = dim != null ? dim.replace(":", ".") : "unknown";
            tooltip.add(Component.translatable("tooltip.eroticdungeongame.filter.workpos",
                    workPos.getX(), workPos.getY(), workPos.getZ(),
                    Component.translatable("dimension." + dimKey)));
        }

        Set<String> whitelist = getWhitelistPlayers(stack);
        if (!whitelist.isEmpty()) {
            // 白名单玩家数量
            tooltip.add(Component.translatable("tooltip.eroticdungeongame.filter.whitelist", whitelist.size()));

            if (flag.isAdvanced()) {
                // 高级提示中显示具体玩家UUID
                whitelist.forEach(uuid ->
                        tooltip.add(Component.literal("  §7- §f" + uuid)));
            }
        }

        Set<String> blacklist = getBlacklistPlayers(stack);
        if (!blacklist.isEmpty()) {
            // 黑名单玩家数量
            tooltip.add(Component.translatable("tooltip.eroticdungeongame.filter.blacklist", blacklist.size()));

            if (flag.isAdvanced()) {
                // 高级提示中显示具体玩家UUID
                blacklist.forEach(uuid ->
                        tooltip.add(Component.literal("  §7- §f" + uuid)));
            }
        }
    }

    /**
     * 格式化列表显示
     */
    private String formatList(List<MutableComponent> components) {
        return components.stream()
                .map(Component::getString)
                .collect(java.util.stream.Collectors.joining(", "));
    }
}