package top.r3944realms.lib39.util;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.player.PlayerModelType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.ResolvableProfile;
import net.minecraft.world.level.block.entity.SkullBlockEntity;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NonNull;
import top.r3944realms.lib39.Lib39;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * The type GameProfile helper.
 */
public class GameProfileHelper {
    /**
     * 获取 GameProfile（通过玩家名）
     */
    @Contract("_ -> new")
    public static @NonNull ResolvableProfile fetchGameProfileByName(String name) {
        return ResolvableProfile.createUnresolved(name);
    }

    /**
     * 获取 GameProfile（通过 UUID）
     * 直接复用 SkullBlockEntity 的实现
     */
    @Contract("_ -> new")
    public static @NonNull ResolvableProfile fetchGameProfileByUUID(UUID uuid) {
        return ResolvableProfile.createUnresolved(uuid);
    }

    /**
     * 获取 GameProfile（自动识别类型）
     */
    @SuppressWarnings("unchecked")
    public static <T> ResolvableProfile fetchGameProfile(T identifier) {
        if (identifier instanceof UUID uuid) {
            return fetchGameProfileByUUID(uuid);
        } else if (identifier instanceof String name) {
            return fetchGameProfileByName(name);
        } else if (identifier instanceof GameProfile gameProfile) {
            return ResolvableProfile.createResolved(gameProfile);
        }
        throw new IllegalArgumentException("Identifier type not supported: " + identifier.getClass());
    }

    /**
     * 从 ItemStack 获取完整的 ResolvableProfile
     */
    public static ResolvableProfile fetchProfileFromItemStack(@NotNull ItemStack stack) {
        ResolvableProfile resolvable = stack.get(DataComponents.PROFILE);
        if (resolvable == null) {
            return ResolvableProfile.Static.EMPTY;
        }
        return resolvable;
    }
    /**
     * Client Only Class
     */
    public static class ClientOpt implements IClientOnly {
        /**
         * Resolve skin texture resource location.
         *
         * @param gameProfile the game profile
         * @return the resource location
         */
        public static @NotNull Identifier resolveSkinTexture(@NotNull GameProfile gameProfile) {
            return IClientOnly.check(() ->
                    Minecraft.getInstance().getSkinManager()
                    .createLookup(gameProfile, true)).get().body().texturePath();
        }

        /**
         * Gets skin texture.
         *
         * @param gameProfile the game profile
         * @return the skin texture
         */
        public static Identifier getSkinTexture(@Nullable GameProfile gameProfile) {
            return IClientOnly.check(() -> {
                if (gameProfile == null) {
                    return Lib39.mrl("textures/entity/player/wide/steve.png");
                }
                return resolveSkinTexture(gameProfile);
            });
        }

        /**
         * Has slim arms client boolean.
         *
         * @param player the player
         * @return the boolean
         */
        public static boolean hasSlimArmsClient(Player player) {
            return IClientOnly.check(() -> {
                if (player instanceof AbstractClientPlayer clientPlayer) {
                    PlayerInfo playerInfo = Objects.requireNonNull(Minecraft.getInstance()
                                    .getConnection())
                            .getPlayerInfo(clientPlayer.getUUID());
                    return playerInfo != null && PlayerModelType.SLIM.equals(playerInfo.getSkin().model());
                }
                return false;
            });
        }

        /**
         * Gets skin model name.
         *
         * @param player the player
         * @return the skin model name
         */
        public static @NotNull String getSkinModelName(@NotNull Player player) {
            return IClientOnly.check(() -> {
                if (player.level().isClientSide() && player instanceof AbstractClientPlayer) {
                    PlayerInfo info = Objects.requireNonNull(Minecraft.getInstance().getConnection())
                            .getPlayerInfo(player.getUUID());
                    return info != null ? info.getSkin().model().name() : PlayerModelType.WIDE.name();
                }
                return PlayerModelType.WIDE.name();
            });
        }

    }

    /**
     * The constant TAG_OWN_PROFILE.
     */
    public static final String TAG_OWN_PROFILE = "OwnerProfile";

    /**
     * Gets skin texture.
     *
     * @param gameProfile the game profile
     * @return the skin texture
     */
    public static Identifier getSkinTexture(@Nullable GameProfile gameProfile) {
        return ClientOpt.getSkinTexture(gameProfile);
    }


    /**
     * Resolve skin texture resource location.
     *
     * @param gameProfile the game profile
     * @return the resource location
     */
    public static @NotNull Identifier resolveSkinTexture(@NotNull GameProfile gameProfile) {
        return ClientOpt.resolveSkinTexture(gameProfile);
    }

    /**
     * Has slim arms boolean.
     *
     * @param player the player
     * @return the boolean
     */
    public static boolean hasSlimArms(@NotNull Player player) {
        if (player.level().isClientSide()) {
            return hasSlimArmsClient(player);
        } else {
            return hasSlimArmsServer(player);
        }
    }


    private static boolean hasSlimArmsClient(Player player) {
        return ClientOpt.hasSlimArmsClient(player);
    }

    // 服务器端判断
    private static boolean hasSlimArmsServer(@NotNull Player player) {
        GameProfile profile = player.getGameProfile();
        for (Property property : profile.properties().get("textures")) {
            try {
                String json = new String(Base64.getDecoder().decode(property.value()));
                JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
                JsonObject textures = obj.getAsJsonObject("textures");
                JsonObject skin = textures.getAsJsonObject("SKIN");

                if (skin.has("metadata")) {
                    JsonObject metadata = skin.getAsJsonObject("metadata");
                    if (metadata.has("model")) {
                        return "slim".equals(metadata.get("model").getAsString());
                    }
                }
            } catch (Exception e) {
                // 解析失败，使用默认
            }
        }
        return false;
    }

    /**
     * Gets skin model name.
     *
     * @param player the player
     * @return the skin model name
     */
    public static @NotNull String getSkinModelName(@NotNull Player player) {
        return ClientOpt.getSkinModelName(player);
    }

    /**
     * 判断玩家是否为纤细手臂（Alex模型）
     *
     * @param profile 玩家的GameProfile
     * @return true =纤细手臂，false=正常手臂
     */
    public static boolean isSlimArms(GameProfile profile) {
        if (profile == null) {
            return false;
        }

        // 获取textures属性
        Collection<Property> textures = profile.properties().get("textures");
        if (textures.isEmpty()) {
            return false; // 没有皮肤数据，使用默认
        }

        // 获取第一个texture属性（通常是皮肤）
        Property textureProperty = textures.iterator().next();
        String value = textureProperty.value();

        try {
            return isSlimFromTextureData(value);
        } catch (Exception e) {
            // 解析失败，使用默认
            return false;
        }
    }

    /**
     * 从Base64编码的皮肤数据判断
     * @param encodedTexture Base64编码的皮肤数据
     * @return true=纤细手臂
     */
    private static boolean isSlimFromTextureData(String encodedTexture) {
        if (encodedTexture == null || encodedTexture.isEmpty()) {
            return false;
        }

        try {
            // 1. Base64解码
            byte[] decodedBytes = Base64.getDecoder().decode(encodedTexture);
            String jsonString = new String(decodedBytes, StandardCharsets.UTF_8);

            // 2. 解析JSON
            JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject();

            // 3. 导航到textures -> SKIN
            JsonObject textures = root.getAsJsonObject("textures");
            if (textures == null) {
                return false;
            }

            JsonObject skin = textures.getAsJsonObject("SKIN");
            if (skin == null) {
                return false;
            }

            // 4. 检查metadata -> model
            JsonObject metadata = skin.getAsJsonObject("metadata");
            if (metadata == null) {
                return false; // 没有metadata，使用默认
            }

            String model = metadata.get("model").getAsString();
            return "slim".equals(model);

        } catch (Exception e) {
            // 解析过程中出现任何错误，返回默认值
            return false;
        }
    }

    /**
     * 获取皮肤模型名称
     *
     * @param profile GameProfile
     * @return "slim" 或 "default"
     */
    public static String getSkinModelName(GameProfile profile) {
        if (profile == null) {
            return "default";
        }

        Collection<Property> textures = profile.properties().get("textures");
        if (textures.isEmpty()) {
            return "default";
        }

        Property textureProperty = textures.iterator().next();
        String value = textureProperty.value();

        try {
            byte[] decodedBytes = Base64.getDecoder().decode(value);
            String jsonString = new String(decodedBytes, StandardCharsets.UTF_8);
            JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject();
            JsonObject texturesObj = root.getAsJsonObject("textures");
            JsonObject skin = texturesObj.getAsJsonObject("SKIN");

            if (skin.has("metadata")) {
                JsonObject metadata = skin.getAsJsonObject("metadata");
                if (metadata.has("model")) {
                    return metadata.get("model").getAsString();
                }
            }
        } catch (Exception e) {
            // 忽略错误
        }

        return "default";
    }

    /**
     * 从ItemStack的组件中读取GameProfile
     *
     * @param stack the stack
     * @return the profile from item stack
     */
    @Nullable
    public static ResolvableProfile getProfileFromItemStack(@NotNull ItemStack stack) {
        if (stack.isEmpty()) {
            return null;
        }

        if (stack.isEmpty()) return null;

        ResolvableProfile profile = stack.get(DataComponents.PROFILE);
        return profile != null ? profile : null;
    }

    /**
     * 将GameProfile保存到ItemStack的组件
     *
     * @param stack   the stack
     * @param profile the profile
     */
    public static void saveProfileToItemStack(@NotNull ItemStack stack, @Nullable ResolvableProfile profile) {
        if (stack.isEmpty()) return;

        if (profile == null) {
            stack.remove(DataComponents.PROFILE);
        } else {
            stack.set(DataComponents.PROFILE, profile);
        }
    }

    /**
     * 检查ItemStack是否有保存的皮肤数据
     *
     * @param stack the stack
     * @return the boolean
     */
    public static boolean hasProfileData(@NotNull ItemStack stack) {
        if (stack.isEmpty()) {
            return false;
        }

        return !stack.isEmpty() && stack.has(DataComponents.PROFILE);
    }

}

