package com.tiedup.remake.commands;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.tiedup.remake.bounty.Bounty;
import com.tiedup.remake.bounty.BountyManager;
import com.tiedup.remake.core.SettingsAccessor;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.state.IBondageState;
import com.tiedup.remake.util.KidnappedHelper;
import java.util.Optional;
import net.minecraft.ChatFormatting;
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;

/**
 * Command: /bounty <player>
 *
 *
 * Creates a bounty on a target player using the held item as reward.
 *
 * Requirements:
 * - Must hold an item (the reward)
 * - Cannot put bounty on yourself
 * - Respects max bounties limit
 * - Cannot be tied up when creating bounty
 */
public class BountyCommand {

    public static void register(
        CommandDispatcher<CommandSourceStack> dispatcher
    ) {
        dispatcher.register(createBountyCommand());
        TiedUpMod.LOGGER.info("Registered /bounty command");
    }

    /**
     * Create the bounty command builder (for use as subcommand of /tiedup).
     * @return The command builder
     */
    public static com.mojang.brigadier.builder.LiteralArgumentBuilder<
        CommandSourceStack
    > createBountyCommand() {
        return Commands.literal("bounty").then(
            Commands.argument("target", EntityArgument.player()).executes(
                BountyCommand::execute
            )
        );
    }

    private static int execute(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();

        // Must be a player
        Optional<ServerPlayer> playerOpt = CommandHelper.getPlayerOrFail(
            source
        );
        if (playerOpt.isEmpty()) return 0;
        ServerPlayer player = playerOpt.get();

        ServerPlayer target = EntityArgument.getPlayer(context, "target");

        // Cannot bounty yourself
        if (player.getUUID().equals(target.getUUID())) {
            source.sendFailure(
                Component.translatable(
                    "command.tiedup.bounty.cannot_self"
                ).withStyle(ChatFormatting.RED)
            );
            return 0;
        }

        // Check if player is tied up
        IBondageState playerState = KidnappedHelper.getKidnappedState(player);
        if (playerState != null && playerState.isTiedUp()) {
            source.sendFailure(
                Component.translatable(
                    "command.tiedup.bounty.tied_up"
                ).withStyle(ChatFormatting.RED)
            );
            return 0;
        }

        // Get bounty manager
        BountyManager manager = BountyManager.get(player.serverLevel());

        // Check bounty limit
        if (!manager.canCreateBounty(player, player.serverLevel())) {
            int max = SettingsAccessor.getMaxBounties(
                player.serverLevel().getGameRules()
            );
            source.sendFailure(
                Component.translatable(
                    "command.tiedup.bounty.max_reached", max
                ).withStyle(ChatFormatting.RED)
            );
            return 0;
        }

        // Must hold an item as reward
        ItemStack heldItem = player.getMainHandItem();
        if (heldItem.isEmpty()) {
            source.sendFailure(
                Component.translatable(
                    "command.tiedup.bounty.must_hold_item"
                ).withStyle(ChatFormatting.RED)
            );
            return 0;
        }

        // Get bounty duration
        int duration = SettingsAccessor.getBountyDuration(
            player.serverLevel().getGameRules()
        );

        // SECURITY FIX: Create reward with count=1 to prevent item duplication
        // Bug: If player held 64 diamonds, bounty would be 64 diamonds but only cost 1
        ItemStack rewardItem = heldItem.copy();
        rewardItem.setCount(1);

        // Create the bounty
        Bounty bounty = new Bounty(
            player.getUUID(),
            player.getName().getString(),
            target.getUUID(),
            target.getName().getString(),
            rewardItem,
            duration
        );

        // Consume one item from the stack (not the entire stack!)
        player.getMainHandItem().shrink(1);

        // Add bounty
        manager.addBounty(bounty);

        // Notify player
        source.sendSuccess(
            () ->
                Component.translatable(
                    "command.tiedup.bounty.created", target.getName().getString()
                ).withStyle(ChatFormatting.GREEN),
            false
        );

        // Broadcast to all players
        player.server
            .getPlayerList()
            .broadcastSystemMessage(
                Component.translatable(
                    "command.tiedup.bounty.broadcast",
                    player.getName().getString(),
                    target.getName().getString()
                ).withStyle(ChatFormatting.GOLD),
                false
            );

        TiedUpMod.LOGGER.info(
            "[BOUNTY] {} created bounty on {} with reward {}",
            player.getName().getString(),
            target.getName().getString(),
            bounty.getRewardDescription()
        );

        return 1;
    }
}
