package com.tiedup.remake.commands;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.tiedup.remake.client.gltf.diagnostic.GlbDiagnostic;
import com.tiedup.remake.client.gltf.diagnostic.GlbDiagnosticRegistry;
import com.tiedup.remake.client.gltf.diagnostic.GlbValidationResult;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

/**
 * Client-only command: /tiedup validate [item_id]
 *
 * Displays GLB validation diagnostics in chat.
 * Registered via {@link net.minecraftforge.client.event.RegisterClientCommandsEvent}
 * on the FORGE bus (never on the server).
 */
@OnlyIn(Dist.CLIENT)
public final class ValidateGlbCommand {

    private ValidateGlbCommand() {}

    public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
        dispatcher.register(
            Commands.literal("tiedup")
                .then(Commands.literal("validate")
                    .executes(ctx -> validateAll(ctx.getSource()))
                    .then(Commands.argument("item_id", StringArgumentType.string())
                        .executes(ctx -> validateOne(
                            ctx.getSource(),
                            StringArgumentType.getString(ctx, "item_id")
                        ))
                    )
                )
        );
    }

    private static int validateAll(CommandSourceStack source) {
        var all = GlbDiagnosticRegistry.getAll();
        if (all.isEmpty()) {
            source.sendSuccess(
                () -> Component.literal(
                    "[TiedUp] No GLB validation results. "
                        + "Try reloading resources (F3+T)."
                ).withStyle(ChatFormatting.YELLOW),
                false
            );
            return 0;
        }

        int totalDiags = 0;
        for (GlbValidationResult result : all) {
            if (result.diagnostics().isEmpty()) continue;
            source.sendSuccess(
                () -> Component.literal("--- " + result.source() + " ---")
                    .withStyle(
                        result.passed()
                            ? ChatFormatting.GREEN
                            : ChatFormatting.RED
                    ),
                false
            );
            for (GlbDiagnostic d : result.diagnostics()) {
                source.sendSuccess(() -> formatDiagnostic(d), false);
                totalDiags++;
            }
        }

        int count = totalDiags;
        source.sendSuccess(
            () -> Component.literal(
                "[TiedUp] " + count + " diagnostic(s) across "
                    + GlbDiagnosticRegistry.size() + " GLBs"
            ).withStyle(ChatFormatting.GRAY),
            false
        );
        return 1;
    }

    private static int validateOne(CommandSourceStack source, String itemId) {
        ResourceLocation loc = ResourceLocation.tryParse(itemId);
        if (loc == null) {
            source.sendFailure(
                Component.literal("Invalid resource location: " + itemId)
            );
            return 0;
        }

        for (GlbValidationResult result : GlbDiagnosticRegistry.getAll()) {
            boolean match = result.source().equals(loc);
            if (!match) {
                match = result.diagnostics().stream()
                    .anyMatch(d -> loc.equals(d.itemDef()));
            }
            if (match) {
                source.sendSuccess(
                    () -> Component.literal("--- " + result.source() + " ---")
                        .withStyle(
                            result.passed()
                                ? ChatFormatting.GREEN
                                : ChatFormatting.RED
                        ),
                    false
                );
                for (GlbDiagnostic d : result.diagnostics()) {
                    source.sendSuccess(() -> formatDiagnostic(d), false);
                }
                return 1;
            }
        }

        source.sendFailure(
            Component.literal("No validation results for: " + itemId)
        );
        return 0;
    }

    private static Component formatDiagnostic(GlbDiagnostic d) {
        ChatFormatting color = switch (d.severity()) {
            case ERROR -> ChatFormatting.RED;
            case WARNING -> ChatFormatting.YELLOW;
            case INFO -> ChatFormatting.GRAY;
        };
        return Component.literal(
            "  [" + d.severity() + "] " + d.code() + ": " + d.message()
        ).withStyle(color);
    }
}
