/*
 * Copyright (c) 2026 盐灯水母
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

package com.remains_cave.dungeon.tomb;

import com.remains_cave.dungeon.tomb.ChallengeType;
import com.remains_cave.item.ModItems;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.AddReloadListenerEvent;
import net.neoforged.neoforge.event.OnDatapackSyncEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;

import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class RewardConfigLoader implements ResourceManagerReloadListener {
    private static final Logger LOGGER = LoggerFactory.getLogger(RewardConfigLoader.class);
    private static final Map<ChallengeType, List<ItemStack>> REWARDS_CACHE = new ConcurrentHashMap<>();
    private static final Yaml YAML = new Yaml();

    public static List<ItemStack> getRewards(ChallengeType type) {
        return REWARDS_CACHE.getOrDefault(type, Collections.emptyList());
    }

    @Override
    public void onResourceManagerReload(ResourceManager resourceManager) {
        Map<ChallengeType, List<ItemStack>> newCache = new HashMap<>();
        for (ChallengeType type : List.of(ChallengeType.WARRIOR, ChallengeType.ARCHER, ChallengeType.WARLOCK)) {
            String fileName = type.getSerializedName() + "_rewards.yml";
            ResourceLocation location = ResourceLocation.parse("remains_cave:loot_table/vault_rewards/" + fileName);
            try (InputStream stream = resourceManager.open(location)) {
                Map<String, Object> data = YAML.load(stream);
                List<ItemStack> rewards = parseRewards(data);
                newCache.put(type, rewards);
                LOGGER.info("Loaded {} rewards for {} from {}", rewards.size(), type, location);
            } catch (Exception e) {
                LOGGER.warn("Failed to load reward config for {} from {}, using defaults", type, location);
                newCache.put(type, getDefaultRewards(type));
            }
        }
        REWARDS_CACHE.clear();
        REWARDS_CACHE.putAll(newCache);
    }

    private static List<ItemStack> parseRewards(Map<String, Object> data) {
        List<ItemStack> result = new ArrayList<>();
        List<Map<String, Object>> pools = (List<Map<String, Object>>) data.get("pools");
        if (pools == null) return result;

        Random random = new Random();
        for (Map<String, Object> pool : pools) {
            int rolls = ((Number) pool.get("rolls")).intValue();
            List<Map<String, Object>> entries = (List<Map<String, Object>>) pool.get("entries");
            if (entries == null) continue;

            // 构建有效条目列表
            List<EntryInfo> validEntries = new ArrayList<>();
            int totalWeight = 0;
            for (Map<String, Object> entry : entries) {
                String itemId = (String) entry.get("item");
                Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(itemId));
                if (item == Items.AIR) {
                    LOGGER.warn("Item {} not found, skipping", itemId);
                    continue;
                }
                int weight = ((Number) entry.get("weight")).intValue();
                int count = 1;
                if (entry.containsKey("count")) {
                    Object countObj = entry.get("count");
                    if (countObj instanceof Number) {
                        count = ((Number) countObj).intValue();
                    } else if (countObj instanceof String) {
                        String range = (String) countObj;
                        if (range.contains("-")) {
                            String[] parts = range.split("-");
                            int min = Integer.parseInt(parts[0]);
                            int max = Integer.parseInt(parts[1]);
                            count = min + random.nextInt(max - min + 1);
                        } else {
                            count = Integer.parseInt(range);
                        }
                    }
                }
                validEntries.add(new EntryInfo(item, count, weight));
                totalWeight += weight;
            }
            if (validEntries.isEmpty()) continue;

            for (int i = 0; i < rolls; i++) {
                int r = random.nextInt(totalWeight);
                int accum = 0;
                for (EntryInfo entry : validEntries) {
                    accum += entry.weight;
                    if (r < accum) {
                        result.add(new ItemStack(entry.item, entry.count));
                        break;
                    }
                }
            }
        }
        return result;
    }

    private static List<ItemStack> getDefaultRewards(ChallengeType type) {
        List<ItemStack> rewards = new ArrayList<>();
        Random random = new Random();
        switch (type) {
            case WARRIOR:
                rewards.add(new ItemStack(ModItems.BONE_HATCHET.get()));
                rewards.add(new ItemStack(ModItems.CRIMSON_CRYSTAL.get(), 6 + random.nextInt(4)));
                rewards.add(new ItemStack(Items.DIAMOND, 3 + random.nextInt(3)));
                break;
            case ARCHER:
                rewards.add(new ItemStack(ModItems.TOMB_BOW.get()));
                rewards.add(new ItemStack(ModItems.CRIMSON_CRYSTAL.get(), 6 + random.nextInt(4)));
                rewards.add(new ItemStack(Items.DIAMOND, 3 + random.nextInt(3)));
                break;
            case WARLOCK:
                rewards.add(new ItemStack(ModItems.DOOM_STAFF.get()));
                rewards.add(new ItemStack(ModItems.CRIMSON_CRYSTAL.get(), 6 + random.nextInt(4)));
                rewards.add(new ItemStack(Items.DIAMOND, 3 + random.nextInt(3)));
                break;
            default:
                break;
        }
        return rewards;
    }

    private static class EntryInfo {
        final Item item;
        final int count;
        final int weight;
        EntryInfo(Item item, int count, int weight) {
            this.item = item;
            this.count = count;
            this.weight = weight;
        }
    }

    @EventBusSubscriber(modid = "remains_cave")
    public static class Events {
        @SubscribeEvent
        public static void onAddReloadListener(AddReloadListenerEvent event) {
            event.addListener(new RewardConfigLoader());
        }

        @SubscribeEvent
        public static void onDatapackSync(OnDatapackSyncEvent event) {
            // 可选：同步配置到客户端
        }
    }
}