package com.tiedup.remake.network.minigame;

import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.minigame.ContinuousStruggleMiniGameState;
import com.tiedup.remake.minigame.StruggleSessionManager;
import com.tiedup.remake.network.PacketRateLimiter;
import java.util.UUID;
import java.util.function.Supplier;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkEvent;

/**
 * Client to Server packet for continuous struggle key hold state.
 *
 * Sent every 5 ticks (4 times per second) while the struggle screen is open.
 * Reports which direction key the player is holding (or -1 if none).
 */
public class PacketContinuousStruggleHold {

    private final UUID sessionId;
    private final int heldDirection; // -1 if not holding any direction key
    private final boolean isHolding;

    public PacketContinuousStruggleHold(
        UUID sessionId,
        int heldDirection,
        boolean isHolding
    ) {
        this.sessionId = sessionId;
        this.heldDirection = heldDirection;
        this.isHolding = isHolding;
    }

    public void encode(FriendlyByteBuf buf) {
        buf.writeUUID(sessionId);
        buf.writeVarInt(heldDirection);
        buf.writeBoolean(isHolding);
    }

    public static PacketContinuousStruggleHold decode(FriendlyByteBuf buf) {
        UUID sessionId = buf.readUUID();
        int heldDirection = buf.readVarInt();
        boolean isHolding = buf.readBoolean();
        return new PacketContinuousStruggleHold(
            sessionId,
            heldDirection,
            isHolding
        );
    }

    public void handle(Supplier<NetworkEvent.Context> ctx) {
        ctx
            .get()
            .enqueueWork(() -> {
                ServerPlayer player = ctx.get().getSender();
                if (player == null) {
                    return;
                }
                handleServer(player);
            });
        ctx.get().setPacketHandled(true);
    }

    private void handleServer(ServerPlayer player) {
        // HIGH FIX #18: Rate limiting to prevent packet spam exploit
        // Designed for 4/sec, allow up to 12/sec with buffer
        if (!PacketRateLimiter.allowPacket(player, "minigame")) {
            return;
        }

        StruggleSessionManager manager = StruggleSessionManager.getInstance();
        ContinuousStruggleMiniGameState session =
            manager.getContinuousStruggleSession(player.getUUID());

        if (session == null) {
            TiedUpMod.LOGGER.debug(
                "[PacketContinuousStruggleHold] No active session for {}",
                player.getName().getString()
            );
            return;
        }

        // Validate session ID
        if (!session.getSessionId().equals(sessionId)) {
            TiedUpMod.LOGGER.debug(
                "[PacketContinuousStruggleHold] Session ID mismatch for {}",
                player.getName().getString()
            );
            return;
        }

        // Update held direction
        session.updateHeldDirection(heldDirection, isHolding);
    }

    // Getters
    public UUID getSessionId() {
        return sessionId;
    }

    public int getHeldDirection() {
        return heldDirection;
    }

    public boolean isHolding() {
        return isHolding;
    }
}
