package com.tiedup.remake.v2.blocks;

import com.tiedup.remake.core.TiedUpMod;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.jetbrains.annotations.Nullable;

/**
 * Server-side manager for pet cage confinement.
 * Tracks which players are caged, immobilizes them, and handles cleanup.
 */
public class PetCageManager {

    private static final UUID PET_CAGE_SPEED_MODIFIER_UUID = UUID.fromString(
        "b2c3d4e5-f6a7-4890-bcde-f01234567890"
    );
    private static final String PET_CAGE_SPEED_MODIFIER_NAME =
        "tiedup.pet_cage_immobilize";
    private static final double FULL_IMMOBILIZATION = -0.10;

    /** Active cage entries keyed by player UUID */
    private static final Map<UUID, CageEntry> entries =
        new ConcurrentHashMap<>();

    private static class CageEntry {

        final BlockPos pos;

        CageEntry(BlockPos pos) {
            this.pos = pos;
        }
    }

    /**
     * Cage a player at the given master block position.
     * Teleports them to the center of the 3x3x3 cage and immobilizes.
     */
    public static void cagePlayer(ServerPlayer player, BlockPos masterPos) {
        UUID uuid = player.getUUID();
        entries.put(uuid, new CageEntry(masterPos.immutable()));

        // Teleport to cage center (master is at center of 3x3x3 grid)
        double[] center = getCageCenter(player, masterPos);
        player.teleportTo(center[0], center[1], center[2]);

        // Immobilize
        applySpeedModifier(player);

        TiedUpMod.LOGGER.debug(
            "[PetCageManager] {} caged at {}",
            player.getName().getString(),
            masterPos
        );
    }

    /**
     * Release a player from cage confinement.
     */
    public static void releasePlayer(ServerPlayer player) {
        UUID uuid = player.getUUID();
        CageEntry entry = entries.remove(uuid);
        if (entry == null) return;

        // Release block entity
        BlockEntity be = player.level().getBlockEntity(entry.pos);
        if (be instanceof PetCageBlockEntity cageBE) {
            cageBE.clearOccupant();
        }

        // Restore speed
        removeSpeedModifier(player);

        TiedUpMod.LOGGER.debug(
            "[PetCageManager] {} released from cage at {}",
            player.getName().getString(),
            entry.pos
        );
    }

    /**
     * Check if a player is in a cage.
     */
    public static boolean isInCage(ServerPlayer player) {
        return entries.containsKey(player.getUUID());
    }

    /**
     * Get the cage position for a player, or null if not caged.
     */
    @Nullable
    public static BlockPos getCagePos(ServerPlayer player) {
        CageEntry entry = entries.get(player.getUUID());
        return entry != null ? entry.pos : null;
    }

    /**
     * Tick a caged player to verify cage still exists.
     * Called from server-side tick handler.
     */
    public static void tickPlayer(ServerPlayer player) {
        CageEntry entry = entries.get(player.getUUID());
        if (entry == null) return;

        // Check if the block is still a cage
        if (
            !(player.level().getBlockState(entry.pos).getBlock() instanceof
                    PetCageBlock)
        ) {
            releasePlayer(player);
            return;
        }

        // Keep player at cage center (prevent movement exploits)
        double[] center = getCageCenter(player, entry.pos);
        double distSq = player.distanceToSqr(center[0], center[1], center[2]);
        if (distSq > 0.25) {
            // > 0.5 blocks
            player.teleportTo(center[0], center[1], center[2]);
        }
    }

    /**
     * Calculate the center of the 3x3x3 cage from the master block position.
     * The master is at the center of the grid, so the cage center is the master block center.
     */
    private static double[] getCageCenter(
        ServerPlayer player,
        BlockPos masterPos
    ) {
        return new double[] {
            masterPos.getX() + 0.5,
            masterPos.getY(),
            masterPos.getZ() + 0.5,
        };
    }

    /**
     * Clean up when a player disconnects.
     */
    public static void onPlayerDisconnect(UUID uuid) {
        entries.remove(uuid);
    }

    /**
     * Remove any leftover cage speed modifier on login.
     */
    public static void onPlayerLogin(ServerPlayer player) {
        removeSpeedModifier(player);
    }

    private static void applySpeedModifier(ServerPlayer player) {
        AttributeInstance movementSpeed = player.getAttribute(
            Attributes.MOVEMENT_SPEED
        );
        if (movementSpeed == null) return;

        // Remove existing to avoid duplicates
        if (movementSpeed.getModifier(PET_CAGE_SPEED_MODIFIER_UUID) != null) {
            movementSpeed.removeModifier(PET_CAGE_SPEED_MODIFIER_UUID);
        }

        AttributeModifier modifier = new AttributeModifier(
            PET_CAGE_SPEED_MODIFIER_UUID,
            PET_CAGE_SPEED_MODIFIER_NAME,
            FULL_IMMOBILIZATION,
            AttributeModifier.Operation.ADDITION
        );
        movementSpeed.addPermanentModifier(modifier);
    }

    private static void removeSpeedModifier(ServerPlayer player) {
        AttributeInstance movementSpeed = player.getAttribute(
            Attributes.MOVEMENT_SPEED
        );
        if (
            movementSpeed != null &&
            movementSpeed.getModifier(PET_CAGE_SPEED_MODIFIER_UUID) != null
        ) {
            movementSpeed.removeModifier(PET_CAGE_SPEED_MODIFIER_UUID);
        }
    }
}
