package com.tiedup.remake.commands;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.tiedup.remake.cells.CellDataV2;
import com.tiedup.remake.cells.CellRegistryV2;
import com.tiedup.remake.state.PlayerBindState;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.tiedup.remake.util.teleport.Position;
import com.tiedup.remake.util.teleport.TeleportHelper;
import com.tiedup.remake.v2.BodyRegionV2;
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.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;

/**
 * Collar management commands.
 *
 * Commands:
 *   /collar claim <player> - Claim ownership of a player's collar
 *   /collar unclaim <player> - Remove your ownership
 *   /collar rename <player> <name> - Set alias for collar
 *   /collar addowner <target> <owner> - Add another owner
 *   /collar removeowner <target> <owner> - Remove an owner
 *   /collar sethome <player> - Set home location
 *   /collar setprison <player> - Set prison location (legacy)
 *   /collar setcell <player> <cellname> - Assign cell to collar (preferred)
 *   /collar prisonradius <player> <radius> - Set prison fence radius (legacy)
 *   /collar prisonfence <player> [on/off] - Toggle prison fence (legacy)
 *   /collar backhome <player> - Teleport slave back home
 *   /collar info <player> - Show collar info
 *
 * Requires OP level 2.
 */
public class CollarCommand {

    public static void register(
        CommandDispatcher<CommandSourceStack> dispatcher
    ) {
        dispatcher.register(createCollarCommand());
    }

    /**
     * Create the collar command builder (for use as subcommand of /tiedup).
     * @return The command builder
     */
    public static com.mojang.brigadier.builder.LiteralArgumentBuilder<
        CommandSourceStack
    > createCollarCommand() {
        return Commands.literal("collar")
            .requires(CommandHelper.REQUIRES_OP)
            // /collar claim <player>
            .then(
                Commands.literal("claim").then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(CollarCommand::claim)
                )
            )
            // /collar unclaim <player>
            .then(
                Commands.literal("unclaim").then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(CollarCommand::unclaim)
                )
            )
            // /collar rename <player> <name>
            .then(
                Commands.literal("rename").then(
                    Commands.argument("player", EntityArgument.player()).then(
                        Commands.argument(
                            "name",
                            StringArgumentType.greedyString()
                        ).executes(CollarCommand::rename)
                    )
                )
            )
            // /collar addowner <target> <owner>
            .then(
                Commands.literal("addowner").then(
                    Commands.argument("target", EntityArgument.player()).then(
                        Commands.argument(
                            "owner",
                            EntityArgument.player()
                        ).executes(CollarCommand::addOwner)
                    )
                )
            )
            // /collar removeowner <target> <owner>
            .then(
                Commands.literal("removeowner").then(
                    Commands.argument("target", EntityArgument.player()).then(
                        Commands.argument(
                            "owner",
                            EntityArgument.player()
                        ).executes(CollarCommand::removeOwner)
                    )
                )
            )
            // /collar setcell <player> <cellname> (assigns cell)
            .then(
                Commands.literal("setcell").then(
                    Commands.argument("player", EntityArgument.player()).then(
                        Commands.argument(
                            "cellname",
                            StringArgumentType.word()
                        ).executes(CollarCommand::setCell)
                    )
                )
            )
            // /collar tocell <player> (teleport to assigned cell)
            .then(
                Commands.literal("tocell").then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(CollarCommand::teleportToCell)
                )
            )
            // /collar info <player>
            .then(
                Commands.literal("info").then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(CollarCommand::info)
                )
            );
    }

    private static ItemStack getPlayerCollar(ServerPlayer player) {
        PlayerBindState state = PlayerBindState.getInstance(player);
        if (state == null || !state.hasCollar()) return ItemStack.EMPTY;
        return state.getEquipment(BodyRegionV2.NECK);
    }

    private static int claim(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        ServerPlayer target = EntityArgument.getPlayer(context, "player");

        ItemStack collar = getPlayerCollar(target);
        if (collar.isEmpty()) {
            source.sendFailure(
                Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString())
            );
            return 0;
        }

        if (source.getEntity() instanceof ServerPlayer executor) {
            if (CollarHelper.isCollar(collar)) {
                CollarHelper.addOwner(collar, executor);
                source.sendSuccess(
                    () ->
                        Component.translatable(
                            "command.tiedup.collar_cmd.claimed", target.getName().getString()
                        ).withStyle(ChatFormatting.GREEN),
                    true
                );
                return 1;
            }
        }

        source.sendFailure(Component.translatable("command.tiedup.collar_cmd.claim_failed"));
        return 0;
    }

    private static int unclaim(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        ServerPlayer target = EntityArgument.getPlayer(context, "player");

        ItemStack collar = getPlayerCollar(target);
        if (collar.isEmpty()) {
            source.sendFailure(
                Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString())
            );
            return 0;
        }

        if (source.getEntity() instanceof ServerPlayer executor) {
            if (CollarHelper.isCollar(collar)) {
                CollarHelper.removeOwner(collar, executor.getUUID());
                source.sendSuccess(
                    () ->
                        Component.translatable(
                            "command.tiedup.collar_cmd.unclaimed", target.getName().getString()
                        ).withStyle(ChatFormatting.GREEN),
                    true
                );
                return 1;
            }
        }

        source.sendFailure(Component.translatable("command.tiedup.collar_cmd.unclaim_failed"));
        return 0;
    }

    private static int rename(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        ServerPlayer target = EntityArgument.getPlayer(context, "player");
        String name = StringArgumentType.getString(context, "name");

        ItemStack collar = getPlayerCollar(target);
        if (collar.isEmpty()) {
            source.sendFailure(
                Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString())
            );
            return 0;
        }

        if (CollarHelper.isCollar(collar)) {
            CollarHelper.setNickname(collar, name);
            source.sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar_cmd.renamed", name
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
            return 1;
        }

        return 0;
    }

    private static int addOwner(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        ServerPlayer target = EntityArgument.getPlayer(context, "target");
        ServerPlayer owner = EntityArgument.getPlayer(context, "owner");

        ItemStack collar = getPlayerCollar(target);
        if (collar.isEmpty()) {
            source.sendFailure(
                Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString())
            );
            return 0;
        }

        if (CollarHelper.isCollar(collar)) {
            CollarHelper.addOwner(collar, owner);
            source.sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar_cmd.owner_added",
                        owner.getName().getString(),
                        target.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
            return 1;
        }

        return 0;
    }

    private static int removeOwner(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        ServerPlayer target = EntityArgument.getPlayer(context, "target");
        ServerPlayer owner = EntityArgument.getPlayer(context, "owner");

        ItemStack collar = getPlayerCollar(target);
        if (collar.isEmpty()) {
            source.sendFailure(
                Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString())
            );
            return 0;
        }

        if (CollarHelper.isCollar(collar)) {
            CollarHelper.removeOwner(collar, owner.getUUID());
            source.sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar_cmd.owner_removed",
                        owner.getName().getString(),
                        target.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
            return 1;
        }

        return 0;
    }

    /**
     * /collar setcell <player> <cellname>
     *
     * Assign a named cell to a player's collar.
     */
    private static int setCell(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        ServerPlayer target = EntityArgument.getPlayer(context, "player");
        String cellName = StringArgumentType.getString(context, "cellname");

        ItemStack collar = getPlayerCollar(target);
        if (collar.isEmpty()) {
            source.sendFailure(
                Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString())
            );
            return 0;
        }

        // Get the cell by name
        ServerLevel serverLevel = source.getLevel();
        CellRegistryV2 registry = CellRegistryV2.get(serverLevel);
        CellDataV2 cell = registry.getCellByName(cellName);

        if (cell == null) {
            source.sendFailure(
                Component.translatable("command.tiedup.collar_cmd.cell_not_found", cellName)
            );
            return 0;
        }

        if (CollarHelper.isCollar(collar)) {
            CollarHelper.setCellId(collar, cell.getId());
            source.sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar_cmd.cell_assigned",
                        cellName,
                        target.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
            return 1;
        }

        return 0;
    }

    /**
     * /collar tocell <player>
     *
     * Teleport player to their assigned cell.
     */
    private static int teleportToCell(
        CommandContext<CommandSourceStack> context
    ) throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        ServerPlayer target = EntityArgument.getPlayer(context, "player");

        ItemStack collar = getPlayerCollar(target);
        if (collar.isEmpty()) {
            source.sendFailure(
                Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString())
            );
            return 0;
        }

        if (CollarHelper.isCollar(collar)) {
            if (!CollarHelper.hasCellAssigned(collar)) {
                source.sendFailure(
                    Component.translatable("command.tiedup.collar_cmd.no_cell_assigned")
                );
                return 0;
            }

            // Get cell position and teleport
            java.util.UUID cellId = CollarHelper.getCellId(collar);
            ServerLevel serverLevel = source.getLevel();
            CellDataV2 cell = CellRegistryV2.get(serverLevel).getCell(cellId);

            if (cell == null) {
                source.sendFailure(
                    Component.translatable("command.tiedup.collar_cmd.cell_deleted")
                );
                return 0;
            }

            net.minecraft.core.BlockPos teleportTarget =
                cell.getSpawnPoint() != null
                    ? cell.getSpawnPoint()
                    : cell.getCorePos().above();
            Position cellPos = new Position(
                teleportTarget,
                serverLevel.dimension()
            );
            TeleportHelper.teleportEntity(target, cellPos);

            source.sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar_cmd.teleported",
                        target.getName().getString(),
                        cell.getCorePos().toShortString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
            return 1;
        }

        return 0;
    }

    private static int info(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        CommandSourceStack source = context.getSource();
        ServerPlayer target = EntityArgument.getPlayer(context, "player");

        ItemStack collar = getPlayerCollar(target);
        if (collar.isEmpty()) {
            source.sendFailure(
                Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString())
            );
            return 0;
        }

        if (CollarHelper.isCollar(collar)) {
            source.sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar_cmd.info_header",
                        target.getName().getString()
                    ).withStyle(ChatFormatting.GOLD),
                false
            );

            String nickname = CollarHelper.getNickname(collar);
            String nicknameDisplay = (nickname == null || nickname.isEmpty()) ? "None" : nickname;
            source.sendSuccess(
                () ->
                    Component.translatable("command.tiedup.collar_cmd.info_nickname", nicknameDisplay).withStyle(ChatFormatting.GRAY),
                false
            );
            source.sendSuccess(
                () ->
                    Component.translatable("command.tiedup.collar_cmd.info_has_owner", String.valueOf(CollarHelper.hasOwner(collar))).withStyle(ChatFormatting.GRAY),
                false
            );
            // Cell assignment
            java.util.UUID cellId = CollarHelper.getCellId(collar);
            if (cellId != null) {
                ServerLevel serverLevel = source.getLevel();
                CellRegistryV2 registry = CellRegistryV2.get(serverLevel);
                CellDataV2 cell = registry.getCell(cellId);
                if (cell != null) {
                    String cellDisplay =
                        cell.getName() != null
                            ? cell.getName()
                            : cellId.toString().substring(0, 8) + "...";
                    source.sendSuccess(
                        () ->
                            Component.translatable(
                                "command.tiedup.collar_cmd.info_cell",
                                cellDisplay,
                                cell.getCorePos().toShortString()
                            ).withStyle(ChatFormatting.GRAY),
                        false
                    );
                } else {
                    source.sendSuccess(
                        () -> Component.translatable("command.tiedup.collar_cmd.info_cell_deleted").withStyle(ChatFormatting.RED),
                        false
                    );
                }
            } else {
                source.sendSuccess(
                    () -> Component.translatable("command.tiedup.collar_cmd.info_cell_none").withStyle(ChatFormatting.GRAY),
                    false
                );
            }

            boolean locked = collar.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable
                && lockable.isLocked(collar);
            source.sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar_cmd.info_locked", String.valueOf(locked)
                    ).withStyle(ChatFormatting.GRAY),
                false
            );

            return 1;
        }

        return 0;
    }
}
