package de.winniepat.citrus.client;

import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.*;
import de.winniepat.citrus.Client;
import de.winniepat.citrus.cosmetics.capes.*;
import de.winniepat.citrus.cosmetics.capes.sync.CapeSyncManager;
import de.winniepat.citrus.cosmetics.wings.ClientWingManager;
import de.winniepat.citrus.managers.ClientRegistrationManager;
import de.winniepat.citrus.gui.*;
import icyllis.modernui.mc.MuiModApi;
import net.fabricmc.fabric.api.client.command.v2.*;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.UUID;

public class ClientCommands {

    public static void register() {
        ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {

            LiteralArgumentBuilder<FabricClientCommandSource> citrusCommand =
                    LiteralArgumentBuilder.<FabricClientCommandSource>literal("citrus")
                            .executes(context -> {
                                context.getSource().sendFeedback(Text.literal("§f#### §aCitrus §7- by WinniePatGG §f####"));
                                context.getSource().sendFeedback(Text.literal("§7Version: §7" + Client.CLIENT_BUILD));
                                context.getSource().sendFeedback(Text.literal(""));
                                context.getSource().sendFeedback(Text.literal("§7Available commands:"));
                                context.getSource().sendFeedback(Text.literal("§e/citrus cape set <cape_name> §7- Set your cape"));
                                context.getSource().sendFeedback(Text.literal("§e/citrus cape reload §7- Reload available capes from cdn"));
                                context.getSource().sendFeedback(Text.literal(""));
                                context.getSource().sendFeedback(Text.literal("§e/citrus capesync clearcache §7- Clear cape sync cache"));
                                context.getSource().sendFeedback(Text.literal("§e/citrus capesync forcefetch §7- Force fetch capes for all players"));
                                context.getSource().sendFeedback(Text.literal(""));
                                context.getSource().sendFeedback(Text.literal("§e/citrus wings toggle §7- Toggle wings visibility"));
                                context.getSource().sendFeedback(Text.literal("§e/citrus wings set <wing_type> §7- Set your wing type"));
                                context.getSource().sendFeedback(Text.literal("§e/citrus wings list §7- List available wing types"));
                                context.getSource().sendFeedback(Text.literal(""));
                                context.getSource().sendFeedback(Text.literal("§e/citrus status §7- Show Citrus status"));
                                context.getSource().sendFeedback(Text.literal("§e/citrus screen <name> §7- Open a client screen"));
                                return 1;
                            });

            citrusCommand.then(LiteralArgumentBuilder.<FabricClientCommandSource>literal("screen")
                    .then(RequiredArgumentBuilder
                            .<FabricClientCommandSource, String>argument("name", StringArgumentType.word())
                            .suggests((context, builder) -> {
                                builder.suggest("showcase");
                                builder.suggest("friends");
                                builder.suggest("profiles");
                                builder.suggest("hud");
                                builder.suggest("menu");
                                return builder.buildFuture();
                            })
                            .executes(context -> {
                                String name = StringArgumentType.getString(context, "name").toLowerCase();
                                MinecraftClient client = MinecraftClient.getInstance();

                                client.execute(() -> {
                                    switch (name) {
                                        case "friends" -> client.setScreen(MuiModApi.get().createScreen(new FriendsFragment(), null, client.currentScreen));
                                        case "profiles" -> client.setScreen(MuiModApi.get().createScreen(new ProfileScreen(), null, client.currentScreen));
                                        case "hud" -> client.setScreen(MuiModApi.get().createScreen(new HudEditorFragment(), null, client.currentScreen));
                                        case "menu" -> client.setScreen(MuiModApi.get().createScreen(new MainMenuScreen(), null, null));
                                        case "showcase" -> client.setScreen(MuiModApi.get().createScreen(new TestScreen(), null, client.currentScreen));
                                        default -> context.getSource().sendError(Text.literal("§cUnknown screen: §e" + name));
                                    }
                                });

                                return 1;
                            })
                    )
            );

            citrusCommand.then(LiteralArgumentBuilder.<FabricClientCommandSource>literal("cape")
                    .then(LiteralArgumentBuilder.<FabricClientCommandSource>literal("set")
                            .then(RequiredArgumentBuilder
                                    .<FabricClientCommandSource, String>argument("cape_name", StringArgumentType.string())
                                    .suggests((context, builder) -> {
                                        builder.suggest("none");
                                        builder.suggest("auto");
                                        for (String cape : CapeHandler.getAvailableCapes()) {
                                            builder.suggest(cape);
                                        }
                                        return builder.buildFuture();
                                    })
                                    .executes(context -> {
                                        String capeName = StringArgumentType.getString(context, "cape_name");
                                        MinecraftClient client = MinecraftClient.getInstance();

                                        if (client.player == null) {
                                            context.getSource().sendError(Text.literal("§cYou must be in-game!"));
                                            return 0;
                                        }

                                        if (CapeHandler.capeExists(capeName)) {
                                            CapeHandler.setLocalPlayerCape(capeName, false);
                                            context.getSource().sendFeedback(Text.literal("§aCape set to: §e" + capeName));
                                        } else {
                                            context.getSource().sendError(Text.literal("§cUnknown cape: " + capeName));
                                        }
                                        return 1;
                                    })
                            )
                    )
                    .then(LiteralArgumentBuilder.<FabricClientCommandSource>literal("reload")
                            .executes(context -> {
                                context.getSource().sendFeedback(Text.literal("§aReloading capes..."));
                                CapeHandler.reloadCapes();
                                return 1;
                            })
                    )
            );

            citrusCommand.then(LiteralArgumentBuilder.<FabricClientCommandSource>literal("capesync")
                    .then(LiteralArgumentBuilder.<FabricClientCommandSource>literal("clearcache")
                            .executes(context -> {
                                CapeSyncManager.clearAllCache();
                                context.getSource().sendFeedback(Text.literal("§aCache cleared."));
                                return 1;
                            })
                    )
                    .then(LiteralArgumentBuilder.<FabricClientCommandSource>literal("forcefetch")
                            .executes(context -> {
                                MinecraftClient client = MinecraftClient.getInstance();

                                if (client.player == null || client.world == null) {
                                    context.getSource().sendError(Text.literal("§cYou must be in-game!"));
                                    return 0;
                                }

                                List<UUID> playerUUIDs = client.world.getPlayers().stream()
                                        .filter(p -> p != client.player)
                                        .map(PlayerEntity::getUuid)
                                        .toList();

                                CapeSyncManager.batchFetchCapes(playerUUIDs);
                                context.getSource().sendFeedback(Text.literal(
                                        "§aFetching capes for §e" + playerUUIDs.size() + "§a players..."
                                ));
                                return 1;
                            })
                    )
            );

            citrusCommand.then(LiteralArgumentBuilder.<FabricClientCommandSource>literal("status")
                    .executes(context -> {
                        context.getSource().sendFeedback(Text.literal("--- §aCitrus Status §7---"));
                        context.getSource().sendFeedback(Text.literal(""));

                        boolean healthy = CapeSyncManager.isIsHealthy();
                        String serverHealth = healthy
                                ? "§ahealthy"
                                : "§cexperiencing issues or is offline";
                        context.getSource().sendFeedback(Text.literal("CapeSync Server: " + serverHealth));

                        int capesAvailable = CapeHandler.getAvailableCapes().size();
                        context.getSource().sendFeedback(Text.literal("§aCapes available: §e" + capesAvailable));

                        MinecraftClient client = MinecraftClient.getInstance();
                        if (client.player != null) {
                            String activeWings = de.winniepat.citrus.cosmetics.wings.ClientWingManager.getActiveWings(client.player.getUuid());
                            boolean wingsVisible = ClientWingManager.areWingsVisible(client.player.getUuid());
                            String wingStatus = "§aWing type: §e" + activeWings + "§a, " + (wingsVisible ? "§avisible" : "§chidden");
                            context.getSource().sendFeedback(Text.literal(wingStatus));
                        }

                        String registrationStatus = getRegistrationStatus(healthy);
                        context.getSource().sendFeedback(Text.literal("Registration: " + registrationStatus));

                        return 1;
                    })
            );

            dispatcher.register(citrusCommand);
        });
    }

    private static @NotNull String getRegistrationStatus(boolean healthy) {
        boolean registered = ClientRegistrationManager.isRegistered();

        String registrationStatus = registered
                ? "§aYou are registered with the Citrus API"
                : "§cYou are not registered with the Citrus API";

        if (!healthy && registered) {
            registrationStatus += " §7(§eStatus may be inaccurate because Backend has issues or is offline§7)";
        }
        return registrationStatus;
    }
}