package com.tiedup.remake.v2.furniture;

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_furniture/}
 * for JSON files and populates the {@link FurnitureRegistry}.
 *
 * <p>Unlike the data-driven item system (which has both client and server listeners),
 * furniture definitions are server-authoritative only. The registry is atomically
 * replaced via {@link FurnitureRegistry#reload(Map)} on each reload.</p>
 *
 * <p>Registered via {@link net.minecraftforge.event.AddReloadListenerEvent} in
 * {@link com.tiedup.remake.core.TiedUpMod.ForgeEvents}.</p>
 */
public class FurnitureServerReloadListener
    extends SimplePreparableReloadListener<Void>
{

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

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

    @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, FurnitureDefinition> 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()) {
                FurnitureDefinition def = FurnitureParser.parse(input, fileId);

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

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

        // Atomically replace all definitions in the registry
        FurnitureRegistry.reload(newDefs);

        // Broadcast updated definitions to all connected players
        net.minecraft.server.MinecraftServer server =
            net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer();
        if (server != null) {
            for (net.minecraft.server.level.ServerPlayer p : server
                .getPlayerList()
                .getPlayers()) {
                com.tiedup.remake.v2.furniture.network.PacketSyncFurnitureDefinitions.sendToPlayer(
                    p
                );
            }
        }

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