package com.tiedup.remake.client.gui.widgets;

import com.mojang.blaze3d.systems.RenderSystem;
import com.tiedup.remake.client.gui.util.GuiColors;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.narration.NarratedElementType;
import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.client.gui.screens.inventory.InventoryScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.LivingEntity;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Quaternionf;

/**
 * Widget that displays a 3D preview of a LivingEntity.
 * Supports mouse drag rotation and optional auto-rotation.
 *
 */
@OnlyIn(Dist.CLIENT)
public class EntityPreviewWidget extends AbstractWidget {

    private LivingEntity entity;
    private float rotationY = 0;
    private float rotationX = 0;
    private boolean isDragging = false;
    private double lastMouseX, lastMouseY;

    // Auto-rotation
    private boolean autoRotate = false;
    private float autoRotateSpeed = 0.5f;

    // Zoom target (for per-tab camera zoom)
    private float targetScale = 1.0f;
    private float targetOffsetY = 0.0f;
    private float currentScale = 1.0f;
    private float currentOffsetY = 0.0f;
    private static final float LERP_SPEED = 0.35f; // ~300ms to settle

    // Visual settings
    private boolean drawBackground = true;
    private int backgroundColor = GuiColors.BG_DARK;
    private boolean drawBorder = true;
    private int borderColor = GuiColors.BORDER_LIGHT;

    /**
     * Create a new entity preview widget.
     *
     * @param x X position
     * @param y Y position
     * @param width Widget width
     * @param height Widget height
     * @param entity Entity to display
     */
    public EntityPreviewWidget(
        int x,
        int y,
        int width,
        int height,
        LivingEntity entity
    ) {
        super(x, y, width, height, Component.empty());
        this.entity = entity;
    }

    /**
     * Set the entity to display.
     */
    public void setEntity(LivingEntity entity) {
        this.entity = entity;
    }

    /**
     * Get the current entity.
     */
    public LivingEntity getEntity() {
        return entity;
    }

    /**
     * Enable/disable auto-rotation.
     */
    public void setAutoRotate(boolean autoRotate) {
        this.autoRotate = autoRotate;
    }

    /**
     * Set auto-rotation speed (degrees per frame).
     */
    public void setAutoRotateSpeed(float speed) {
        this.autoRotateSpeed = speed;
    }

    /**
     * Enable/disable background drawing.
     */
    public void setDrawBackground(boolean drawBackground) {
        this.drawBackground = drawBackground;
    }

    /**
     * Set background color.
     */
    public void setBackgroundColor(int color) {
        this.backgroundColor = color;
    }

    /**
     * Enable/disable border drawing.
     */
    public void setDrawBorder(boolean drawBorder) {
        this.drawBorder = drawBorder;
    }

    /**
     * Set rotation angles directly.
     */
    public void setRotation(float yaw, float pitch) {
        this.rotationY = yaw;
        this.rotationX = Mth.clamp(pitch, -30, 30);
    }

    /**
     * Reset rotation to default (facing forward).
     */
    public void resetRotation() {
        this.rotationY = 0;
        this.rotationX = 0;
    }

    /**
     * Refresh the preview (call after entity equipment changes).
     */
    public void refresh() {
        // The entity's equipment is read directly during render,
        // so no special action needed here. This method exists
        // for API consistency.
    }

    /**
     * Set the zoom target for animated transition.
     * @param scale Scale multiplier (1.0 = full body, 1.8 = face zoom)
     * @param offsetY Vertical offset (-0.6 = look up at head, +0.4 = look down at legs)
     */
    public void setZoomTarget(float scale, float offsetY) {
        this.targetScale = scale;
        this.targetOffsetY = offsetY;
    }

    /**
     * Tick the zoom lerp animation. Call each frame from the parent screen.
     */
    public void tickZoom() {
        currentScale += (targetScale - currentScale) * LERP_SPEED;
        currentOffsetY += (targetOffsetY - currentOffsetY) * LERP_SPEED;
    }

    @Override
    protected void renderWidget(
        GuiGraphics graphics,
        int mouseX,
        int mouseY,
        float partialTick
    ) {
        if (entity == null) {
            return;
        }

        // Auto-rotation
        if (autoRotate && !isDragging) {
            rotationY += autoRotateSpeed;
        }

        // Background
        if (drawBackground) {
            graphics.fill(
                getX(),
                getY(),
                getX() + width,
                getY() + height,
                backgroundColor
            );
        }

        // Border
        if (drawBorder) {
            // Top
            graphics.fill(
                getX(),
                getY(),
                getX() + width,
                getY() + 1,
                borderColor
            );
            // Bottom
            graphics.fill(
                getX(),
                getY() + height - 1,
                getX() + width,
                getY() + height,
                borderColor
            );
            // Left
            graphics.fill(
                getX(),
                getY(),
                getX() + 1,
                getY() + height,
                borderColor
            );
            // Right
            graphics.fill(
                getX() + width - 1,
                getY(),
                getX() + width,
                getY() + height,
                borderColor
            );
        }

        // Calculate entity render position — feet at widget bottom, fill height
        int centerX = getX() + width / 2;
        int entityScale = (int) (height / 1.95f);
        int centerY = getY() + height - 4;

        // Enable scissor to clip entity to widget bounds
        RenderSystem.enableScissor(
            (int) (getX() * minecraft.getWindow().getGuiScale()),
            (int) ((minecraft.getWindow().getGuiScaledHeight() -
                    getY() -
                    height) *
                minecraft.getWindow().getGuiScale()),
            (int) (width * minecraft.getWindow().getGuiScale()),
            (int) (height * minecraft.getWindow().getGuiScale())
        );

        // Save original entity rotations
        float origBodyRot = entity.yBodyRot;
        float origHeadRot = entity.yHeadRot;
        float origYRot = entity.getYRot();
        float origXRot = entity.getXRot();
        float origYHeadRotO = entity.yHeadRotO;
        float origYBodyRotO = entity.yBodyRotO;
        float origXRotO = entity.xRotO;

        // Set neutral pose (facing forward, not looking up/down)
        entity.yBodyRot = 180f + rotationY; // Face the camera + user rotation
        entity.yHeadRot = 180f + rotationY; // Head same as body
        entity.setYRot(180f + rotationY);
        entity.setXRot(rotationX); // User-controlled pitch
        entity.yHeadRotO = entity.yHeadRot;
        entity.yBodyRotO = entity.yBodyRot;
        entity.xRotO = entity.getXRot(); // Prevent pitch interpolation

        // Render entity using renderEntityInInventory with Quaternionf
        // X rotation flips upright, Y rotation faces camera
        Quaternionf poseRotation = new Quaternionf()
            .rotationX((float) Math.PI) // Flip upright
            .rotateY((float) Math.PI); // Face camera
        Quaternionf cameraRotation = new Quaternionf();

        InventoryScreen.renderEntityInInventory(
            graphics,
            centerX,
            centerY,
            entityScale,
            poseRotation,
            cameraRotation,
            entity
        );

        // Restore original rotations
        entity.yBodyRot = origBodyRot;
        entity.yHeadRot = origHeadRot;
        entity.setYRot(origYRot);
        entity.setXRot(origXRot);
        entity.yHeadRotO = origYHeadRotO;
        entity.yBodyRotO = origYBodyRotO;
        entity.xRotO = origXRotO;

        RenderSystem.disableScissor();
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (isMouseOver(mouseX, mouseY) && button == 0) {
            isDragging = true;
            lastMouseX = mouseX;
            lastMouseY = mouseY;
            return true;
        }
        return false;
    }

    @Override
    public boolean mouseReleased(double mouseX, double mouseY, int button) {
        if (button == 0) {
            isDragging = false;
        }
        return super.mouseReleased(mouseX, mouseY, button);
    }

    @Override
    public boolean mouseDragged(
        double mouseX,
        double mouseY,
        int button,
        double dragX,
        double dragY
    ) {
        if (isDragging && button == 0) {
            rotationY += (float) (mouseX - lastMouseX) * 0.8f;
            rotationX = Mth.clamp(
                rotationX + (float) (mouseY - lastMouseY) * 0.5f,
                -30,
                30
            );
            lastMouseX = mouseX;
            lastMouseY = mouseY;
            return true;
        }
        return false;
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
        if (isMouseOver(mouseX, mouseY)) {
            // Could be used for zoom in the future
            return true;
        }
        return false;
    }

    @Override
    protected void updateWidgetNarration(NarrationElementOutput output) {
        // Narration for accessibility
        if (entity != null) {
            output.add(
                NarratedElementType.TITLE,
                Component.translatable("gui.tiedup.preview", entity.getName())
            );
        }
    }

    /**
     * Get the current Minecraft instance (from AbstractWidget).
     */
    private net.minecraft.client.Minecraft minecraft =
        net.minecraft.client.Minecraft.getInstance();
}
