package zenith.zov.client.screens.autobuy.items;

import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.util.math.Vector2f;
import net.minecraft.item.Items;
import zenith.zov.Zenith;
import zenith.zov.base.animations.base.Animation;
import zenith.zov.base.animations.base.Easing;
import zenith.zov.base.autobuy.item.ItemBuy;
import zenith.zov.base.font.Fonts;
import zenith.zov.base.theme.Theme;
import zenith.zov.client.modules.impl.misc.AutoSbor;
import zenith.zov.client.screens.autobuy.UiItemBuy;
import zenith.zov.utility.game.other.MouseButton;
import zenith.zov.utility.game.other.render.CustomScreen;
import zenith.zov.utility.render.display.ScrollHandler;
import zenith.zov.utility.render.display.TextBox;
import zenith.zov.utility.render.display.base.BorderRadius;
import zenith.zov.utility.render.display.base.UIContext;

public class AutoInventoryBuyScreen extends CustomScreen {
    private final Animation animationScale = new Animation(300L, Easing.QUAD_IN_OUT);
    private final TextBox searchBox = new TextBox(new Vector2f(0.0F, 0.0F), Fonts.MEDIUM.getFont(7.0F), "Search...", 200.0F);
    private final List<UiItemBuy> libraryItems = new ArrayList<>();
    private final List<UiItemBuy> inventoryItems = new ArrayList<>();
    private UiItemBuy draggedItem = null;
    private boolean draggedFromLibrary = false;
    private float dragOffsetX;
    private float dragOffsetY;
    private final ScrollHandler scrollHandler = new ScrollHandler();
    private boolean draggingScrollbar = false;
    private float scrollClickOffset = 0.0F;
    private UiItemBuy currentUiItemBuy = null;

    public AutoInventoryBuyScreen(List<ItemBuy> lib, List<AutoInventoryItem> items) {
        lib.forEach(itemBuy -> this.libraryItems.add(new UiItemBuy(createItem(itemBuy))));
        items.forEach(itemBuy -> this.inventoryItems.add(new UiItemBuy(itemBuy)));
        this.currentUiItemBuy = this.inventoryItems.stream().filter(e -> e.getItemBuy().isSelected()).findAny().orElse(null);
    }

    public static AutoInventoryItem createItem(ItemBuy itemBuy) {
        return (AutoInventoryItem)(itemBuy.getCategory() == ItemBuy.Category.ANY && itemBuy.getItemStack().getItem() == Items.ELYTRA
            ? new AutoInventoryElytra(itemBuy)
            : new AutoInventoryItem(itemBuy));
    }

    @Override
    public void render(UIContext ctx, float mouseX, float mouseY) {
        this.scrollHandler.update();
        float sizeItem = 20.0F;
        float widthLibrary = 8.0F + (sizeItem + 4.0F) * 4.0F + 8.0F - 4.0F;
        float widthSettings = 9.0F * (sizeItem + 4.0F) + 8.0F;
        float totalWidth = widthLibrary + widthSettings;
        float height = 200.0F;
        float x = ((float)mc.getWindow().getScaledWidth() - totalWidth) / 2.0F;
        float y = ((float)mc.getWindow().getScaledHeight() - height) / 2.0F;
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();
        ctx.drawRoundedRect(x, y, totalWidth, height, BorderRadius.all(8.0F), theme.getBackgroundColor());
        ctx.drawRoundedRect(x + 8.0F, y + 8.0F, (sizeItem + 4.0F) * 4.0F - 4.0F, 20.0F, BorderRadius.all(4.0F), theme.getForegroundLight());
        this.searchBox.render(ctx, x + 8.0F + 8.0F, y + 8.0F + 8.0F, theme.getWhite(), theme.getGray());
        this.searchBox.setWidth(sizeItem * 4.0F);
        this.searchBox.setMaxLength(15);
        String query = this.searchBox.getText().toLowerCase();
        List<UiItemBuy> filteredLibrary = this.libraryItems
            .stream()
            .filter(item -> item.getItemBuy().getItemBuy().getSearchName().toLowerCase().contains(query))
            .toList();
        this.renderLibrary(ctx, filteredLibrary, x + 8.0F, y + 8.0F + 8.0F + 20.0F, sizeItem);
        this.renderInventory(ctx, x + widthLibrary, y + height - 8.0F - 4.0F * (sizeItem + 4.0F), sizeItem);
        if (this.currentUiItemBuy != null) {
            this.currentUiItemBuy.renderSettings(ctx, mouseX, mouseY, x + widthLibrary, y + 8.0F, sizeItem);
        }

        if (this.draggedItem != null) {
            this.draggedItem.renderSlotBar(ctx, mouseX - this.dragOffsetX, mouseY - this.dragOffsetY, sizeItem, BorderRadius.all(4.0F));
        }
    }

    private void renderLibrary(UIContext ctx, List<UiItemBuy> items, float startX, float startY, float sizeItem) {
        int totalRows = (int)Math.ceil((double)items.size() / 4.0);
        float rowHeight = sizeItem + 4.0F;
        float contentHeight = (float)totalRows * rowHeight;
        this.scrollHandler.setMax((double)Math.max(0.0F, contentHeight - 160.0F));
        float scrollOffset = (float)this.scrollHandler.getValue();
        ctx.enableScissor((int)startX, (int)startY, (int)(startX + (sizeItem + 4.0F) * 4.0F), (int)(startY + 165.0F));
        int col = 0;
        int row = 0;

        for (UiItemBuy itemBuy : items) {
            float slotX = startX + (float)col * (sizeItem + 4.0F);
            float slotY = startY + (float)row * (sizeItem + 4.0F) - scrollOffset;
            itemBuy.setBounds(slotX, slotY, sizeItem, sizeItem);
            if (itemBuy != this.draggedItem || !this.draggedFromLibrary) {
                itemBuy.renderSlotBar(ctx, slotX, slotY, sizeItem, BorderRadius.all(4.0F));
            }

            if (++col >= 4) {
                col = 0;
                row++;
            }
        }

        ctx.disableScissor();
    }

    private void renderInventory(UIContext ctx, float startX, float startY, float sizeItem) {
        Theme theme = Zenith.getInstance().getThemeManager().getCurrentTheme();
        int col = 0;
        int row = 0;

        for (int slotIndex = 0; slotIndex < 36; slotIndex++) {
            float slotX = startX + (float)col * (sizeItem + 4.0F);
            float slotY = startY + (float)row * (sizeItem + 4.0F);
            ctx.drawRoundedRect(slotX, slotY, sizeItem, sizeItem, BorderRadius.all(4.0F), theme.getForegroundGray());

            for (UiItemBuy itemBuy : this.inventoryItems) {
                if (itemBuy.getItemBuy().getSlotId() == slotIndex && itemBuy != this.draggedItem) {
                    itemBuy.setBounds(slotX, slotY, sizeItem, sizeItem);
                    itemBuy.renderSlotBar(ctx, slotX, slotY, sizeItem, BorderRadius.all(4.0F));
                }
            }

            if (++col >= 9) {
                col = 0;
                row++;
            }
        }
    }

    private boolean isSlotOccupied(int slotIndex) {
        for (UiItemBuy item : this.inventoryItems) {
            if (item.getItemBuy().getSlotId() == slotIndex) {
                return true;
            }
        }

        return false;
    }

    @Override
    public void onMouseClicked(double mouseX, double mouseY, MouseButton button) {
        this.searchBox.onMouseClicked(mouseX, mouseY, button);
        float y = (float)(mc.getWindow().getScaledHeight() - 200) / 2.0F;
        if (mouseY > (double)(y + 8.0F + 8.0F + 20.0F) && mouseY < (double)(y + 8.0F + 8.0F + 20.0F + 160.0F)) {
            for (UiItemBuy itemBuy : this.libraryItems
                .stream()
                .filter(item -> item.getItemBuy().getItemBuy().getSearchName().toLowerCase().contains(this.searchBox.getText().toLowerCase()))
                .toList()) {
                if (itemBuy.getBounds() != null && itemBuy.getBounds().contains(mouseX, mouseY) && button == MouseButton.LEFT) {
                    this.draggedItem = itemBuy;
                    this.draggedFromLibrary = true;
                    this.dragOffsetX = (float)mouseX - itemBuy.getBounds().x();
                    this.dragOffsetY = (float)mouseY - itemBuy.getBounds().y();
                    return;
                }
            }
        }

        for (UiItemBuy itemBuyx : this.inventoryItems) {
            if (itemBuyx.getBounds() != null && itemBuyx.getBounds().contains(mouseX, mouseY)) {
                if (button == MouseButton.LEFT) {
                    this.draggedItem = itemBuyx;
                    this.draggedFromLibrary = false;
                    this.dragOffsetX = (float)mouseX - itemBuyx.getBounds().x();
                    this.dragOffsetY = (float)mouseY - itemBuyx.getBounds().y();
                    return;
                }

                if (button == MouseButton.RIGHT) {
                    if (this.currentUiItemBuy != null) {
                        this.currentUiItemBuy.getItemBuy().setSelected(false);
                    }

                    this.currentUiItemBuy = itemBuyx;
                    this.currentUiItemBuy.getItemBuy().setSelected(true);
                    return;
                }
            }
        }

        if (this.currentUiItemBuy != null) {
            this.currentUiItemBuy.onMouseClicked(mouseX, mouseY, button, true);
        }
    }

    @Override
    public void onMouseReleased(double mouseX, double mouseY, MouseButton button) {
        if (this.draggedItem != null && button == MouseButton.LEFT) {
            float sizeItem = 20.0F;
            float widthLibrary = 8.0F + (sizeItem + 4.0F) * 4.0F + 8.0F;
            float height = 200.0F;
            float x = ((float)mc.getWindow().getScaledWidth() - (widthLibrary + 9.0F * (sizeItem + 4.0F) + 8.0F)) / 2.0F;
            float y = ((float)mc.getWindow().getScaledHeight() - height) / 2.0F;
            float slotStartX = x + widthLibrary;
            float slotStartY = y + height - 8.0F - 4.0F * (sizeItem + 4.0F);
            int col = 0;
            int row = 0;
            boolean placed = false;

            for (int slotIndex = 0; slotIndex < 36; slotIndex++) {
                float slotX = slotStartX + (float)col * (sizeItem + 4.0F);
                float slotY = slotStartY + (float)row * (sizeItem + 4.0F);
                if (mouseX >= (double)slotX && mouseX <= (double)(slotX + sizeItem) && mouseY >= (double)slotY && mouseY <= (double)(slotY + sizeItem)) {
                    if (!this.isSlotOccupied(slotIndex)) {
                        if (this.draggedFromLibrary) {
                            AutoInventoryItem newItem = this.draggedItem.getItemBuy().copy();
                            newItem.setSlotId(slotIndex);
                            AutoSbor.INSTANCE.getZakup().add(newItem);
                            UiItemBuy uiItemBuy = new UiItemBuy(newItem);
                            this.inventoryItems.add(uiItemBuy);
                            if (this.currentUiItemBuy != null) {
                                this.currentUiItemBuy.getItemBuy().setSelected(false);
                            }

                            this.currentUiItemBuy = uiItemBuy;
                            this.currentUiItemBuy.getItemBuy().setSelected(true);
                        } else {
                            this.draggedItem.getItemBuy().setSlotId(slotIndex);
                        }

                        placed = true;
                    }
                    break;
                }

                if (++col >= 9) {
                    col = 0;
                    row++;
                }
            }

            if (!placed && !this.draggedFromLibrary) {
                AutoSbor.INSTANCE.getZakup().remove(this.draggedItem.getItemBuy());
                this.inventoryItems.remove(this.draggedItem);
            }

            this.draggedItem = null;
        }

        if (this.currentUiItemBuy != null) {
            this.currentUiItemBuy.onMouseReleased(mouseX, mouseY, button);
        }
    }

    public boolean charTyped(char codePoint, int modifiers) {
        this.searchBox.charTyped(codePoint, modifiers);
        if (this.currentUiItemBuy != null) {
            this.currentUiItemBuy.charTyped(codePoint, modifiers);
        }

        return super.charTyped(codePoint, modifiers);
    }

    public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
        this.scrollHandler.scroll(verticalAmount * 10.0);
        return true;
    }

    public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
        this.searchBox.keyPressed(keyCode, scanCode, modifiers);
        if (this.currentUiItemBuy != null) {
            this.currentUiItemBuy.keyPressed(keyCode, scanCode, modifiers);
        }

        return super.keyPressed(keyCode, scanCode, modifiers);
    }

    public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) {
    }
}
