package com.livingworld.commands;

import com.livingworld.core.LivingWorldConstants;
import com.livingworld.modules.recovery.RecoveryModule;
import com.livingworld.modules.recovery.RecoveryRegionData;
import com.livingworld.modules.recovery.SuccessionStage;
import com.livingworld.regions.RegionCoordinate;
import com.livingworld.regions.RegionManager;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import java.util.function.Supplier;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;

/**
 * Renders an ASCII coloured grid of nearby regions showing their succession stage.
 * Usage: {@code /lw map} (7×7 grid) or {@code /lw map <radius>} (1–7, giving 3×3 to 15×15).
 */
public final class LivingWorldMapCommand {

    private static final int DEFAULT_RADIUS = 3;

    private LivingWorldMapCommand() {}

    public static LiteralArgumentBuilder<CommandSourceStack> build(Supplier<RegionManager> regionManager) {
        return Commands.literal("map")
                .executes(ctx -> executeMap(ctx.getSource(), regionManager, DEFAULT_RADIUS))
                .then(Commands.argument("radius", IntegerArgumentType.integer(1, 7))
                        .executes(ctx -> executeMap(ctx.getSource(), regionManager,
                                IntegerArgumentType.getInteger(ctx, "radius"))));
    }

    private static int executeMap(
            CommandSourceStack source, Supplier<RegionManager> rmSupplier, int radius) {
        RegionManager rm = rmSupplier.get();
        if (rm == null) {
            source.sendFailure(Component.literal("Region manager not ready."));
            return 0;
        }

        String dimId = source.getLevel().dimension().location().toString();
        var pos = source.getPosition();
        int prx = (int) Math.floor(pos.x / (LivingWorldConstants.DEFAULT_REGION_SIZE_CHUNKS * 16.0));
        int prz = (int) Math.floor(pos.z / (LivingWorldConstants.DEFAULT_REGION_SIZE_CHUNKS * 16.0));
        int size = radius * 2 + 1;

        source.sendSuccess(() -> Component.literal(
                "[LW] Map " + size + "×" + size
                + " around (" + prx + "," + prz + ") | [X]=you, ↑N ↓S ←W →E")
                .withStyle(ChatFormatting.GOLD), false);

        // dz goes from -radius (north) to +radius (south) visually top-to-bottom
        for (int dz = -radius; dz <= radius; dz++) {
            MutableComponent row = Component.empty();
            for (int dx = -radius; dx <= radius; dx++) {
                RegionCoordinate coord = new RegionCoordinate(dimId, prx + dx, prz + dz);
                row.append(renderCell(rm, coord, dx == 0 && dz == 0));
            }
            final MutableComponent finalRow = row;
            source.sendSuccess(() -> finalRow, false);
        }

        source.sendSuccess(() -> Component.literal(
                "§2F§r=Forest §aW§r=Woodland §es§r=Scrub §fG§r=Grass §6g§r=Sparse §cB§r=Barren §8·§r=Unknown")
                .withStyle(ChatFormatting.DARK_GRAY), false);
        return 1;
    }

    private static MutableComponent renderCell(RegionManager rm, RegionCoordinate coord, boolean isPlayer) {
        if (isPlayer) {
            return Component.literal("[X]").withStyle(ChatFormatting.AQUA, ChatFormatting.BOLD);
        }
        SuccessionStage stage = rm.resolve(coord)
                .flatMap(r -> r.getModuleData().get(RecoveryModule.MODULE_ID, RecoveryRegionData.class))
                .map(RecoveryRegionData::getSuccessionStage)
                .orElse(null);

        if (stage == null) {
            return Component.literal(" · ").withStyle(ChatFormatting.DARK_GRAY);
        }
        return switch (stage) {
            case MATURE_FOREST  -> Component.literal(" F ").withStyle(ChatFormatting.DARK_GREEN);
            case YOUNG_WOODLAND -> Component.literal(" W ").withStyle(ChatFormatting.GREEN);
            case SCRUBLAND      -> Component.literal(" s ").withStyle(ChatFormatting.YELLOW);
            case GRASSLAND      -> Component.literal(" G ").withStyle(ChatFormatting.WHITE);
            case SPARSE_GRASS   -> Component.literal(" g ").withStyle(ChatFormatting.GOLD);
            case BARREN         -> Component.literal(" B ").withStyle(ChatFormatting.RED);
        };
    }
}
