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

import com.tiedup.remake.core.SettingsAccessor;
import com.tiedup.remake.items.base.IHasResistance;
import com.tiedup.remake.items.base.ILockable;
import com.tiedup.remake.minigame.ContinuousStruggleMiniGameState;
import com.tiedup.remake.minigame.StruggleSessionManager;
import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.PacketRateLimiter;
import com.tiedup.remake.network.minigame.PacketContinuousStruggleState;
import com.tiedup.remake.v2.BodyRegionV2;
import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper;
import java.util.function.Supplier;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.network.NetworkEvent;

/**
 * C2S packet: player starts a struggle minigame against a V2 item in a region.
 *
 * <p>Flow:
 * <ol>
 *   <li>Client sends this packet with the target {@link BodyRegionV2}</li>
 *   <li>Server validates: region occupied, item has resistance</li>
 *   <li>Server creates a {@link ContinuousStruggleMiniGameState} via
 *       {@link MiniGameSessionManager#startV2StruggleSession}</li>
 *   <li>Server sends {@link PacketContinuousStruggleState}(START) back to open the minigame GUI</li>
 * </ol>
 *
 * <p>Rate limited under the "ui" bucket (3 tokens, 0.5/sec refill) since this is
 * a screen-opening action, not a per-tick input.
 */
public class PacketV2StruggleStart {

    private final BodyRegionV2 region;

    public PacketV2StruggleStart(BodyRegionV2 region) {
        this.region = region;
    }

    public BodyRegionV2 getRegion() {
        return region;
    }

    public static void encode(PacketV2StruggleStart msg, FriendlyByteBuf buf) {
        buf.writeEnum(msg.region);
    }

    public static PacketV2StruggleStart decode(FriendlyByteBuf buf) {
        return new PacketV2StruggleStart(buf.readEnum(BodyRegionV2.class));
    }

    public static void handle(
        PacketV2StruggleStart msg,
        Supplier<NetworkEvent.Context> ctxSupplier
    ) {
        NetworkEvent.Context ctx = ctxSupplier.get();
        ctx.enqueueWork(() -> {
            ServerPlayer player = ctx.getSender();
            if (player == null) return;
            if (!PacketRateLimiter.allowPacket(player, "ui")) return;

            handleServer(player, msg.region);
        });
        ctx.setPacketHandled(true);
    }

    private static void handleServer(ServerPlayer player, BodyRegionV2 region) {
        ItemStack stack = V2EquipmentHelper.getInRegion(player, region);
        if (stack.isEmpty()) return;

        if (!(stack.getItem() instanceof IHasResistance resistanceItem)) return;

        // BUG-002 fix: respect canBeStruggledOut flag
        if (!resistanceItem.canBeStruggledOut(stack)) return;

        // RISK-002 fix: respect server config
        if (
            !SettingsAccessor.isStruggleMiniGameEnabled()
        ) return;

        int resistance = resistanceItem.getCurrentResistance(stack, player);
        boolean isLocked = false;
        if (stack.getItem() instanceof ILockable lockable) {
            isLocked = lockable.isLocked(stack);
            if (isLocked) {
                // Only add padlock bonus on FIRST session (fresh resistance = base).
                // If resistance was already decremented and persisted from a prior
                // interrupted session, the padlock bonus is already baked in.
                int baseResistance = resistance; // getCurrentResistance returns base if no NBT
                com.tiedup.remake.v2.bondage.component.ResistanceComponent comp =
                    com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.getComponent(
                        stack, com.tiedup.remake.v2.bondage.component.ComponentType.RESISTANCE,
                        com.tiedup.remake.v2.bondage.component.ResistanceComponent.class);
                if (comp != null) {
                    baseResistance = comp.getBaseResistance();
                }
                if (resistance >= baseResistance) {
                    // Fresh or fully restored — add padlock bonus
                    resistance += com.tiedup.remake.core.SettingsAccessor.getPadlockResistance(null);
                }
            }
        }

        // RISK-003 fix: no point starting a session with 0 resistance
        if (resistance <= 0) return;

        StruggleSessionManager manager = StruggleSessionManager.getInstance();
        ContinuousStruggleMiniGameState session =
            manager.startV2StruggleSession(
                player,
                region,
                resistance,
                isLocked
            );

        if (session != null) {
            ModNetwork.sendToPlayer(
                new PacketContinuousStruggleState(
                    session.getSessionId(),
                    ContinuousStruggleMiniGameState.UpdateType.START,
                    session.getCurrentDirection().getIndex(),
                    session.getCurrentResistance(),
                    session.getMaxResistance(),
                    isLocked
                ),
                player
            );
        }
    }
}
