/*
 * Copyright (c) 2026 盐灯水母
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

package com.remains_cave.item.client;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Axis;
import com.remains_cave.client.model.ArrowModelLoader;
import com.remains_cave.item.ModDataComponents;
import com.remains_cave.item.component.QuiverContent;
import com.remains_cave.item.custom.TombQuiverItem;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.alchemy.PotionContents;
import software.bernie.geckolib.cache.object.BakedGeoModel;
import software.bernie.geckolib.cache.object.GeoBone;
import software.bernie.geckolib.cache.object.GeoCube;
import software.bernie.geckolib.model.GeoModel;
import software.bernie.geckolib.renderer.GeoArmorRenderer;

import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class TombQuiverArmorRenderer extends GeoArmorRenderer<TombQuiverItem> {

    public TombQuiverArmorRenderer() {
        super(new TombQuiverModel());
        // 调试：检查 body 骨骼是否存在
        GeoBone body = this.model.getBone("body").orElse(null);
    }

    @Override
    public void renderRecursively(PoseStack poseStack, TombQuiverItem animatable, GeoBone bone,
                                  RenderType renderType, MultiBufferSource bufferSource,
                                  VertexConsumer buffer, boolean isReRender, float partialTick,
                                  int packedLight, int packedOverlay, int packedColor) {
        // 检查骨骼名称是否为 arrow1, arrow2, arrow3
        int slotIndex = -1;
        slotIndex = switch (bone.getName()) {
            case "arrow1" -> 0;
            case "arrow2" -> 1;
            case "arrow3" -> 2;
            default -> slotIndex;
        };

        if (slotIndex != -1 && this.currentStack != null && !this.currentStack.isEmpty()) {
            // 从当前箭袋中读取对应槽位的箭矢
            QuiverContent content = this.currentStack.get(ModDataComponents.QUIVER_CONTENT.get());
            if (content != null) {
                List<ItemStack> arrows = content.arrows();
                if (slotIndex < arrows.size()) {
                    ItemStack arrowStack = arrows.get(slotIndex);
                    if (!arrowStack.isEmpty()) {
                        poseStack.pushPose();
                        // 应用当前骨骼的变换（使箭矢位于正确位置）
                        applyBoneTransform(poseStack, bone);

                        // 加载箭矢模型
                        BakedGeoModel arrowModel = ArrowModelLoader.getArrowModel(arrowStack.getItem());
                        if (arrowModel != null) {
                            // 确定纹理
                            ResourceLocation arrowTexture;
                            if (arrowModel == ArrowModelLoader.getDefaultArrowModel()) {
                                arrowTexture = ResourceLocation.parse("remains_cave:textures/item/arrow/arrow_default.png");
                            } else {
                                arrowTexture = getArrowTexture(arrowStack);
                            }

                            // 获取药水颜色（如果有）
                            int defaultColor = 0xFFFFFFFF;
                            int potionColor = defaultColor;
                            PotionContents potionContents = arrowStack.get(DataComponents.POTION_CONTENTS);
                            if (potionContents != null) {
                                potionColor = potionContents.getColor();
                            }

                            RenderType arrowRenderType = RenderType.entityCutoutNoCull(arrowTexture);
                            VertexConsumer arrowBuffer = bufferSource.getBuffer(arrowRenderType);

                            // 获取箭矢模型的根骨骼并渲染
                            Collection<GeoBone> rootBones = getRootBones(arrowModel);
                            for (GeoBone rootBone : rootBones) {
                                renderBoneTree(poseStack, rootBone, arrowRenderType, arrowTexture, bufferSource, arrowBuffer,
                                        isReRender, partialTick, packedLight, packedOverlay, defaultColor, potionColor);
                            }
                        }

                        poseStack.popPose();
                        // 注意：这里不调用父类的 renderRecursively，因为已经渲染了箭矢
                        return;
                    }
                }
            }
        }

        // 对于其他骨骼或箭矢为空，调用父类继续渲染箭袋本体
        super.renderRecursively(poseStack, animatable, bone, renderType, bufferSource, buffer,
                isReRender, partialTick, packedLight, packedOverlay, packedColor);
    }

    // ---------- 以下为辅助方法，与弓渲染器中的实现一致 ----------

    private void applyBoneTransform(PoseStack poseStack, GeoBone bone) {
        poseStack.translate(bone.getPosX() / 16f, bone.getPosY() / 16f, bone.getPosZ() / 16f);
        poseStack.translate(bone.getPivotX() / 16f, bone.getPivotY() / 16f, bone.getPivotZ() / 16f);
        if (bone.getRotZ() != 0) poseStack.mulPose(Axis.ZP.rotation(bone.getRotZ()));
        if (bone.getRotY() != 0) poseStack.mulPose(Axis.YP.rotation(bone.getRotY()));
        if (bone.getRotX() != 0) poseStack.mulPose(Axis.XP.rotation(bone.getRotX()));
        poseStack.scale(bone.getScaleX(), bone.getScaleY(), bone.getScaleZ());
    }

    private Collection<GeoBone> getRootBones(BakedGeoModel model) {
        try {
            Field field = model.getClass().getDeclaredField("topLevelBones");
            field.setAccessible(true);
            Object value = field.get(model);
            if (value instanceof Collection) {
                return (Collection<GeoBone>) value;
            }
        } catch (Exception ignored) {}
        return Collections.emptyList();
    }

    private void renderBoneTree(PoseStack poseStack, GeoBone bone, RenderType renderType, ResourceLocation texture,
                                MultiBufferSource bufferSource, VertexConsumer buffer,
                                boolean isReRender, float partialTick, int packedLight,
                                int packedOverlay, int defaultColor, int potionColor) {
        poseStack.pushPose();
        applyBoneTransform(poseStack, bone);

        if (!bone.isHidden()) {
            for (GeoCube cube : bone.getCubes()) {
                poseStack.pushPose();

                int colorToUse = bone.getName().equals("arrowhead") ? potionColor : defaultColor;

                // 对光灵箭的发光核心使用自发光渲染
                if (bone.getName().equals("glow_core")) {
                    RenderType glowRenderType = RenderType.entityTranslucentEmissive(texture);
                    VertexConsumer glowBuffer = bufferSource.getBuffer(glowRenderType);
                    renderCube(poseStack, cube, glowBuffer, 0xF000F0, packedOverlay, colorToUse);
                } else {
                    renderCube(poseStack, cube, buffer, packedLight, packedOverlay, colorToUse);
                }

                poseStack.popPose();
            }
        }

        for (GeoBone child : bone.getChildBones()) {
            renderBoneTree(poseStack, child, renderType, texture, bufferSource, buffer,
                    isReRender, partialTick, packedLight, packedOverlay, defaultColor, potionColor);
        }

        poseStack.popPose();
    }

    private ResourceLocation getArrowTexture(ItemStack arrowStack) {
        if (arrowStack.isEmpty()) {
            return ResourceLocation.parse("remains_cave:textures/item/arrow/arrow_default.png");
        }
        ResourceLocation itemId = arrowStack.getItem().builtInRegistryHolder().key().location();
        return ResourceLocation.parse(itemId.getNamespace() + ":textures/item/arrow/" +
                itemId.getNamespace() + "_" + itemId.getPath().replace('/', '_') + ".png");
    }

    // ---------- 以下为原方法，保持不变 ----------

    @Override
    @Nullable
    public GeoBone getHeadBone(GeoModel<TombQuiverItem> model) { return null; }

    @Override
    @Nullable
    public GeoBone getBodyBone(GeoModel<TombQuiverItem> model) {
        return model.getBone("body").orElse(null);
    }

    @Override
    @Nullable
    public GeoBone getRightArmBone(GeoModel<TombQuiverItem> model) { return null; }

    @Override
    @Nullable
    public GeoBone getLeftArmBone(GeoModel<TombQuiverItem> model) { return null; }

    @Override
    @Nullable
    public GeoBone getRightLegBone(GeoModel<TombQuiverItem> model) { return null; }

    @Override
    @Nullable
    public GeoBone getLeftLegBone(GeoModel<TombQuiverItem> model) { return null; }

    @Override
    @Nullable
    public GeoBone getRightBootBone(GeoModel<TombQuiverItem> model) { return null; }

    @Override
    @Nullable
    public GeoBone getLeftBootBone(GeoModel<TombQuiverItem> model) { return null; }

    @Override
    protected void applyBoneVisibilityBySlot(EquipmentSlot currentSlot) {
        setAllBonesVisible(false);
        if (this.body != null) {
            this.body.setHidden(false);
        }
    }
}