package zenith.zov.client.modules.impl.combat;

import com.darkmagician6.eventapi.EventTarget;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.screen.slot.Slot;
import net.minecraft.util.Hand;
import zenith.zov.base.events.impl.input.EventKey;
import zenith.zov.client.modules.api.Category;
import zenith.zov.client.modules.api.Module;
import zenith.zov.client.modules.api.ModuleAnnotation;
import zenith.zov.client.modules.api.setting.impl.KeySetting;
import zenith.zov.client.modules.api.setting.impl.ModeSetting;
import zenith.zov.client.modules.api.setting.impl.ToolSelectSetting;
import zenith.zov.utility.game.player.PlayerInventoryComponent;
import zenith.zov.utility.game.player.PlayerInventoryUtil;

@ModuleAnnotation(
    name = "AutoSwap",
    category = Category.COMBAT,
    description = "Automatic tool swap"
)
public final class AutoSwap extends Module {
    public static final AutoSwap INSTANCE = new AutoSwap();
    private final ToolSelectSetting primaryTools = new ToolSelectSetting("Primary Tools", new ArrayList<>());
    private final ToolSelectSetting secondaryTools = new ToolSelectSetting("Secondary Tools", new ArrayList<>());
    private final ModeSetting itemType = new ModeSetting("Item Type", "Shield", "Gapples", "Totem", "Head", "Sword", "Mace");
    private final ModeSetting swapType = new ModeSetting("Swap to", "Shield", "Gapples", "Totem", "Head", "Sword", "Mace");
    private final KeySetting keyToSwap = new KeySetting("Button", -1);

    private AutoSwap() {
        this.primaryTools.add(Items.DIAMOND_PICKAXE);
        this.primaryTools.add(Items.NETHERITE_PICKAXE);
        this.primaryTools.add(Items.DIAMOND_AXE);
        this.primaryTools.add(Items.NETHERITE_AXE);
        this.secondaryTools.add(Items.DIAMOND_SWORD);
        this.secondaryTools.add(Items.NETHERITE_SWORD);
        this.secondaryTools.add(Items.DIAMOND_SHOVEL);
        this.secondaryTools.add(Items.NETHERITE_SHOVEL);
    }

    @EventTarget
    public void onKey(EventKey event) {
        if (mc.currentScreen == null) {
            if (event.getAction() == 1) {
                if (event.is(this.keyToSwap.getKeyCode())) {
                    Slot primarySlot = this.findBestToolSlot(this.primaryTools.getToolsById());
                    Slot secondarySlot = this.findBestToolSlot(this.secondaryTools.getToolsById());
                    if (primarySlot == null) {
                        primarySlot = PlayerInventoryUtil.getSlot(
                            this.getItemByType(this.itemType.get()),
                            Comparator.comparing(s -> s.getStack().hasEnchantments()),
                            s -> s.id != 46 && s.id != 45
                        );
                    }

                    if (secondarySlot == null) {
                        secondarySlot = PlayerInventoryUtil.getSlot(
                            this.getItemByType(this.swapType.get()),
                            Comparator.comparing(s -> s.getStack().hasEnchantments()),
                            s -> s.id != 46 && s.id != 45
                        );
                    }

                    Slot validSlot = primarySlot != null && mc.player.getOffHandStack().getItem() != primarySlot.getStack().getItem()
                        ? primarySlot
                        : secondarySlot;
                    if (validSlot != null) {
                        PlayerInventoryComponent.addTask(() -> {
                            PlayerInventoryUtil.swapHand(validSlot, Hand.OFF_HAND, false);
                            PlayerInventoryUtil.closeScreen(true);
                        });
                    }
                }
            }
        }
    }

    private Slot findBestToolSlot(List<String> toolIds) {
        if (toolIds.isEmpty()) {
            return null;
        } else {
            Slot bestSlot = null;
            int bestPriority = Integer.MIN_VALUE;

            for (String toolId : toolIds) {
                Item toolItem = this.getItemById(toolId);
                if (toolItem != null) {
                    Slot slot = PlayerInventoryUtil.getSlot(
                        toolItem,
                        Comparator.<Slot, Boolean>comparing(s -> s.getStack().hasEnchantments()).thenComparing(s -> this.getSlotPriority(s.id)),
                        s -> s.id != 46 && s.id != 45
                    );
                    if (slot != null) {
                        int priority = this.calculateSlotPriority(slot);
                        if (priority > bestPriority) {
                            bestPriority = priority;
                            bestSlot = slot;
                        }
                    }
                }
            }

            return bestSlot;
        }
    }

    private Item getItemById(String toolId) {
        return switch (toolId) {
            case "diamond_pickaxe" -> Items.DIAMOND_PICKAXE;
            case "netherite_pickaxe" -> Items.NETHERITE_PICKAXE;
            case "diamond_axe" -> Items.DIAMOND_AXE;
            case "netherite_axe" -> Items.NETHERITE_AXE;
            case "diamond_shovel" -> Items.DIAMOND_SHOVEL;
            case "netherite_shovel" -> Items.NETHERITE_SHOVEL;
            case "diamond_sword" -> Items.DIAMOND_SWORD;
            case "netherite_sword" -> Items.NETHERITE_SWORD;
            case "diamond_hoe" -> Items.DIAMOND_HOE;
            case "netherite_hoe" -> Items.NETHERITE_HOE;
            case "iron_pickaxe" -> Items.IRON_PICKAXE;
            case "iron_axe" -> Items.IRON_AXE;
            case "iron_shovel" -> Items.IRON_SHOVEL;
            case "iron_sword" -> Items.IRON_SWORD;
            case "iron_hoe" -> Items.IRON_HOE;
            case "stone_pickaxe" -> Items.STONE_PICKAXE;
            case "stone_axe" -> Items.STONE_AXE;
            case "stone_shovel" -> Items.STONE_SHOVEL;
            case "stone_sword" -> Items.STONE_SWORD;
            case "stone_hoe" -> Items.STONE_HOE;
            case "wooden_pickaxe" -> Items.WOODEN_PICKAXE;
            case "wooden_axe" -> Items.WOODEN_AXE;
            case "wooden_shovel" -> Items.WOODEN_SHOVEL;
            case "wooden_sword" -> Items.WOODEN_SWORD;
            case "wooden_hoe" -> Items.WOODEN_HOE;
            case "golden_pickaxe" -> Items.GOLDEN_PICKAXE;
            case "golden_axe" -> Items.GOLDEN_AXE;
            case "golden_shovel" -> Items.GOLDEN_SHOVEL;
            case "golden_sword" -> Items.GOLDEN_SWORD;
            case "golden_hoe" -> Items.GOLDEN_HOE;
            case "mace" -> Items.MACE;
            default -> null;
        };
    }

    private int calculateSlotPriority(Slot slot) {
        int priority = 0;
        if (slot.getStack().hasEnchantments()) {
            priority += 1000;
        }

        if (slot.id >= 0 && slot.id <= 8) {
            priority += 500;
        }

        if (slot.id >= 9 && slot.id <= 35) {
            priority += 200;
        }

        if (slot.getStack().isDamageable()) {
            int maxDamage = slot.getStack().getMaxDamage();
            int currentDamage = slot.getStack().getDamage();
            if (maxDamage > 0) {
                priority += (int)((1.0 - (double)currentDamage / (double)maxDamage) * 100.0);
            }
        }

        return priority;
    }

    private int getSlotPriority(int slotId) {
        if (slotId >= 0 && slotId <= 8) {
            return slotId;
        } else {
            return slotId >= 9 && slotId <= 35 ? slotId + 100 : slotId + 1000;
        }
    }

    private Item getItemByType(String itemType) {
        return switch (itemType) {
            case "Shield" -> Items.SHIELD;
            case "Totem" -> Items.TOTEM_OF_UNDYING;
            case "Gapples" -> Items.GOLDEN_APPLE;
            case "Head" -> Items.PLAYER_HEAD;
            case "Sword" -> Items.NETHERITE_SWORD;
            case "Mace" -> Items.MACE;
            default -> Items.AIR;
        };
    }
}
