import { world, system, EquipmentSlot, ItemStack, EntityDamageCause } from '@minecraft/server';

export const CarmotShovelSystem = {
    config: {
        gravityVortexRadius: 10,
        gravityCooldown: 300, // 15 seconds
        terrainExcavationRadius: 6,
        carmotDropChance: 0.35, // 35% chance for carmot drops
        crystallineDropChance: 0.18, // 18% chance for crystalline drops
        vortexDuration: 150, // 7.5 seconds
        chainReactionChance: 0.25 // 25% chance for chain reaction
    },

    // Utility function for sending styled action bar messages
    sendActionBar(player, message, color = '§6') {
        try {
            player.onScreenDisplay.setActionBar(`${color}${message}`);
        } catch (error) {
            // Silent fail
        }
    },

    handleShovelUse(player, itemStack, useDuration) {
        try {
            if (player.isSneaking) {
                // Primary ability: Gravity Vortex
                this.activateGravityVortex(player);
                return;
            } else {
                // Show shovel info when used without sneaking
                this.sendActionBar(player, '§6Terrain Disruptor §8▸ §7Sneak + Use to create gravity vortex §7| §6Dig earth for carmot materials', '§6');
                return;
            }
        } catch (error) {
            this.sendActionBar(player, '§cGravitational Anomaly Detected', '§6');
        }
    },

    handleTerrainDigging(player, itemStack, targetBlock, blockFace) {
        try {
            const blockType = targetBlock.typeId;

            // Check if it's an earth-related block
            if (this.isEarthBlock(blockType)) {
                // Gravity-enhanced terrain harvesting
                this.performGravityExcavation(player, targetBlock);
                return;
            }

            // Regular digging effects for any block
            this.createDiggingEffects(player, targetBlock.location, blockType);

        } catch (error) {
            this.sendActionBar(player, '§cExcavation Protocol Error', '§6');
        }
    },

    // PRIMARY ABILITY: Gravity Vortex (Sneak + Use)
    activateGravityVortex(player) {
        try {
            // Check cooldown
            const lastVortex = player.getDynamicProperty('myw:carmot_shovel_last_vortex') || 0;
            const currentTime = Date.now();

            if (currentTime - lastVortex < this.config.gravityCooldown * 50) {
                const remainingTime = Math.ceil((this.config.gravityCooldown * 50 - (currentTime - lastVortex)) / 1000);
                this.sendActionBar(player, `§6Gravity Vortex Cooldown §8▸ §e${remainingTime}s remaining`, '§6');
                return;
            }

            player.setDynamicProperty('myw:carmot_shovel_last_vortex', currentTime);

            this.sendActionBar(player, '§6Gravity Vortex §8▸ §aGenerating gravitational singularity...', '§6');
            this.createGravityVortex(player);

        } catch (error) {
            // Silent error
        }
    },

    createGravityVortex(player) {
        const { x, y, z } = player.location;
        const dimension = player.dimension;
        let vortexTime = 0;

        const vortexInterval = system.runInterval(() => {
            vortexTime++;

            // Create vortex particles
            const radius = 3.0;
            for (let i = 0; i < 16; i++) {
                const angle = (i / 16) * Math.PI * 2 + vortexTime * 0.2;
                const vortexX = x + Math.cos(angle) * radius;
                const vortexZ = z + Math.sin(angle) * radius;
                const vortexY = y + 1.0 + Math.sin(vortexTime * 0.3) * 0.5;

                this.spawnCarmotParticle(dimension, vortexX, vortexY, vortexZ, 'gravity');

                // Add earth particles occasionally
                if (i % 4 === 0) {
                    this.spawnCarmotParticle(dimension, vortexX, vortexY + 0.3, vortexZ, 'standard');
                }
            }

            // Attract and damage entities
            dimension.getEntities().forEach(entity => {
                if (entity.id !== player.id && this.isNear(player, entity, this.config.gravityVortexRadius)) {
                    // Strong attraction force
                    this.applyGravitationalForce(entity, x, y + 1.5, z, 0.9);

                    // Damage to mobs
                    if (entity.typeId !== 'minecraft:item' && vortexTime % 10 === 0) {
                        try {
                            entity.applyDamage(4, { cause: EntityDamageCause.magic });
                        } catch (error) {
                            // Ignore if cannot apply damage
                        }
                    }
                }
            });

            // Break nearby terrain
            if (vortexTime % 15 === 0) {
                this.breakNearbyTerrain(dimension, x, y, z, player);
            }

            if (vortexTime >= this.config.vortexDuration) {
                system.clearRun(vortexInterval);
                this.collapseGravityVortex(dimension, x, y, z, player);
            }
        }, 2);
    },

    collapseGravityVortex(dimension, x, y, z, player) {
        // Implosion effect
        for (let i = 0; i < 20; i++) {
            system.runTimeout(() => {
                const radius = 4.0 - (i * 0.2);

                for (let j = 0; j < 12; j++) {
                    const angle = (j / 12) * Math.PI * 2;
                    const collapseX = x + Math.cos(angle) * radius;
                    const collapseZ = z + Math.sin(angle) * radius;
                    const collapseY = y + 1.5 + (Math.random() - 0.5);

                    this.spawnCarmotParticle(dimension, collapseX, collapseY, collapseZ, 'serpentine');
                }
            }, i * 3);
        }

        // Final message
        system.runTimeout(() => {
            this.sendActionBar(player, '§6Gravity Vortex Collapsed §8▸ §aSingularity dissipated', '§6');
        }, 60);
    },

    breakNearbyTerrain(dimension, centerX, centerY, centerZ, player) {
        for (let x = -this.config.terrainExcavationRadius; x <= this.config.terrainExcavationRadius; x++) {
            for (let y = -this.config.terrainExcavationRadius; y <= this.config.terrainExcavationRadius; y++) {
                for (let z = -this.config.terrainExcavationRadius; z <= this.config.terrainExcavationRadius; z++) {
                    // Check spherical radius
                    const distance = Math.sqrt(x * x + y * y + z * z);
                    if (distance > this.config.terrainExcavationRadius) continue;

                    const checkLocation = {
                        x: Math.floor(centerX) + x,
                        y: Math.floor(centerY) + y,
                        z: Math.floor(centerZ) + z
                    };

                    try {
                        const block = dimension.getBlock(checkLocation);
                        if (block && (this.isEarthBlock(block.typeId) || this.isSandBlock(block.typeId))) {
                            // Break the block and attempt drops
                            this.mineBlockWithPlayer(dimension, checkLocation, block.typeId, player);

                            // Create breaking effect
                            this.createGravityBreakEffect(dimension, checkLocation);
                        }
                    } catch (error) {
                        continue;
                    }
                }
            }
        }
    },

    // GRAVITY EXCAVATION: When digging earth blocks
    performGravityExcavation(player, targetBlock) {
        try {
            const blockType = targetBlock.typeId;
            const location = targetBlock.location;

            // Always attempt carmot drops from earth
            this.attemptCarmotDrops(player, location);

            // Special gravity digging effects
            this.createGravityExcavationEffects(player, location, blockType);

            // Chance for gravity chain reaction
            if (Math.random() < this.config.chainReactionChance) {
                this.triggerGravityChainReaction(player, location, blockType);
            }

            const terrainName = this.getTerrainName(blockType);
            this.sendActionBar(player, `§6${terrainName} Excavated §8▸ §eGravity-Enhanced §7| §6Carmot essence absorbed`, '§6');

        } catch (error) {
            // Error with gravity excavation
        }
    },

    triggerGravityChainReaction(player, startLocation, blockType) {
        try {
            const dimension = player.dimension;
            const nearbyTerrain = [];

            // Find nearby terrain blocks of similar type
            for (let x = -3; x <= 3; x++) {
                for (let y = -2; y <= 2; y++) {
                    for (let z = -3; z <= 3; z++) {
                        if (x === 0 && y === 0 && z === 0) continue; // Skip center block

                        const checkLocation = {
                            x: startLocation.x + x,
                            y: startLocation.y + y,
                            z: startLocation.z + z
                        };

                        try {
                            const block = dimension.getBlock(checkLocation);
                            if (block && (block.typeId === blockType || this.isSimilarTerrain(blockType, block.typeId))) {
                                nearbyTerrain.push(checkLocation);
                            }
                        } catch (error) {
                            continue;
                        }
                    }
                }
            }

            if (nearbyTerrain.length > 0) {
                const terrainToBreak = nearbyTerrain.slice(0, 4); // Limit to 4 blocks

                terrainToBreak.forEach((terrainLocation, index) => {
                    system.runTimeout(() => {
                        try {
                            this.createGravityChainEffects(dimension, terrainLocation);
                            this.attemptCarmotDrops(player, terrainLocation);
                            dimension.runCommand(`setblock ${terrainLocation.x} ${terrainLocation.y} ${terrainLocation.z} air destroy`);
                        } catch (error) {
                            // Error with chain reaction
                        }
                    }, index * 8);
                });

                system.runTimeout(() => {
                    this.sendActionBar(player, `§6Gravity Chain Reaction §8▸ §e${terrainToBreak.length} extra blocks §7| §6Gravitational resonance`, '§6');
                }, 30);
            }

        } catch (error) {
            // Error with chain reaction
        }
    },

    // UTILITY FUNCTIONS
    createDiggingEffects(player, location, blockType) {
        try {
            // Always attempt carmot drops for any block dug with the shovel
            this.attemptCarmotDrops(player, location);

            if (this.isEarthBlock(blockType) || this.isSandBlock(blockType)) {
                // Enhanced effects already handled in performGravityExcavation
                return;
            } else {
                // Regular block digging
                this.sendActionBar(player, `§6Block Excavated §8▸ §eGravity Enhanced §7| §6Chance for carmot materials`, '§6');
            }
        } catch (error) {
            // Error with effects
        }
    },

    attemptCarmotDrops(player, location) {
        try {
            const dimension = player.dimension;
            const dropLocation = {
                x: Math.floor(location.x) + 0.5,
                y: Math.floor(location.y) + 0.1,
                z: Math.floor(location.z) + 0.5
            };

            let droppedSomething = false;

            // Chance for carmot dust
            if (Math.random() < this.config.carmotDropChance) {
                this.spawnCarmotItem(dimension, dropLocation, 'myw:carmot_dust');
                droppedSomething = true;

                // Gravity particles for dust
                for (let i = 0; i < 5; i++) {
                    system.runTimeout(() => {
                        try {
                            this.spawnCarmotParticle(dimension, {
                                x: dropLocation.x + (Math.random() - 0.5) * 0.8,
                                y: dropLocation.y + Math.random() * 0.5,
                                z: dropLocation.z + (Math.random() - 0.5) * 0.8
                            }, 'gravity');
                        } catch (error) {
                            // Error with particles
                        }
                    }, i * 3);
                }
            }

            // Chance for crystalline fragment
            if (Math.random() < this.config.crystallineDropChance) {
                this.spawnCarmotItem(dimension, dropLocation, 'myw:carmot_nugget');
                droppedSomething = true;

                // Crystalline particles for nugget
                for (let i = 0; i < 7; i++) {
                    system.runTimeout(() => {
                        try {
                            this.spawnCarmotParticle(dimension, {
                                x: dropLocation.x + (Math.random() - 0.5) * 1.0,
                                y: dropLocation.y + Math.random() * 0.6,
                                z: dropLocation.z + (Math.random() - 0.5) * 1.0
                            }, 'serpentine');
                        } catch (error) {
                            // Error with particles
                        }
                    }, i * 4);
                }

                system.runTimeout(() => {
                    this.sendActionBar(player, `§5Crystalline Fragment! §8▸ §dEarth-bound artifact §7| §518% chance success`, '§5');
                }, 10);
            }

            if (droppedSomething) {
                system.runTimeout(() => {
                    this.sendActionBar(player, `§dTerrain Materials Found! §8▸ §5Check around your feet §7| §6Continue excavating`, '§d');
                }, 5);
            }

        } catch (error) {
            // Error in drop system
        }
    },

    spawnCarmotItem(dimension, location, itemId) {
        try {
            const itemSpawn = dimension.spawnItem(new ItemStack(itemId, 1), location);
        } catch (error) {
            try {
                dimension.runCommand(`summon item ${location.x} ${location.y} ${location.z} ~ ~ ~ minecraft:item 1 0 {"Item":{"id":"${itemId}","Count":1}}`);
            } catch (cmdError) {
                try {
                    const players = world.getAllPlayers();
                    if (players.length > 0) {
                        dimension.runCommand(`give "${players[0].name}" ${itemId} 1`);
                    }
                } catch (giveError) {
                    // All methods failed
                }
            }
        }
    },

    mineBlockWithPlayer(dimension, location, blockType, player) {
        try {
            const block = dimension.getBlock(location);
            if (!block || block.typeId !== blockType) return;

            // Effects before mining
            this.createGravityBreakEffect(dimension, location);

            // Attempt carmot drops
            this.attemptCarmotDrops(player, location);

            // Break the block
            dimension.runCommand(`setblock ${location.x} ${location.y} ${location.z} air destroy`);

        } catch (error) {
            // If command fails, try manual mining
            try {
                const block = dimension.getBlock(location);
                if (block) {
                    block.setType('minecraft:air');
                }
            } catch (fallbackError) {
                // Silent continue
            }
        }
    },

    // VISUAL EFFECTS
    createGravityExcavationEffects(player, location, blockType) {
        try {
            // Gravity digging particles
            for (let i = 0; i < 6; i++) {
                system.runTimeout(() => {
                    try {
                        this.spawnCarmotParticle(player.dimension, {
                            x: location.x + 0.5 + (Math.random() - 0.5) * 1.2,
                            y: location.y + 0.5 + (Math.random() - 0.5) * 1.2,
                            z: location.z + 0.5 + (Math.random() - 0.5) * 1.2
                        }, 'gravity');
                    } catch (error) {
                        // Error with particles
                    }
                }, i * 2);
            }
        } catch (error) {
            // Error creating effects
        }
    },

    createGravityBreakEffect(dimension, location) {
        try {
            // Particles moving toward center (implosion effect)
            for (let i = 0; i < 8; i++) {
                const angle = Math.random() * Math.PI * 2;
                const radius = 1.2 + Math.random() * 0.5;
                const particleX = location.x + 0.5 + Math.cos(angle) * radius;
                const particleZ = location.z + 0.5 + Math.sin(angle) * radius;
                const particleY = location.y + 0.5 + (Math.random() - 0.5) * 1.2;

                this.spawnCarmotParticle(dimension, particleX, particleY, particleZ, 'gravity');
            }

            // Center implosion
            this.spawnCarmotParticle(dimension, location.x + 0.5, location.y + 0.5, location.z + 0.5, 'serpentine');
        } catch (error) {
            // Error with effects
        }
    },

    createGravityChainEffects(dimension, location) {
        try {
            for (let i = 0; i < 10; i++) {
                system.runTimeout(() => {
                    try {
                        this.spawnCarmotParticle(dimension, {
                            x: location.x + 0.5 + (Math.random() - 0.5) * 1.5,
                            y: location.y + 0.5 + (Math.random() - 0.5) * 1.5,
                            z: location.z + 0.5 + (Math.random() - 0.5) * 1.5
                        }, 'gravity');
                    } catch (error) {
                        // Error with particles
                    }
                }, i * 1);
            }
        } catch (error) {
            // Error creating chain effects
        }
    },

    // BLOCK TYPE CHECKERS
    isEarthBlock(blockType) {
        const earthBlocks = [
            'minecraft:dirt', 'minecraft:grass_block', 'minecraft:coarse_dirt',
            'minecraft:podzol', 'minecraft:mycelium', 'minecraft:rooted_dirt',
            'minecraft:mud', 'minecraft:packed_mud', 'minecraft:muddy_mangrove_roots',
            'minecraft:clay', 'minecraft:farmland'
        ];
        return earthBlocks.includes(blockType);
    },

    isSandBlock(blockType) {
        const sandBlocks = [
            'minecraft:sand', 'minecraft:red_sand', 'minecraft:gravel',
            'minecraft:soul_sand', 'minecraft:soul_soil', 'minecraft:suspicious_sand',
            'minecraft:suspicious_gravel', 'minecraft:powder_snow'
        ];
        return sandBlocks.includes(blockType);
    },

    isSimilarTerrain(originalType, checkType) {
        // Group similar terrain types for chain reactions
        const dirtGroup = ['minecraft:dirt', 'minecraft:grass_block', 'minecraft:coarse_dirt', 'minecraft:podzol', 'minecraft:mycelium'];
        const sandGroup = ['minecraft:sand', 'minecraft:red_sand', 'minecraft:gravel'];
        const mudGroup = ['minecraft:mud', 'minecraft:packed_mud', 'minecraft:clay'];

        for (const group of [dirtGroup, sandGroup, mudGroup]) {
            if (group.includes(originalType) && group.includes(checkType)) {
                return true;
            }
        }
        return false;
    },

    getTerrainName(blockType) {
        const names = {
            'minecraft:dirt': 'Dirt',
            'minecraft:grass_block': 'Grass',
            'minecraft:sand': 'Sand',
            'minecraft:red_sand': 'Red Sand',
            'minecraft:gravel': 'Gravel',
            'minecraft:clay': 'Clay',
            'minecraft:mud': 'Mud',
            'minecraft:soul_sand': 'Soul Sand',
            'minecraft:soul_soil': 'Soul Soil'
        };
        return names[blockType] || 'Terrain';
    },

    // Utility functions for gravity effects
    isNear(entity1, entity2, maxDistance, maxHeightDiff = 10) {
        const distance = Math.sqrt(
            Math.pow(entity1.location.x - entity2.location.x, 2) +
            Math.pow(entity1.location.y - entity2.location.y, 2) +
            Math.pow(entity1.location.z - entity2.location.z, 2)
        );

        return distance <= maxDistance &&
            Math.abs(entity1.location.y - entity2.location.y) <= maxHeightDiff;
    },

    spawnCarmotParticle(dimension, location, particleType = 'gravity') {
        const particles = {
            'standard': 'myw:carmot_particle',
            'gravity': 'myw:carmot_particle_gravity',
            'serpentine': 'myw:carmot_particle_serpentine'
        };

        const fallbacks = {
            'standard': 'minecraft:lava_particle',
            'gravity': 'minecraft:portal_particle',
            'serpentine': 'minecraft:crimson_spore_particle'
        };

        try {
            // Handle both object and coordinate parameters
            if (typeof location === 'object' && location.x !== undefined) {
                dimension.spawnParticle(particles[particleType] || particles.gravity, location);
            } else {
                // Assume coordinates were passed separately
                dimension.spawnParticle(particles[particleType] || particles.gravity, {
                    x: arguments[1],
                    y: arguments[2],
                    z: arguments[3]
                });
            }
        } catch (error) {
            try {
                if (typeof location === 'object' && location.x !== undefined) {
                    dimension.spawnParticle(fallbacks[particleType] || fallbacks.gravity, location);
                } else {
                    dimension.spawnParticle(fallbacks[particleType] || fallbacks.gravity, {
                        x: arguments[1],
                        y: arguments[2],
                        z: arguments[3]
                    });
                }
            } catch (fallbackError) {
                // Silent fail
            }
        }
    },

    applyGravitationalForce(entity, centerX, centerY, centerZ, strength) {
        const { x, y, z } = entity.location;
        const dx = centerX - x;
        const dy = centerY - y;
        const dz = centerZ - z;

        const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
        if (distance < 0.1) return;

        const forceX = (dx / distance) * strength;
        const forceY = (dy / distance) * strength;
        const forceZ = (dz / distance) * strength;

        try {
            entity.applyImpulse({ x: forceX, y: forceY, z: forceZ });
        } catch (error) {
            // Entity might not have physics
        }
    }
};

// Register shovel component
export function registerCarmotShovel(itemComponentRegistry) {
    itemComponentRegistry.registerCustomComponent('myw:carmot_shovel', {
        onUse(eventData) {
            const { itemStack, source, useDuration } = eventData;
            CarmotShovelSystem.handleShovelUse(source, itemStack, useDuration);
        },

        onUseOn(eventData) {
            const { itemStack, source, block, blockFace, faceLocation } = eventData;
            CarmotShovelSystem.handleTerrainDigging(source, itemStack, block, blockFace);
        },

        onHitEntity(eventData) {
            const { source, hitEntity } = eventData;
            if (source) {
                CarmotShovelSystem.sendActionBar(source, '§6Terrain Warrior §8▸ §7Combat with gravitational force', '§6');
                CarmotShovelSystem.createGravityExcavationEffects(source, source.location, 'entity_hit');

                // Apply gravitational knockback
                try {
                    const dx = hitEntity.location.x - source.location.x;
                    const dz = hitEntity.location.z - source.location.z;
                    const distance = Math.sqrt(dx * dx + dz * dz);

                    if (distance > 0) {
                        hitEntity.applyImpulse({
                            x: (dx / distance) * 1.2,
                            y: 0.4,
                            z: (dz / distance) * 1.2
                        });
                    }
                } catch (error) {
                    // Ignore if cannot apply impulse
                }
            }
        }
    });
}

// Initialize shovel systems
export function initializeCarmotShovelSystems() {
    // Passive gravity effects when holding shovel
    system.runInterval(() => {
        try {
            world.getAllPlayers().forEach(player => {
                const equippableComp = player.getComponent('minecraft:equippable');
                const mainhandItem = equippableComp?.getEquipment(EquipmentSlot.Mainhand);

                if (mainhandItem?.typeId === 'myw:carmot_shovel') {
                    // Create subtle gravity ambient effects
                    if (Math.random() > 0.92) { // 8% chance per tick
                        CarmotShovelSystem.createGravityAmbientEffects(player);
                    }
                }
            });
        } catch (error) {
            // Error in passive effects
        }
    }, 20);

    // Show initialization message
    system.runTimeout(() => {
        world.getAllPlayers().forEach(player => {
            CarmotShovelSystem.sendActionBar(player, '§6Terrain Disruptor System §8▸ §aOnline §7| §6Gravitational Excavation & Vortex', '§6');
        });
    }, 60);

    world.sendMessage('§6[TERRAIN DISRUPTOR] Carmot Shovel System initialized - Earth manipulation ready!');
}

// Create subtle ambient effects
CarmotShovelSystem.createGravityAmbientEffects = function (player) {
    try {
        const location = player.location;

        // Create orbiting gravity particles around feet (earth-themed)
        const angle = Date.now() / 1000;
        const radius = 1.5;

        this.spawnCarmotParticle(player.dimension, {
            x: location.x + Math.cos(angle) * radius,
            y: location.y + 0.2,
            z: location.z + Math.sin(angle) * radius
        }, 'gravity');

        // Secondary orbit at different height
        this.spawnCarmotParticle(player.dimension, {
            x: location.x + Math.cos(angle + Math.PI) * (radius * 0.7),
            y: location.y + 0.8,
            z: location.z + Math.sin(angle + Math.PI) * (radius * 0.7)
        }, 'standard');
    } catch (error) {
        // Error with ambient effects
    }
};