package top.r3944realms.lib39.base.command;

import com.mojang.brigadier.Command;
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 net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.event.RegisterCommandsEvent;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.lib39.Lib39;
import top.r3944realms.lib39.core.command.ICommandHelpManager;
import top.r3944realms.lib39.core.command.SimpleHelpCommand;

import java.util.Map;

/**
 * The type Lib 39 help command.
 */
public class Lib39HelpCommand extends SimpleHelpCommand {

    /**
     * Instantiates a new Lib 39 help command.
     *
     * @param event the event
     */
    public Lib39HelpCommand(@NotNull RegisterCommandsEvent event) {
        super(event);
        if(Lib39.shouldRegisterExamples()) {
            // 在這裡註冊測試命令
            registerTestCommands(event.getDispatcher());
        }
    }

    @Override
    public ICommandHelpManager getCommandHelpManager() {
        return Lib39CommandHelpManager.INSTANCE;
    }

    /**
     * 註冊測試命令
     */
    private void registerTestCommands(@NotNull CommandDispatcher<CommandSourceStack> dispatcher) {
        // 註冊幫助系統本身
        dispatcher.register(
                getRoot()
                .then(Commands.literal("test")
                        .executes(this::executeTest)
                        .then(Commands.argument("param", StringArgumentType.string())
                                .executes(this::executeTestWithParam))
                )
                .then(Commands.literal("demo")
                        .executes(this::executeDemo)
                )
        );

        // 註冊其他測試命令
        registerTestCommandTree(dispatcher);

        // 在幫助系統中註冊這些命令
        registerCommandsInHelpSystem();
    }

    /**
     * 註冊測試命令樹
     */
    private void registerTestCommandTree(@NotNull CommandDispatcher<CommandSourceStack> dispatcher) {
        // 基本命令
        dispatcher.register(
                Commands.literal("lib39")
                        .then(Commands.literal("greet")
                                .executes(this::executeGreet)
                                .then(Commands.argument("player", EntityArgument.player())
                                        .executes(this::executeGreetPlayer))
                        )
                        .then(Commands.literal("calculate")
                                .then(Commands.argument("a", IntegerArgumentType.integer())
                                        .then(Commands.argument("b", IntegerArgumentType.integer())
                                                .executes(this::executeCalculate)))
                        )
                        .then(Commands.literal("teleport")
                                .requires(source -> source.hasPermission(2)) // 需要OP權限
                                .then(Commands.argument("target", EntityArgument.player())
                                        .executes(this::executeTeleport))
                        )
                        .then(Commands.literal("info")
                                .executes(this::executeInfo)
                        )
        );

        // 嵌套命令示例
        dispatcher.register(
                Commands.literal("lib39")
                        .then(Commands.literal("team")
                                .then(Commands.literal("create")
                                        .then(Commands.argument("teamName", StringArgumentType.string())
                                                .executes(this::executeTeamCreate))
                                )
                                .then(Commands.literal("join")
                                        .then(Commands.argument("teamName", StringArgumentType.string())
                                                .executes(this::executeTeamJoin))
                                )
                                .then(Commands.literal("leave")
                                        .executes(this::executeTeamLeave))
                        )
                        .then(Commands.literal("game")
                                .then(Commands.literal("start")
                                        .then(Commands.argument("map", StringArgumentType.string())
                                                .executes(this::executeGameStart))
                                )
                                .then(Commands.literal("stop")
                                        .executes(this::executeGameStop))
                                .then(Commands.literal("pause")
                                        .executes(this::executeGamePause))
                                .then(Commands.literal("resume")
                                        .executes(this::executeGameResume))
                        )
        );
    }

    /**
     * 在幫助系統中註冊命令
     */
    private void registerCommandsInHelpSystem() {
        ICommandHelpManager helpManager = getCommandHelpManager();

        // 使用Builder模式註冊完整的命令樹
        helpManager.registerCommands(builder -> {
            builder.root("lib39", "commands.lib39.root")
                    .expanded(true)  // 根節點默認展開

                    // 問候命令 - 添加多個子命令
                    .branch("greet", "commands.lib39.greet.basic", greetBuilder -> {
                        greetBuilder.expanded(false);  // 默認摺疊
                        greetBuilder.leaf("hello", "commands.lib39.greet.hello");
                        greetBuilder.leaf("morning", "commands.lib39.greet.morning");
                        greetBuilder.leaf("evening", "commands.lib39.greet.evening");
                        greetBuilder.push("player", "commands.lib39.greet.player")
                                .required("player")
                                .pop();
                    })

                    // 計算命令
                    .push("calculate", "commands.lib39.calculate")
                    .required("a")
                    .required("b")
                    .pop()

                    // 傳送命令
                    .push("teleport", "commands.lib39.teleport")
                    .required("target")
                    .pop()

                    // 信息命令
                    .leaf("info", "commands.lib39.info")

                    // 隊伍系統 - 添加多個子命令
                    .branch("team", "commands.lib39.team", teamBuilder -> {
                        teamBuilder.expanded(false);  // 默認摺疊
                        teamBuilder.leaf("create", "commands.lib39.team.create")
                                .required("teamName");
                        teamBuilder.leaf("join", "commands.lib39.team.join")
                                .required("teamName");
                        teamBuilder.leaf("leave", "commands.lib39.team.leave");
                        teamBuilder.leaf("list", "commands.lib39.team.list");
                        teamBuilder.leaf("info", "commands.lib39.team.info");
                    })

                    // 遊戲系統 - 添加多個子命令
                    .branch("game", "commands.lib39.game", gameBuilder -> {
                        gameBuilder.expanded(false);  // 默認摺疊
                        gameBuilder.leaf("start", "commands.lib39.game.start")
                                .required("map");
                        gameBuilder.leaf("stop", "commands.lib39.game.stop");
                        gameBuilder.leaf("pause", "commands.lib39.game.pause");
                        gameBuilder.leaf("resume", "commands.lib39.game.resume");
                        gameBuilder.leaf("status", "commands.lib39.game.status");
                    })

                    // 設置命令
                    .leavesT(Map.of(
                            "settings", "commands.lib39.settings",
                            "config", "commands.lib39.config",
                            "reload", "commands.lib39.reload",
                            "debug", "commands.lib39.debug",
                            "demo", "commands.lib39.demo",
                            "test", "commands.lib39.test"
                    ));
        });
    }

    // ==================== 命令執行方法 ====================

    private int executeTest(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();
        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.test.success")
                                .withStyle(net.minecraft.ChatFormatting.GREEN),
                false
        );
        return Command.SINGLE_SUCCESS;
    }

    private int executeTestWithParam(CommandContext<CommandSourceStack> context) {
        String param = StringArgumentType.getString(context, "param");
        CommandSourceStack source = context.getSource();
        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.test.with_param", param)
                                .withStyle(net.minecraft.ChatFormatting.AQUA),
                false
        );
        return Command.SINGLE_SUCCESS;
    }

    private int executeDemo(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();
        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.demo.message")
                                .withStyle(net.minecraft.ChatFormatting.GOLD),
                false
        );
        return Command.SINGLE_SUCCESS;
    }

    private int executeGreet(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();
        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.greet.default")
                                .withStyle(net.minecraft.ChatFormatting.YELLOW),
                false
        );
        return Command.SINGLE_SUCCESS;
    }

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

        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.greet.player", player.getDisplayName())
                                .withStyle(net.minecraft.ChatFormatting.GREEN),
                false
        );

        player.sendSystemMessage(
                Component.translatable("commands.lib39.greet.received", source.getDisplayName())
                        .withStyle(net.minecraft.ChatFormatting.AQUA)
        );

        return Command.SINGLE_SUCCESS;
    }

    private int executeCalculate(CommandContext<CommandSourceStack> context) {
        int a = IntegerArgumentType.getInteger(context, "a");
        int b = IntegerArgumentType.getInteger(context, "b");
        int sum = a + b;

        CommandSourceStack source = context.getSource();
        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.calculate.result", a, b, sum)
                                .withStyle(net.minecraft.ChatFormatting.LIGHT_PURPLE),
                false
        );

        return Command.SINGLE_SUCCESS;
    }

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

        if (source.getEntity() instanceof ServerPlayer player) {
            player.teleportTo(
                    target.serverLevel(),
                    target.getX(),
                    target.getY(),
                    target.getZ(),
                    target.getYRot(),
                    target.getXRot()
            );

            source.sendSuccess(() ->
                            Component.translatable("commands.lib39.teleport.success", target.getDisplayName())
                                    .withStyle(net.minecraft.ChatFormatting.GREEN),
                    false
            );
        }

        return Command.SINGLE_SUCCESS;
    }

    private int executeInfo(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();
        ResourceLocation dimension = source.getLevel().dimension().location();

        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.info.message")
                                .append("\n")
                                .append(Component.translatable("commands.lib39.info.dimension", dimension))
                                .append("\n")
                                .append(Component.translatable("commands.lib39.info.position",
                                        String.format("%.1f", source.getPosition().x()),
                                        String.format("%.1f", source.getPosition().y()),
                                        String.format("%.1f", source.getPosition().z())))
                                .withStyle(net.minecraft.ChatFormatting.AQUA),
                false
        );

        return Command.SINGLE_SUCCESS;
    }

    private int executeTeamCreate(CommandContext<CommandSourceStack> context) {
        String teamName = StringArgumentType.getString(context, "teamName");
        CommandSourceStack source = context.getSource();

        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.team.create.success", teamName)
                                .withStyle(net.minecraft.ChatFormatting.GREEN),
                false
        );

        return Command.SINGLE_SUCCESS;
    }

    private int executeTeamJoin(CommandContext<CommandSourceStack> context) {
        String teamName = StringArgumentType.getString(context, "teamName");
        CommandSourceStack source = context.getSource();

        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.team.join.success", teamName)
                                .withStyle(net.minecraft.ChatFormatting.GREEN),
                false
        );

        return Command.SINGLE_SUCCESS;
    }

    private int executeTeamLeave(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();

        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.team.leave.success")
                                .withStyle(net.minecraft.ChatFormatting.YELLOW),
                false
        );

        return Command.SINGLE_SUCCESS;
    }

    private int executeGameStart(CommandContext<CommandSourceStack> context) {
        String map = StringArgumentType.getString(context, "map");
        CommandSourceStack source = context.getSource();

        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.game.start.success", map)
                                .withStyle(net.minecraft.ChatFormatting.GREEN),
                false
        );

        return Command.SINGLE_SUCCESS;
    }

    private int executeGameStop(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();

        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.game.stop.success")
                                .withStyle(net.minecraft.ChatFormatting.RED),
                false
        );

        return Command.SINGLE_SUCCESS;
    }

    private int executeGamePause(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();

        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.game.pause.success")
                                .withStyle(net.minecraft.ChatFormatting.YELLOW),
                false
        );

        return Command.SINGLE_SUCCESS;
    }

    private int executeGameResume(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();

        source.sendSuccess(() ->
                        Component.translatable("commands.lib39.game.resume.success")
                                .withStyle(net.minecraft.ChatFormatting.GREEN),
                false
        );

        return Command.SINGLE_SUCCESS;
    }
}
