package com.tiedup.remake.v2.bondage.datadriven;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
import net.minecraft.util.profiling.ProfilerFiller;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * Server-side resource reload listener that scans {@code data/<namespace>/tiedup_items/}
 * for JSON files and populates the {@link DataDrivenItemRegistry}.
 *
 * <p>This is the server counterpart to {@link DataDrivenItemReloadListener} (client-side,
 * which scans {@code assets/}). On a dedicated server, only this listener runs.
 * On an integrated server (singleplayer), both listeners run -- the last one to apply
 * wins the atomic swap, but they parse identical JSON content so the result is the same.</p>
 *
 * <p>Registered via {@link net.minecraftforge.event.AddReloadListenerEvent} in
 * {@link com.tiedup.remake.core.TiedUpMod.ForgeEvents}.</p>
 */
public class DataDrivenItemServerReloadListener
    extends SimplePreparableReloadListener<Void>
{

    private static final Logger LOGGER = LogManager.getLogger(
        "DataDrivenItems"
    );

    /** Resource directory containing item definition JSON files (under data/). */
    private static final String DIRECTORY = "tiedup_items";

    @Override
    protected Void prepare(
        ResourceManager resourceManager,
        ProfilerFiller profiler
    ) {
        // No preparation needed -- parsing happens in apply phase
        return null;
    }

    @Override
    protected void apply(
        Void nothing,
        ResourceManager resourceManager,
        ProfilerFiller profiler
    ) {
        Map<ResourceLocation, DataDrivenItemDefinition> newDefs =
            new HashMap<>();

        Map<ResourceLocation, Resource> resources =
            resourceManager.listResources(DIRECTORY, loc ->
                loc.getPath().endsWith(".json")
            );

        int skipped = 0;

        for (Map.Entry<
            ResourceLocation,
            Resource
        > entry : resources.entrySet()) {
            ResourceLocation fileId = entry.getKey();
            Resource resource = entry.getValue();

            try (InputStream input = resource.open()) {
                DataDrivenItemDefinition def = DataDrivenItemParser.parse(
                    input,
                    fileId
                );

                if (def != null) {
                    // Check for duplicate IDs
                    if (newDefs.containsKey(def.id())) {
                        LOGGER.warn(
                            "[DataDrivenItems] Server: Duplicate item ID '{}' from file '{}' -- overwriting previous definition",
                            def.id(),
                            fileId
                        );
                    }

                    newDefs.put(def.id(), def);
                    LOGGER.debug(
                        "[DataDrivenItems] Server loaded: {} -> '{}'",
                        def.id(),
                        def.displayName()
                    );
                } else {
                    skipped++;
                }
            } catch (Exception e) {
                LOGGER.error(
                    "[DataDrivenItems] Server: Failed to read resource {}: {}",
                    fileId,
                    e.getMessage()
                );
                skipped++;
            }
        }

        // Merge into the registry (not replace) so the client listener's
        // definitions aren't overwritten on integrated server
        DataDrivenItemRegistry.mergeAll(newDefs);

        LOGGER.info(
            "[DataDrivenItems] Server loaded {} item definitions ({} skipped) from {} JSON files",
            newDefs.size(),
            skipped,
            resources.size()
        );
    }
}
