package com.tiedup.remake.commands.subcommands;

import com.mojang.brigadier.arguments.FloatArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.tiedup.remake.items.base.AdjustmentHelper;
import com.tiedup.remake.items.ModItems;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.tiedup.remake.commands.CommandHelper;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.ChatFormatting;
import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.state.PlayerBindState;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;

@SuppressWarnings("null")
public class AccessoryCommands {

    public static void register(LiteralArgumentBuilder<CommandSourceStack> root) {
        // /tiedup putearplugs <player>
        root.then(
            Commands.literal("putearplugs")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(AccessoryCommands::putearplugs)
                )
        );
        // /tiedup takeearplugs <player>
        root.then(
            Commands.literal("takeearplugs")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(AccessoryCommands::takeearplugs)
                )
        );
        // /tiedup putclothes <player>
        root.then(
            Commands.literal("putclothes")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(AccessoryCommands::putclothes)
                )
        );
        // /tiedup takeclothes <player>
        root.then(
            Commands.literal("takeclothes")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(AccessoryCommands::takeclothes)
                )
        );
        // /tiedup fullyrestrain <player>
        root.then(
            Commands.literal("fullyrestrain")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(AccessoryCommands::fullyrestrain)
                )
        );
        // /tiedup adjust <player> <type:gag|blindfold|all> <value>
        root.then(
            Commands.literal("adjust")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument("player", EntityArgument.player()).then(
                        Commands.argument("type", StringArgumentType.word())
                            .suggests((ctx, builder) -> {
                                builder.suggest("gag");
                                builder.suggest("blindfold");
                                builder.suggest("all");
                                return builder.buildFuture();
                            })
                            .then(
                                Commands.argument(
                                    "value",
                                    FloatArgumentType.floatArg(-4.0f, 4.0f)
                                ).executes(AccessoryCommands::adjust)
                            )
                    )
                )
        );
    }

    static int putearplugs(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);

        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        if (state.hasEarplugs()) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable(
                        "command.tiedup.accessory.already_earplugs",
                        targetPlayer.getName().getString()
                    )
                );
            return 0;
        }

        ItemStack earplugs = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "classic_earplugs"));
        state.putEarplugsOn(earplugs);
        CommandHelper.syncPlayerState(targetPlayer, state);

        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.accessory.earplugs_on",
                        targetPlayer.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
        SystemMessageManager.sendToTarget(
            context.getSource().getEntity(),
            targetPlayer,
            SystemMessageManager.MessageCategory.EARPLUGS_ON
        );

        return 1;
    }

    static int takeearplugs(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);

        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        if (!state.hasEarplugs()) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable(
                        "command.tiedup.accessory.no_earplugs",
                        targetPlayer.getName().getString()
                    )
                );
            return 0;
        }

        state.takeEarplugsOff();
        CommandHelper.syncPlayerState(targetPlayer, state);

        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.accessory.earplugs_removed",
                        targetPlayer.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
        SystemMessageManager.sendToPlayer(
            targetPlayer,
            SystemMessageManager.MessageCategory.INFO,
            "Your earplugs have been removed!"
        );

        return 1;
    }

    static int putclothes(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);

        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        if (state.hasClothes()) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable(
                        "command.tiedup.accessory.already_clothes",
                        targetPlayer.getName().getString()
                    )
                );
            return 0;
        }

        ItemStack clothes = new ItemStack(ModItems.CLOTHES.get());
        state.putClothesOn(clothes);
        CommandHelper.syncPlayerState(targetPlayer, state);

        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.accessory.clothes_on",
                        targetPlayer.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );

        return 1;
    }

    static int takeclothes(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);

        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        if (!state.hasClothes()) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable(
                        "command.tiedup.accessory.no_clothes",
                        targetPlayer.getName().getString()
                    )
                );
            return 0;
        }

        ItemStack removed = state.takeClothesOff();
        CommandHelper.syncPlayerState(targetPlayer, state);

        if (!removed.isEmpty()) {
            targetPlayer.drop(removed, false);
        }

        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.accessory.clothes_removed",
                        targetPlayer.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
        return 1;
    }

    static int fullyrestrain(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);

        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        int applied = 0;

        if (!state.isTiedUp()) {
            ItemStack ropes = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "ropes"));
            state.putBindOn(ropes);
            applied++;
        }

        if (!state.isGagged()) {
            ItemStack gag = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "cloth_gag"));
            state.putGagOn(gag);
            applied++;
        }

        if (!state.isBlindfolded()) {
            ItemStack blindfold = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "classic_blindfold"));
            state.putBlindfoldOn(blindfold);
            applied++;
        }

        if (!state.hasCollar()) {
            ItemStack collar = com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.createStack(net.minecraft.resources.ResourceLocation.fromNamespaceAndPath("tiedup", "classic_collar"));
            if (
                context.getSource().getEntity() instanceof ServerPlayer executor
            ) {
                CollarHelper.addOwner(collar, executor);
            }
            state.putCollarOn(collar);
            applied++;
        }

        if (!state.hasEarplugs()) {
            ItemStack earplugs = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "classic_earplugs"));
            state.putEarplugsOn(earplugs);
            applied++;
        }

        if (applied == 0) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable(
                        "command.tiedup.accessory.already_restrained",
                        targetPlayer.getName().getString()
                    )
                );
            return 0;
        }

        CommandHelper.syncPlayerState(targetPlayer, state);

        int finalApplied = applied;
        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.accessory.fully_restrained",
                        targetPlayer.getName().getString(),
                        finalApplied
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
        SystemMessageManager.sendToPlayer(
            targetPlayer,
            SystemMessageManager.MessageCategory.INFO,
            "You have been fully restrained!"
        );

        return 1;
    }

    static int adjust(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        String type = StringArgumentType.getString(context, "type");
        float value = FloatArgumentType.getFloat(context, "value");

        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);
        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        boolean adjustedGag = false;
        boolean adjustedBlindfold = false;

        if (type.equals("gag") || type.equals("all")) {
            ItemStack gag = state.getEquipment(
                com.tiedup.remake.v2.BodyRegionV2.MOUTH
            );
            if (!gag.isEmpty()) {
                AdjustmentHelper.setAdjustment(gag, value);
                adjustedGag = true;
            }
        }

        if (type.equals("blindfold") || type.equals("all")) {
            ItemStack blindfold = state.getEquipment(
                com.tiedup.remake.v2.BodyRegionV2.EYES
            );
            if (!blindfold.isEmpty()) {
                AdjustmentHelper.setAdjustment(blindfold, value);
                adjustedBlindfold = true;
            }
        }

        if (
            !type.equals("gag") &&
            !type.equals("blindfold") &&
            !type.equals("all")
        ) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable("command.tiedup.accessory.adjust_invalid_type")
                );
            return 0;
        }

        if (!adjustedGag && !adjustedBlindfold) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable(
                        "command.tiedup.accessory.nothing_to_adjust",
                        targetPlayer.getName().getString(),
                        type
                    )
                );
            return 0;
        }

        CommandHelper.syncPlayerState(targetPlayer, state);

        String items =
            adjustedGag && adjustedBlindfold
                ? "gag and blindfold"
                : adjustedGag
                    ? "gag"
                    : "blindfold";
        String valueStr = String.format("%.2f", value);

        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.accessory.adjusted",
                        items,
                        targetPlayer.getName().getString(),
                        valueStr
                    ).withStyle(ChatFormatting.GREEN),
                true
            );

        return 1;
    }

}
