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

import com.tiedup.remake.client.gui.util.GuiRenderUtil;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.IV2BondageItem;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import net.minecraft.client.Minecraft;
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.network.chat.Component;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

/**
 * Modal overlay for selecting a bondage item to equip on a body region.
 * Filters the player's inventory for compatible IV2BondageItem instances.
 */
@OnlyIn(Dist.CLIENT)
public class ItemPickerOverlay extends AbstractWidget {

    private record PickerEntry(ItemStack stack, int inventorySlot) {}

    private static final int ENTRY_HEIGHT = 28;
    private static final int PADDING = 10;
    private static final int CANCEL_BTN_HEIGHT = 22;
    private static final int CANCEL_BTN_WIDTH = 80;
    private static final int OVERLAY_BG = 0xCC000000; // Semi-transparent black
    private static final int WARNING_COLOR = 0xFFF44336;

    private BodyRegionV2 targetRegion;
    private final List<PickerEntry> entries = new ArrayList<>();
    private BiConsumer<BodyRegionV2, Integer> onItemSelected; // region, inventorySlot
    private Runnable onCancelled;
    private boolean visible = false;

    // ARMS self-equip warning: click-twice-to-confirm
    private int armsWarningSlot = -1; // -1 = no warning shown
    private boolean isSelfMode;

    // Scroll
    private int scrollOffset = 0;

    // Screen dimensions for overlay sizing
    private int screenWidth;
    private int screenHeight;

    public ItemPickerOverlay() {
        super(0, 0, 0, 0, Component.translatable("gui.tiedup.item_picker"));
        this.active = false;
        this.visible = false;
    }

    public void setOnItemSelected(BiConsumer<BodyRegionV2, Integer> cb) {
        this.onItemSelected = cb;
    }

    public void setOnCancelled(Runnable cb) {
        this.onCancelled = cb;
    }

    public boolean isOverlayVisible() {
        return visible;
    }

    /**
     * Open the picker overlay for a specific region.
     */
    public void open(
        BodyRegionV2 region,
        boolean selfMode,
        int screenWidth,
        int screenHeight
    ) {
        this.targetRegion = region;
        this.isSelfMode = selfMode;
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;
        this.scrollOffset = 0;
        this.armsWarningSlot = -1;
        scanInventory();
        this.visible = true;
        this.active = true;
    }

    public void close() {
        this.visible = false;
        this.active = false;
        entries.clear();
    }

    private void scanInventory() {
        entries.clear();
        Player player = Minecraft.getInstance().player;
        if (player == null || targetRegion == null) return;

        for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
            ItemStack stack = player.getInventory().getItem(i);
            if (stack.isEmpty()) continue;
            if (
                !(stack.getItem() instanceof IV2BondageItem bondageItem)
            ) continue;
            if (
                !bondageItem.getOccupiedRegions(stack).contains(targetRegion)
            ) continue;
            entries.add(new PickerEntry(stack, i));
        }
    }

    // Panel bounds (centered on screen)
    private int getPanelWidth() {
        return Math.min(280, screenWidth - 40);
    }

    private int getPanelHeight() {
        int contentH =
            entries.size() * ENTRY_HEIGHT +
            CANCEL_BTN_HEIGHT +
            PADDING * 3 +
            20;
        return Math.min(contentH, screenHeight - 60);
    }

    private int getPanelX() {
        return (screenWidth - getPanelWidth()) / 2;
    }

    private int getPanelY() {
        return (screenHeight - getPanelHeight()) / 2;
    }

    @Override
    protected void renderWidget(
        GuiGraphics graphics,
        int mouseX,
        int mouseY,
        float partialTick
    ) {
        if (!visible) return;
        Minecraft mc = Minecraft.getInstance();

        // Full-screen overlay
        graphics.fill(0, 0, screenWidth, screenHeight, OVERLAY_BG);

        int panelX = getPanelX();
        int panelY = getPanelY();
        int panelW = getPanelWidth();
        int panelH = getPanelHeight();

        // MC-style raised panel
        GuiRenderUtil.drawMCPanel(graphics, panelX, panelY, panelW, panelH);

        // Title (dark text, vanilla style)
        String title = Component.translatable(
            "gui.tiedup.picker.title",
            Component.translatable(
                "gui.tiedup.region." + targetRegion.name().toLowerCase()
            )
        ).getString();
        graphics.drawString(
            mc.font,
            title,
            panelX + PADDING,
            panelY + PADDING,
            GuiRenderUtil.MC_TEXT_DARK,
            false
        );

        // Entries
        int listY = panelY + PADDING + mc.font.lineHeight + 8;
        int maxVisible =
            (panelH -
                PADDING * 3 -
                mc.font.lineHeight -
                8 -
                CANCEL_BTN_HEIGHT) /
            ENTRY_HEIGHT;

        for (int i = 0; i < Math.min(entries.size(), maxVisible); i++) {
            int idx = i + scrollOffset;
            if (idx >= entries.size()) break;
            PickerEntry entry = entries.get(idx);
            int entryY = listY + i * ENTRY_HEIGHT;
            int entryX = panelX + PADDING;
            int entryW = panelW - PADDING * 2;

            boolean hovered =
                mouseX >= entryX &&
                mouseX < entryX + entryW &&
                mouseY >= entryY &&
                mouseY < entryY + ENTRY_HEIGHT;
            boolean isArmsWarning = (armsWarningSlot == entry.inventorySlot);

            // MC-style slot for each entry
            GuiRenderUtil.drawMCSlot(
                graphics,
                entryX,
                entryY,
                entryW,
                ENTRY_HEIGHT - 2
            );

            // Gold border for ARMS warning confirmation
            if (isArmsWarning) {
                GuiRenderUtil.drawSelectedBorder(
                    graphics,
                    entryX,
                    entryY,
                    entryW,
                    ENTRY_HEIGHT - 2
                );
            }

            // Vanilla hover overlay (white semi-transparent)
            if (hovered && !isArmsWarning) {
                GuiRenderUtil.drawSlotHover(
                    graphics,
                    entryX,
                    entryY,
                    entryW,
                    ENTRY_HEIGHT - 2
                );
            }

            // Item icon (16x16)
            graphics.renderItem(
                entry.stack,
                entryX + 4,
                entryY + (ENTRY_HEIGHT - 18) / 2
            );

            // Item name
            String name = entry.stack.getHoverName().getString();
            graphics.drawString(
                mc.font,
                name,
                entryX + 24,
                entryY + (ENTRY_HEIGHT - mc.font.lineHeight) / 2,
                GuiRenderUtil.MC_TEXT_DARK,
                false
            );
        }

        // ARMS warning text
        if (armsWarningSlot >= 0) {
            String warning = Component.translatable(
                "gui.tiedup.picker.arms_warning"
            ).getString();
            int warningY =
                listY + Math.min(entries.size(), maxVisible) * ENTRY_HEIGHT + 2;
            graphics.drawString(
                mc.font,
                warning,
                panelX + PADDING,
                warningY,
                WARNING_COLOR,
                false
            );
        }

        // Empty state
        if (entries.isEmpty()) {
            String empty = Component.translatable(
                "gui.tiedup.picker.empty"
            ).getString();
            GuiRenderUtil.drawCenteredStringNoShadow(
                graphics,
                mc.font,
                empty,
                panelX + panelW / 2,
                listY + 20,
                GuiRenderUtil.MC_TEXT_GRAY
            );
        }

        // Cancel button (MC-style)
        int cancelX = panelX + (panelW - CANCEL_BTN_WIDTH) / 2;
        int cancelY = panelY + panelH - CANCEL_BTN_HEIGHT - PADDING;
        boolean cancelHovered =
            mouseX >= cancelX &&
            mouseX < cancelX + CANCEL_BTN_WIDTH &&
            mouseY >= cancelY &&
            mouseY < cancelY + CANCEL_BTN_HEIGHT;
        GuiRenderUtil.drawMCButton(
            graphics,
            cancelX,
            cancelY,
            CANCEL_BTN_WIDTH,
            CANCEL_BTN_HEIGHT,
            cancelHovered,
            true
        );
        String cancelText = Component.translatable(
            "gui.tiedup.cancel"
        ).getString();
        GuiRenderUtil.drawCenteredStringNoShadow(
            graphics,
            mc.font,
            cancelText,
            cancelX + CANCEL_BTN_WIDTH / 2,
            cancelY + (CANCEL_BTN_HEIGHT - mc.font.lineHeight) / 2,
            GuiRenderUtil.MC_TEXT_DARK
        );
    }

    @Override
    public boolean mouseClicked(double mouseX, double mouseY, int button) {
        if (!visible || button != 0) return false;
        Minecraft mc = Minecraft.getInstance();

        int panelX = getPanelX();
        int panelY = getPanelY();
        int panelW = getPanelWidth();
        int panelH = getPanelHeight();

        // Cancel button
        int cancelX = panelX + (panelW - CANCEL_BTN_WIDTH) / 2;
        int cancelY = panelY + panelH - CANCEL_BTN_HEIGHT - PADDING;
        if (
            mouseX >= cancelX &&
            mouseX < cancelX + CANCEL_BTN_WIDTH &&
            mouseY >= cancelY &&
            mouseY < cancelY + CANCEL_BTN_HEIGHT
        ) {
            close();
            if (onCancelled != null) onCancelled.run();
            return true;
        }

        // Entry clicks
        int listY = panelY + PADDING + mc.font.lineHeight + 8;
        int maxVisible =
            (panelH -
                PADDING * 3 -
                mc.font.lineHeight -
                8 -
                CANCEL_BTN_HEIGHT) /
            ENTRY_HEIGHT;

        for (int i = 0; i < Math.min(entries.size(), maxVisible); i++) {
            int idx = i + scrollOffset;
            if (idx >= entries.size()) break;
            PickerEntry entry = entries.get(idx);
            int entryY = listY + i * ENTRY_HEIGHT;
            int entryX = panelX + PADDING;
            int entryW = panelW - PADDING * 2;

            if (
                mouseX >= entryX &&
                mouseX < entryX + entryW &&
                mouseY >= entryY &&
                mouseY < entryY + ENTRY_HEIGHT
            ) {
                // ARMS self-equip warning: double-click confirmation
                if (isSelfMode && targetRegion == BodyRegionV2.ARMS) {
                    if (armsWarningSlot == entry.inventorySlot) {
                        // Second click — confirm
                        if (onItemSelected != null) onItemSelected.accept(
                            targetRegion,
                            entry.inventorySlot
                        );
                        close();
                    } else {
                        // First click — show warning
                        armsWarningSlot = entry.inventorySlot;
                    }
                } else {
                    if (onItemSelected != null) onItemSelected.accept(
                        targetRegion,
                        entry.inventorySlot
                    );
                    close();
                }
                playDownSound(mc.getSoundManager());
                return true;
            }
        }

        // Click outside panel = cancel
        if (
            mouseX < panelX ||
            mouseX > panelX + panelW ||
            mouseY < panelY ||
            mouseY > panelY + panelH
        ) {
            close();
            if (onCancelled != null) onCancelled.run();
            return true;
        }

        return false;
    }

    @Override
    public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
        if (!visible) return false;
        int panelH = getPanelHeight();
        int maxVisible =
            (panelH -
                PADDING * 3 -
                Minecraft.getInstance().font.lineHeight -
                8 -
                CANCEL_BTN_HEIGHT) /
            ENTRY_HEIGHT;
        int maxScroll = Math.max(0, entries.size() - maxVisible);
        scrollOffset = Math.max(
            0,
            Math.min(maxScroll, scrollOffset - (int) delta)
        );
        return true;
    }

    @Override
    public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
        if (!visible) return false;
        // ESC closes overlay
        if (keyCode == 256) {
            // GLFW_KEY_ESCAPE
            close();
            if (onCancelled != null) onCancelled.run();
            return true;
        }
        return false;
    }

    @Override
    protected void updateWidgetNarration(NarrationElementOutput output) {
        output.add(
            NarratedElementType.TITLE,
            Component.translatable(
                "gui.tiedup.picker.title",
                targetRegion != null
                    ? Component.translatable(
                          "gui.tiedup.region." +
                              targetRegion.name().toLowerCase()
                      )
                    : ""
            )
        );
    }
}
