import { world, system, ItemStack } from "@minecraft/server";

const GRABPACK_MAP = {
    "mebesm:grabpack_blue": { proj: "mebesm:grabpack_blue_bullet", anim: "animation.grabpack.left_hand" },
    "mebesm:grabpack_blue_g": { proj: "mebesm:grabpack_blue_bullet", anim: "animation.grabpack.left_hand" },
    "mebesm:grabpack_blue_o": { proj: "mebesm:grabpack_blue_bullet", anim: "animation.grabpack.left_hand" },
    "mebesm:grabpack_blue_om": { proj: "mebesm:grabpack_blue_bullet", anim: "animation.grabpack.left_hand" },
    "mebesm:grabpack_blue_p": { proj: "mebesm:grabpack_blue_bullet", anim: "animation.grabpack.left_hand" },
    "mebesm:grabpack_blue_y": { proj: "mebesm:grabpack_blue_bullet", anim: "animation.grabpack.left_hand" },
    "mebesm:grabpack_blue_pr": { proj: "mebesm:grabpack_blue_bullet", anim: "animation.grabpack.left_hand" },
    "mebesm:grabpack_blue_r": { proj: "mebesm:grabpack_blue_bullet", anim: "animation.grabpack.left_hand" },
    "mebesm:grabpack_green": { proj: "mebesm:grabpack_gren_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_green_active": { proj: "mebesm:grabpack_gren_active_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_omni": { proj: "mebesm:grabpack_omni_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_orange": { proj: "mebesm:grabpack_orange_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_purple": { proj: "mebesm:grabpack_purple_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_yellow": { proj: "mebesm:grabpack_yellow_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_yellow_energi": { proj: "mebesm:grabpack_yellow_energi_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_yellow_ice": { proj: "mebesm:grabpack_yellow_ice_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_yellow_fire": { proj: "mebesm:grabpack_yellow_fire_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_red": { proj: "mebesm:grabpack_red_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_pressure": { proj: "mebesm:grabpack_pressure_bullet", anim: "animation.grabpack.right_hand" },
    "mebesm:grabpack_green_and_blue": { proj: "mebesm:grabpack_gren_and_blue_bullet", anim: "animation.grabpack.left_right_hand" },
    "mebesm:grabpack_yellow_and_blue": { proj: "mebesm:grabpack_yellow_and_blue_bullet", anim: "animation.grabpack.left_right_hand" },
    "mebesm:grabpack_omni_and_blue": { proj: "mebesm:grabpack_omni_and_blue_bullet", anim: "animation.grabpack.left_right_hand" },
    "mebesm:grabpack_pressure_and_blue": { proj: "mebesm:grabpack_pressure_and_blue_bullet", anim: "animation.grabpack.left_right_hand" },
    "mebesm:grabpack_purple_and_blue": { proj: "mebesm:grabpack_purple_and_blue_bullet", anim: "animation.grabpack.left_right_hand" },
    "mebesm:grabpack_red_and_blue": { proj: "mebesm:grabpack_red_and_blue_bullet", anim: "animation.grabpack.left_right_hand" }
};

const SINGLE_USE_GRABPACKS = new Set([
    "mebesm:grabpack_yellow_ice",
    "mebesm:grabpack_yellow_energi",
    "mebesm:grabpack_yellow_fire"
]);

const ICE_FREEZE_MAP = {
    "minecraft:water": "minecraft:ice",
    "minecraft:flowing_water": "minecraft:ice",
    "mebesm:organic_gel": "mebesm:organic_gel_ice"
};

const ICE_FREEZE_RADIUS = 3;

const PRESSURE_BREAKABLE = [
    "minecraft:ice", "minecraft:packed_ice", "minecraft:blue_ice", "minecraft:frosted_ice",
    "mebesm:organic_gel_ice", "minecraft:glass", "minecraft:tinted_glass", "minecraft:glass_pane",
    "minecraft:white_stained_glass", "minecraft:orange_stained_glass", "minecraft:magenta_stained_glass",
    "minecraft:light_blue_stained_glass", "minecraft:yellow_stained_glass", "minecraft:lime_stained_glass",
    "minecraft:pink_stained_glass", "minecraft:gray_stained_glass", "minecraft:light_gray_stained_glass",
    "minecraft:cyan_stained_glass", "minecraft:purple_stained_glass", "minecraft:blue_stained_glass",
    "minecraft:brown_stained_glass", "minecraft:green_stained_glass", "minecraft:red_stained_glass",
    "minecraft:black_stained_glass", "minecraft:white_stained_glass_pane", "minecraft:orange_stained_glass_pane",
    "minecraft:magenta_stained_glass_pane", "minecraft:light_blue_stained_glass_pane",
    "minecraft:yellow_stained_glass_pane", "minecraft:lime_stained_glass_pane",
    "minecraft:pink_stained_glass_pane", "minecraft:gray_stained_glass_pane",
    "minecraft:light_gray_stained_glass_pane", "minecraft:cyan_stained_glass_pane",
    "minecraft:purple_stained_glass_pane", "minecraft:blue_stained_glass_pane",
    "minecraft:brown_stained_glass_pane", "minecraft:green_stained_glass_pane",
    "minecraft:red_stained_glass_pane", "minecraft:black_stained_glass_pane",
    "minecraft:oak_door", "minecraft:spruce_door", "minecraft:birch_door", "minecraft:jungle_door",
    "minecraft:acacia_door", "minecraft:dark_oak_door", "minecraft:mangrove_door",
    "minecraft:cherry_door", "minecraft:bamboo_door", "minecraft:crimson_door", "minecraft:warped_door",
    "minecraft:oak_trapdoor", "minecraft:spruce_trapdoor", "minecraft:birch_trapdoor",
    "minecraft:jungle_trapdoor", "minecraft:acacia_trapdoor", "minecraft:dark_oak_trapdoor",
    "minecraft:mangrove_trapdoor", "minecraft:cherry_trapdoor", "minecraft:bamboo_trapdoor",
    "minecraft:crimson_trapdoor", "minecraft:warped_trapdoor"
];

const PRESSURE_RADIUS = 3;

function replaceWithYellow(player) {
    system.run(() => {
        try {
            const inventory = player.getComponent("minecraft:inventory");
            if (!inventory) return;
            const container = inventory.container;
            const slot = player.selectedSlotIndex;
            const current = container.getItem(slot);
            if (current && SINGLE_USE_GRABPACKS.has(current.typeId)) {
                container.setItem(slot, new ItemStack("mebesm:grabpack_yellow", 1));
            }
        } catch (e) { }
    });
}

function replaceWithGreen(player) {
    system.run(() => {
        try {
            const inventory = player.getComponent("minecraft:inventory");
            if (!inventory) return;
            const container = inventory.container;
            const slot = player.selectedSlotIndex;
            const current = container.getItem(slot);
            if (current && current.typeId === "mebesm:grabpack_green_active") {
                container.setItem(slot, new ItemStack("mebesm:grabpack_green", 1));
            }
        } catch (e) { }
    });
}

function spawnVanillaFire(dimension, location) {
    try {
        const firePos = {
            x: Math.floor(location.x),
            y: Math.floor(location.y),
            z: Math.floor(location.z)
        };
        const block = dimension.getBlock(firePos);
        if (block && block.typeId === "minecraft:air") {
            block.setType("minecraft:fire");
        }
    } catch (e) { }
}

function handleIceFreeze(dimension, location) {
    try { dimension.spawnParticle("minecraft:snowflake_particle", location); } catch (e) { }
    try { dimension.playSound("random.glass", location, { volume: 1.0, pitch: 0.7 }); } catch (e) { }

    const r = ICE_FREEZE_RADIUS;
    for (let dx = -r; dx <= r; dx++) {
        for (let dy = -r; dy <= r; dy++) {
            for (let dz = -r; dz <= r; dz++) {
                if (dx * dx + dy * dy + dz * dz > r * r) continue;
                try {
                    const block = dimension.getBlock({
                        x: Math.floor(location.x) + dx,
                        y: Math.floor(location.y) + dy,
                        z: Math.floor(location.z) + dz
                    });
                    if (block) {
                        const frozenType = ICE_FREEZE_MAP[block.typeId];
                        if (frozenType) block.setType(frozenType);
                    }
                } catch (e) { }
            }
        }
    }
}

function handlePressureExplosion(dimension, location, owner) {
    try { dimension.spawnParticle("minecraft:explosion_particle", location); } catch (e) { }
    try { dimension.playSound("random.explode", location, { volume: 1.0, pitch: 1.2 }); } catch (e) { }

    const r = PRESSURE_RADIUS;
    for (let dx = -r; dx <= r; dx++) {
        for (let dy = -r; dy <= r; dy++) {
            for (let dz = -r; dz <= r; dz++) {
                if (dx * dx + dy * dy + dz * dz > r * r) continue;
                try {
                    const block = dimension.getBlock({
                        x: Math.floor(location.x) + dx,
                        y: Math.floor(location.y) + dy,
                        z: Math.floor(location.z) + dz
                    });
                    if (block && PRESSURE_BREAKABLE.includes(block.typeId)) {
                        block.setType("minecraft:air");
                    }
                } catch (e) { }
            }
        }
    }

    try {
        const entities = dimension.getEntities({ location, maxDistance: PRESSURE_RADIUS });
        for (const entity of entities) {
            if (owner && entity.id === owner.id) continue;
            if (!entity.hasComponent("minecraft:health")) continue;
            try { entity.applyDamage(5, { cause: "projectile", damagingEntity: owner }); } catch (e) { }
        }
    } catch (e) { }
}

function shootGrabpack(player, itemStack) {
    const config = GRABPACK_MAP[itemStack.typeId];
    if (!config) return;

    const headLoc = player.getHeadLocation();
    const viewVec = player.getViewDirection();
    const spawnPos = {
        x: headLoc.x + viewVec.x * 1.5,
        y: headLoc.y + viewVec.y * 1.5,
        z: headLoc.z + viewVec.z * 1.5
    };

    try {
        const projectile = player.dimension.spawnEntity(config.proj, spawnPos);
        const projComp = projectile.getComponent("minecraft:projectile");
        if (projComp) projComp.owner = player;
        projectile.applyImpulse({ x: viewVec.x * 3, y: viewVec.y * 3, z: viewVec.z * 3 });
    } catch (e) {
        console.warn(`[GRABPACK] Spawn error: ${config.proj}`);
    }

    const sound = (itemStack.typeId === "mebesm:grabpack_orange") ? "grabpack_orange" : "grabpack";
    player.dimension.playSound(sound, player.location);

    system.run(() => {
        player.playAnimation(config.anim, { blendOutTime: 0.2 });
    });

    if (itemStack.typeId === "mebesm:grabpack_green_active") {
        replaceWithGreen(player);
    } else if (SINGLE_USE_GRABPACKS.has(itemStack.typeId)) {
        replaceWithYellow(player);
    }
}

world.beforeEvents.worldInitialize.subscribe(({ itemComponentRegistry }) => {
    itemComponentRegistry.registerCustomComponent("grabpack:trigger", {
        onUse(event) {
            const { source: player, itemStack } = event;
            if (!player) return;
            event.cancelPop = true;
            shootGrabpack(player, itemStack);
        },
        onUseOn(event) {
            event.cancel = true;
            const { source: player, itemStack } = event;
            if (!player) return;
            shootGrabpack(player, itemStack);
        }
    });
});

world.afterEvents.projectileHitBlock.subscribe((event) => {
    const projectile = event.projectile;

    if (projectile.typeId === "mebesm:grabpack_pressure_bullet") {
        const loc = event.location;
        const dimension = event.dimension;
        const owner = projectile.getComponent("minecraft:projectile")?.owner;
        system.run(() => {
            handlePressureExplosion(dimension, loc, owner);
            try { projectile.remove(); } catch (e) { }
        });
    }

    if (projectile.typeId === "mebesm:grabpack_orange_bullet") {
        const loc = event.location;
        system.run(() => {
            event.dimension.spawnEntity("mebesm:fire", loc);
        });
    }

    if (projectile.typeId === "mebesm:grabpack_yellow_ice_bullet") {
        const loc = event.location;
        const dimension = event.dimension;
        system.run(() => {
            handleIceFreeze(dimension, loc);
            try { projectile.remove(); } catch (e) { }
        });
    }

    if (projectile.typeId === "mebesm:grabpack_yellow_fire_bullet") {
        const loc = event.location;
        const dimension = event.dimension;
        system.run(() => {
            try {
                dimension.spawnParticle("minecraft:basic_flame_particle", loc);
                dimension.playSound("fire.ignite", loc, { volume: 1.0, pitch: 1.0 });
            } catch (e) { }
            spawnVanillaFire(dimension, loc);
            try { projectile.remove(); } catch (e) { }
        });
    }
});

world.afterEvents.projectileHitEntity.subscribe((event) => {
    const projectile = event.projectile;

    if (projectile.typeId === "mebesm:grabpack_pressure_bullet") {
        const loc = event.location;
        const dimension = event.dimension;
        const owner = projectile.getComponent("minecraft:projectile")?.owner;
        system.run(() => {
            handlePressureExplosion(dimension, loc, owner);
            try { projectile.remove(); } catch (e) { }
        });
    }

    if (projectile.typeId === "mebesm:grabpack_orange_bullet") {
        const hit = event.getEntityHit();
        if (!hit) return;
        const owner = projectile.getComponent("minecraft:projectile")?.owner;
        if (hit.entity.id !== owner?.id) {
            const loc = event.location;
            system.run(() => {
                event.dimension.spawnEntity("mebesm:fire", loc);
            });
        }
    }

    if (projectile.typeId === "mebesm:grabpack_yellow_ice_bullet") {
        const hitEntity = event.getEntityHit().entity;
        const loc = event.location;
        const dimension = event.dimension;
        const owner = projectile.getComponent("minecraft:projectile")?.owner;

        if (!owner || hitEntity.id !== owner.id) {
            system.run(() => {
                try {
                    dimension.spawnParticle("minecraft:snowflake_particle", loc);
                    dimension.playSound("random.glass", loc, { volume: 1.0, pitch: 0.7 });
                } catch (e) { }
                try {
                    if (hitEntity.hasComponent("minecraft:health")) {
                        hitEntity.addEffect("slowness", 100, { amplifier: 4, showParticles: true });
                        hitEntity.addEffect("mining_fatigue", 100, { amplifier: 2, showParticles: false });
                    }
                } catch (e) { }
                handleIceFreeze(dimension, loc);
                try { projectile.remove(); } catch (e) { }
            });
        }
    }

    if (projectile.typeId === "mebesm:grabpack_yellow_fire_bullet") {
        const hitEntity = event.getEntityHit().entity;
        const loc = event.location;
        const dimension = event.dimension;
        const owner = projectile.getComponent("minecraft:projectile")?.owner;

        if (!owner || hitEntity.id !== owner.id) {
            system.run(() => {
                try {
                    dimension.spawnParticle("minecraft:basic_flame_particle", loc);
                    dimension.playSound("fire.ignite", loc, { volume: 1.0, pitch: 1.0 });
                    hitEntity.setOnFire(5, true);
                } catch (e) { }
                try { projectile.remove(); } catch (e) { }
            });
        }
    }

    if (
        projectile.typeId === "mebesm:grabpack_yellow_energi_bullet" ||
        projectile.typeId === "mebesm:grabpack_gren_active_bullet"
    ) {
        const hitEntity = event.getEntityHit().entity;
        const owner = projectile.getComponent("minecraft:projectile")?.owner;

        if (!hitEntity.hasComponent("minecraft:health")) return;
        if (owner && hitEntity.id === owner.id) return;

        try {
            const family = hitEntity.getComponent("minecraft:type_family");
            if (family && family.hasTypeFamily("module")) return;
        } catch { }

        system.run(() => {
            let ticks = 80;

            const interval = system.runInterval(() => {
                try {
                    if (!hitEntity || !hitEntity.isValid()) {
                        system.clearRun(interval);
                        return;
                    }
                    hitEntity.applyDamage(1.5, { cause: "magic", damagingEntity: owner });
                    hitEntity.dimension.spawnParticle("mebesm:electricity", hitEntity.location);
                    ticks -= 20;
                    if (ticks <= 0) system.clearRun(interval);
                } catch {
                    system.clearRun(interval);
                }
            }, 20);

            try { projectile.remove(); } catch { }
        });
    }
});