/*
 *  Copyright 2025-2026 R3944Realms
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package top.r3944realms.eroticdungeongame.content;

import com.google.common.collect.ImmutableMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.entity.npc.VillagerTrades;
import net.minecraft.world.item.*;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.EnchantmentInstance;
import net.minecraft.world.item.trading.MerchantOffer;
import net.minecraftforge.registries.RegistryObject;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.eroticdungeongame.content.block.IColorBlock;
import top.r3944realms.eroticdungeongame.content.block.IWoodTypeBlock;
import top.r3944realms.eroticdungeongame.core.register.EDGEnchantments;
import top.r3944realms.eroticdungeongame.core.register.EDGItems;
import top.r3944realms.eroticdungeongame.core.register.EDGVillagers;
import top.r3944realms.lib39.util.villager.TradeBuilder;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class EDGVillagerTrades {
    public static void init(@NotNull Map<VillagerProfession, Int2ObjectMap<VillagerTrades.ItemListing[]>> trades) {
        trades.put(EDGVillagers.DUNGEON_CRAFTSMAN.get(),
                toIntMap(
                        ImmutableMap.of(
                                1, new VillagerTrades.ItemListing[] {
                                        TradeBuilder.createBuyItemTrade(EDGItems.WHIP.get(), 3, 1, 10, 1),
                                        TradeBuilder.createSellItemTrade(Items.IRON_INGOT, 2, 1024, 1),
                                },
                                2, new VillagerTrades.ItemListing[] {
                                        TradeBuilder.createSellItemTrade(Items.DIAMOND, 1, 1024, 5),
                                        new RandomWoodenDeviceEmeralds(3, 20, 1),
                                },
                                3, new VillagerTrades.ItemListing[] {
                                        TradeBuilder.createSellItemTrade(Items.END_ROD, 4, 1024, 2),
                                        new EnchantBookForEmeralds(10, EDGEnchantments.CARROT_AND_STICK.get()),
                                },
                                4, new VillagerTrades.ItemListing[] {
                                        new TradeBuilder.EnchantedItemForEmeralds(EDGItems.WHIP.get(), 1, 5, 20, 1),
                                        new TradeBuilder.EnchantedItemForEmeralds(EDGItems.END_ROD_LOVE_MACHINE.get(), 1, 5, 20, 1),
                                },
                                5, new VillagerTrades.ItemListing[] {
                                        new RandomWoodenDeviceEmeralds(1, 20, 1),
                                        new RandomWoodenDeviceEmeralds(1, 20, 11),
                                }
                        )
                )
        );
    }
    @Contract("_ -> new")
    private static @NotNull Int2ObjectMap<VillagerTrades.ItemListing[]> toIntMap(ImmutableMap<Integer, VillagerTrades.ItemListing[]> map) {
        return new Int2ObjectOpenHashMap<>(map);
    }
    public static class RandomWoodenDeviceEmeralds implements VillagerTrades.ItemListing {

        private final int value;
        private final int maxUses;
        private final int villagerXp;
        private static volatile List<Item> woodenDeviceItems;
        public RandomWoodenDeviceEmeralds(int value) {
            this(value, 12, 1);
        }

        public RandomWoodenDeviceEmeralds(int value, int maxUses, int villagerXp) {

            this.value = value;
            this.maxUses = maxUses;
            this.villagerXp = villagerXp;
        }

        public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
            ItemStack itemstack = new ItemStack(Items.EMERALD, this.value);
            ItemStack itemstack1 = new ItemStack(getRandomWoodenDevice(random));

            return new MerchantOffer(itemstack, itemstack1, this.maxUses, this.villagerXp, 0.2F);
        }

        private static @NotNull Item getRandomWoodenDevice(@NotNull RandomSource random) {
            if (woodenDeviceItems == null) {
                synchronized (RandomWoodenDeviceEmeralds.class) {
                    if (woodenDeviceItems == null) {
                        woodenDeviceItems = EDGItems.SEAT_ITEMS.stream()
                                .filter(i-> i.get() instanceof BlockItem blockItem && blockItem.getBlock() instanceof IWoodTypeBlock && !(blockItem.getBlock() instanceof IColorBlock))
                                .map(RegistryObject::get)
                                .collect(Collectors.toList());
                    }
                }

            }
            if (!woodenDeviceItems.isEmpty()) {
                return woodenDeviceItems.get(random.nextInt(0, woodenDeviceItems.size()));
            } else return Items.AIR;
        }
    }
    public static class RandomColorDeviceEmeralds implements VillagerTrades.ItemListing {

        private final int value;
        private final int maxUses;
        private final int villagerXp;
        private static volatile List<Item> woodenDeviceItems;
        public RandomColorDeviceEmeralds(int value) {
            this(value, 12, 1);
        }

        public RandomColorDeviceEmeralds(int value, int maxUses, int villagerXp) {

            this.value = value;
            this.maxUses = maxUses;
            this.villagerXp = villagerXp;
        }

        public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
            ItemStack itemstack = new ItemStack(Items.EMERALD, this.value);
            ItemStack itemstack1 = new ItemStack(getRandomWoodenDevice(random));

            return new MerchantOffer(itemstack, itemstack1, this.maxUses, this.villagerXp, 0.2F);
        }

        private static @NotNull Item getRandomWoodenDevice(@NotNull RandomSource random) {
            if (woodenDeviceItems == null) {
                synchronized (RandomWoodenDeviceEmeralds.class) {
                    if (woodenDeviceItems == null) {
                        woodenDeviceItems = EDGItems.SEAT_ITEMS.stream()
                                .filter(i-> i.get() instanceof BlockItem blockItem && blockItem.getBlock() instanceof IColorBlock)
                                .map(RegistryObject::get)
                                .collect(Collectors.toList());
                    }
                }

            }
            if (!woodenDeviceItems.isEmpty()) {
                return woodenDeviceItems.get(random.nextInt(0, woodenDeviceItems.size()));
            } else return Items.AIR;
        }
    }
    public static class EnchantBookForEmeralds implements VillagerTrades.ItemListing {
        private final int villagerXp;
        private final Enchantment enchantment;
        public EnchantBookForEmeralds(int villagerXp, Enchantment enchantment) {
            this.villagerXp = villagerXp;
            this.enchantment = enchantment;
        }

        public MerchantOffer getOffer(@NotNull Entity trader, @NotNull RandomSource random) {
            int i = Mth.nextInt(random, enchantment.getMinLevel(), enchantment.getMaxLevel());
            ItemStack itemstack = EnchantedBookItem.createForEnchantment(new EnchantmentInstance(enchantment, i));
            int j = 2 + random.nextInt(5 + i * 10) + 3 * i;
            if (enchantment.isTreasureOnly()) {
                j *= 2;
            }

            if (j > 64) {
                j = 64;
            }

            return new MerchantOffer(new ItemStack(Items.EMERALD, j), new ItemStack(Items.BOOK), itemstack, 12, this.villagerXp, 0.2F);
        }
    }
}
