package com.tiedup.remake.commands;

import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.sync.PacketSyncBindState;
import com.tiedup.remake.state.PlayerBindState;
import java.util.Optional;
import java.util.function.Predicate;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;

/**
 * Utility methods for command handling.
 */
public final class CommandHelper {

    /**
     * Permission level 2 (OP) requirement for commands.
     * Use with: .requires(CommandHelper.REQUIRES_OP)
     */
    public static final Predicate<CommandSourceStack> REQUIRES_OP = source ->
        source.hasPermission(2);

    private CommandHelper() {}

    /**
     * Get the player from command source, or send failure message and return empty.
     *
     * Usage:
     * <pre>
     * var playerOpt = CommandHelper.getPlayerOrFail(source);
     * if (playerOpt.isEmpty()) return 0;
     * ServerPlayer player = playerOpt.get();
     * </pre>
     *
     * @param source The command source
     * @return Optional containing the player, or empty if source is not a player
     */
    public static Optional<ServerPlayer> getPlayerOrFail(
        CommandSourceStack source
    ) {
        if (source.getEntity() instanceof ServerPlayer player) {
            return Optional.of(player);
        }
        source.sendFailure(Component.translatable("command.tiedup.error.must_be_player"));
        return Optional.empty();
    }

    /**
     * Get the player from command source without sending failure message.
     *
     * @param source The command source
     * @return Optional containing the player, or empty if source is not a player
     */
    public static Optional<ServerPlayer> getPlayer(CommandSourceStack source) {
        if (source.getEntity() instanceof ServerPlayer player) {
            return Optional.of(player);
        }
        return Optional.empty();
    }

    /**
     * Check if source is a player.
     *
     * @param source The command source
     * @return true if source is a player
     */
    public static boolean isPlayer(CommandSourceStack source) {
        return source.getEntity() instanceof ServerPlayer;
    }

    /**
     * Sync player state to client after command changes.
     *
     * @param player The player to sync
     * @param state The player's bind state
     */
    public static void syncPlayerState(
        ServerPlayer player,
        PlayerBindState state
    ) {
        // Sync V2 equipment
        com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper.sync(player);

        // Sync bind state
        PacketSyncBindState statePacket = PacketSyncBindState.fromPlayer(
            player
        );
        if (statePacket != null) {
            ModNetwork.sendToPlayer(statePacket, player);
        }
    }
}
