package net.Chipperfluff.chipi.server;

import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.structure.StructurePlacementData;
import net.minecraft.structure.StructureTemplate;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraft.world.gen.GenerationStep;

import net.Chipperfluff.chipi.SpawnPlacedState;
import net.Chipperfluff.chipi.armor.ProtectionAuraHandler;
import net.Chipperfluff.chipi.block.ChipperPortalBlock;
import net.Chipperfluff.chipi.item.ModItems;
import net.Chipperfluff.chipi.world.gen.ChipiDungeonGenerator;


public final class ChipiServerEvents {

    public static final RegistryKey<World> CHIPI_DIMENSION_KEY =
        RegistryKey.of(RegistryKeys.WORLD, new Identifier("chipi", "chipi_dimension"));

    private static final Identifier SPAWN_STRUCTURE =
        new Identifier("chipi", "spawn");

    private static MinecraftServer SERVER;

    private ChipiServerEvents() {}

    public static void register() {
        BiomeModifications.addFeature(
            BiomeSelectors.foundInOverworld(),
            GenerationStep.Feature.UNDERGROUND_ORES,
            RegistryKey.of(
                RegistryKeys.PLACED_FEATURE,
                new Identifier("chipi", "chipper_ore")
            )
        );

        // ===== PLAYER MILK INTERACTION =====
        UseEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> {
            if (world.isClient()) return ActionResult.PASS;

            if (!(entity instanceof PlayerEntity target)) return ActionResult.PASS;
            if (target == player) return ActionResult.FAIL;

            ItemStack stack = player.getStackInHand(hand);
            if (!stack.isOf(Items.BUCKET)) return ActionResult.PASS;

            stack.decrement(1);

            ItemStack milk = new ItemStack(ModItems.PLAYER_MILK);
            if (!player.getInventory().insertStack(milk)) {
                player.dropItem(milk, false);
            }

            world.playSound(
                null,
                player.getBlockPos(),
                SoundEvents.ENTITY_COW_MILK,
                SoundCategory.PLAYERS,
                1.0f,
                1.1f
            );

            return ActionResult.SUCCESS;
        });

        ServerLifecycleEvents.SERVER_STARTED.register(server -> SERVER = server);
        ServerTickEvents.END_SERVER_TICK.register(ChipiServerEvents::tickPlayers);
        ServerTickEvents.END_WORLD_TICK.register(ChipiServerEvents::handleVoidFailsafe);
        ServerWorldEvents.LOAD.register(ChipiServerEvents::onWorldLoad);
    }

    private static void tickPlayers(MinecraftServer server) {
        for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) {
            ProtectionAuraHandler.tick(player);
        }
    }

    private static void handleVoidFailsafe(ServerWorld world) {
        if (!world.getRegistryKey().equals(CHIPI_DIMENSION_KEY)) return;

        for (PlayerEntity player : world.getPlayers()) {
            if (player.getBlockY() < 50) {
                ChipperPortalBlock.teleportToChipiSpawn(world, player);
            }
        }
    }

    private static void onWorldLoad(MinecraftServer server, ServerWorld world) {
        if (!world.getRegistryKey().equals(CHIPI_DIMENSION_KEY)) return;

        world.setTimeOfDay(18000);
        world.getGameRules().get(GameRules.DO_DAYLIGHT_CYCLE).set(false, server);

        SpawnPlacedState state = world.getPersistentStateManager().getOrCreate(
            SpawnPlacedState::fromNbt,
            SpawnPlacedState::new,
            "chipi_spawn"
        );

        if (state.placed) return;

        StructureTemplate template =
            world.getStructureTemplateManager().getTemplate(SPAWN_STRUCTURE).orElse(null);

        if (template == null) return;

        BlockPos spawn = new BlockPos(0, 80, 0);

        template.place(world, spawn, spawn, new StructurePlacementData(), world.getRandom(), 2);
        world.setSpawnPos(spawn.up(), 0f);
        ChipiDungeonGenerator.generateInitialLayout(world, spawn);

        state.placed = true;
        state.markDirty();
    }

    public static ServerWorld getChipiWorld() {
        return SERVER == null ? null : SERVER.getWorld(CHIPI_DIMENSION_KEY);
    }
}
