/*
 * 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.TombBowItem;
import com.remains_cave.item.custom.TombQuiverItem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
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.item.ItemDisplayContext;
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.renderer.GeoItemRenderer;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class TombQuiverRenderer extends GeoItemRenderer<TombQuiverItem> {
    private ItemStack currentRenderingStack;

    public TombQuiverRenderer() {
        super(new TombQuiverModel());
    }

    @Override
    public void renderByItem(ItemStack stack, ItemDisplayContext transformType,
                             PoseStack poseStack, MultiBufferSource bufferSource,
                             int packedLight, int packedOverlay) {
        this.currentRenderingStack = stack;

        LocalPlayer player = Minecraft.getInstance().player;
        boolean appliedTransform = false;

        // ========== 副手特殊逻辑（优先处理，完成后直接返回）==========
        if (player != null && ItemStack.isSameItemSameComponents(player.getOffhandItem(), stack)) {
            // 拉弓时隐藏副手箭矢（仅在非 GUI 下）
            if (transformType != ItemDisplayContext.GUI && player.isUsingItem()) {
                ItemStack useItem = player.getUseItem();
                if (useItem.getItem() instanceof TombBowItem) {
                    this.currentRenderingStack = null;
                    return;
                }
            }

            // 渲染手中箭矢（第一/三人称副手）
            if (transformType == ItemDisplayContext.THIRD_PERSON_LEFT_HAND ||
                    transformType == ItemDisplayContext.FIRST_PERSON_LEFT_HAND) {
                renderArrowInHand(poseStack, bufferSource, packedLight, packedOverlay, transformType);
                this.currentRenderingStack = null;
                return;
            }
        }

        // ========== 对非副手状态应用自定义变换 ==========
        // 主手（右手）、掉落物、物品展示框等
        if (transformType == ItemDisplayContext.FIRST_PERSON_RIGHT_HAND ||
                transformType == ItemDisplayContext.FIRST_PERSON_LEFT_HAND ||
                transformType == ItemDisplayContext.THIRD_PERSON_RIGHT_HAND ||
                transformType == ItemDisplayContext.GROUND ||
                transformType == ItemDisplayContext.FIXED ||
                transformType == ItemDisplayContext.GUI) {
            poseStack.pushPose();
            appliedTransform = true;

            switch (transformType) {
                case FIRST_PERSON_RIGHT_HAND:
                    // 第一人称右手（主手）变换
                    poseStack.mulPose(Axis.ZP.rotationDegrees(45));
                    poseStack.translate(0.5, -1.75, -0.5);
                    break;
                case FIRST_PERSON_LEFT_HAND:
                    // 第一人称左手变换（移出屏幕
                    poseStack.translate(0.0, 10.0, 0.0);
                    break;
                case THIRD_PERSON_RIGHT_HAND:
                    // 第三人称右手（主手）变换
                    poseStack.mulPose(Axis.ZP.rotationDegrees(45));
                    poseStack.translate(0.1, -1.75, -0.2);
                    break;
                case GROUND:
                    // 掉落物状态
                    poseStack.translate(-0.0, -1.0, -0.25);
                    break;
                case FIXED:
                    // 物品展示框或盔甲架
                    poseStack.mulPose(Axis.ZP.rotationDegrees(90));
                    poseStack.translate(-0.125, -2.25, -0.2);
                    break;
                case GUI:
                    // GUI 内显示
                    poseStack.translate(-0.1, -1.25, 0);
                    break;
                default:
                    break;
            }
        }

        // 正常渲染箭袋本体（会触发 renderRecursively）
        super.renderByItem(stack, transformType, poseStack, bufferSource, packedLight, packedOverlay);

        // 恢复变换（如果有）
        if (appliedTransform) {
            poseStack.popPose();
        }

        this.currentRenderingStack = 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) {
        // 检查骨骼是否为箭槽，并尝试渲染对应箭矢
        if (currentRenderingStack != null && !currentRenderingStack.isEmpty()) {
            int slotIndex = -1;
            slotIndex = switch (bone.getName()) {
                case "arrow1" -> 0;
                case "arrow2" -> 1;
                case "arrow3" -> 2;
                default -> slotIndex;
            };

            if (slotIndex != -1) {
                // 从当前箭袋中获取对应槽位的箭矢
                QuiverContent content = currentRenderingStack.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 renderArrowInHand(PoseStack poseStack, MultiBufferSource bufferSource,
                                   int packedLight, int packedOverlay,
                                   ItemDisplayContext transformType) {
        LocalPlayer player = Minecraft.getInstance().player;
        if (player == null) return;
        ItemStack quiverStack = player.getOffhandItem();
        if (!(quiverStack.getItem() instanceof TombQuiverItem)) return;

        QuiverContent content = quiverStack.get(ModDataComponents.QUIVER_CONTENT.get());
        if (content == null) return;
        List<ItemStack> arrows = content.arrows();
        if (arrows.isEmpty()) return;

        // 寻找第一个非空箭矢（优先第一格，其次第二格，最后第三格）
        ItemStack arrowStack = ItemStack.EMPTY;
        for (ItemStack arrow : arrows) {
            if (!arrow.isEmpty()) {
                arrowStack = arrow;
                break;
            }
        }
        if (arrowStack.isEmpty()) return;

        BakedGeoModel arrowModel = ArrowModelLoader.getArrowModel(arrowStack.getItem());
        if (arrowModel == null) return;

        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);

        // 根据视角应用不同变换（请根据实际效果微调）
        poseStack.pushPose();

        if (transformType == ItemDisplayContext.FIRST_PERSON_LEFT_HAND) {
            // 第一人称左手（副手）位置
            poseStack.mulPose(Axis.XP.rotationDegrees(180));
            poseStack.mulPose(Axis.YP.rotationDegrees(45));
            poseStack.translate(-0, 0.0, -0.1);
        } else if (transformType == ItemDisplayContext.THIRD_PERSON_LEFT_HAND) {
            // 第三人称左手（副手）位置
            poseStack.mulPose(Axis.XP.rotationDegrees(180));
            poseStack.mulPose(Axis.YP.rotationDegrees(0));
            poseStack.translate(0.5, -0.125, -0.55);
        }

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

    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());
    }

    @SuppressWarnings("unchecked")
    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");
    }
}