import { BlockPermutation, Dimension, EntityComponentTypes, EntityHealthComponent, EntityProjectileComponent, EquipmentSlot, GameMode, ItemStack, Player, system, world } from '@minecraft/server'
import { dynamicArmorsConfig } from "./armors.config";
import { Vec3 } from '../UTILS/Vec3';

export const daInjections = new Map();
const daICache = {};
const glitchEscapeCooldown = new Map(); // player.id -> tick or timestamp
function damageEquippedItem(player, slot = EquipmentSlot.Mainhand) {
    if (!(player instanceof Player)) return;
    const equippable = player.getComponent("minecraft:equippable");
    if (!equippable) return;
    const equipped = equippable.getEquipmentSlot(slot);
    if (!equipped || !equipped.hasItem()) return;
    if (player.getGameMode() === GameMode.creative) return;
    const itemStack = equipped.getItem();
    const durability = itemStack.getComponent("minecraft:durability");
    if (!durability) return;
    const enchantable = itemStack.getComponent("minecraft:enchantable");
    const unbreakingLevel = enchantable?.getEnchantment("unbreaking")?.level ?? 0;
    const damageChance = durability.getDamageChance(unbreakingLevel) / 100;
    if (Math.random() > damageChance) return;
    if (durability.damage + 1 >= durability.maxDurability) {
        equipped.setItem(undefined);
        player.playSound("random.break");
    } else {
        durability.damage++;
        equipped.setItem(itemStack);
    }
}
function damageHackerShield(player) {
    if (!(player instanceof Player)) return;
    const equippable = player.getComponent("minecraft:equippable");
    if (!equippable) return;
    const main = equippable.getEquipmentSlot(EquipmentSlot.Mainhand);
    const off = equippable.getEquipmentSlot(EquipmentSlot.Offhand);
    const isHackerShield = (slot) => {
        const item = slot?.getItem();
        return item?.typeId === "dive_hw:hacker_shield";
    };
    let shieldSlot = null;
    if (isHackerShield(main)) {
        shieldSlot = main;
    } else if (isHackerShield(off)) {
        shieldSlot = off;
    }
    if (!shieldSlot || !shieldSlot.hasItem()) return;
    if (player.getGameMode() === GameMode.creative) return;
    const itemStack = shieldSlot.getItem();
    const durability = itemStack.getComponent("minecraft:durability");
    if (!durability) return;
    const enchantable = itemStack.getComponent("minecraft:enchantable");
    const unbreakingLevel = enchantable?.getEnchantment("unbreaking")?.level ?? 0;
    const damageChance = durability.getDamageChance(unbreakingLevel) / 100;
    if (Math.random() > damageChance) return;
    if (durability.damage + 1 >= durability.maxDurability) {
        shieldSlot.setItem(undefined);
        player.playSound("random.break");
    } else {
        durability.damage++;
        shieldSlot.setItem(itemStack);
    }
}

daInjections.set("dive_hw:hacker_armor_full_set_green", {
    hurtEntity: {
        dependenceFullSet: {
            key: "dive_hw:hacker_armor_green",
            excludeHandsSlots: true
        },
        extraActions: (player, cause, damage, damager) => {
            const healthComp = player.getComponent("minecraft:health");
            const currentHP = healthComp.currentValue;
            if (Math.random() < 0.5 && damager) {
                player.applyImpulse({x: 0, y: 0, z: 0}); // anula knockback
                player.dimension.spawnParticle("minecraft:mobspell", player.location);
                player.runCommandAsync(`title @s actionbar §bAnti-Knockback`);
            }
            if (currentHP <= 6 && !player.hasTag("glitch_escape_cooldown")) {
                const dir = player.getViewDirection();
                const dest = {
                    x: player.location.x + dir.x * 10,
                    y: player.location.y + 1,
                    z: player.location.z + dir.z * 10
                };
                player.teleport(dest, { checkForBlocks: true });
                player.addEffect("absorption", 100, { amplifier: 1, showParticles: true });
                player.runCommandAsync(`title @s actionbar §dGlitch Escape Activated!`);
                player.addTag("glitch_escape_cooldown");
                //  (2400 ticks)
                system.runTimeout(() => {
                    if (player?.isValid()) player.removeTag("glitch_escape_cooldown");
                }, 100);
            }
        }
    }
});
daInjections.set("dive_hw:hacker_armor_full_set_red", {
    hurtEntity: {
    dependenceFullSet: {
        key: "dive_hw:hacker_armor_red",
        excludeHandsSlots: true
    },
    extraActions: (player, cause, damage, damager) => {
        const healthComp = player.getComponent("minecraft:health");
        const currentHP = healthComp.currentValue;
        if (currentHP <= 10 && !player.hasTag("glitch_escape_cooldown")) {
            player.addTag("glitch_escape_cooldown");
            player.addTag("glitch_fire_trail");
            player.addEffect("strength", 200, { amplifier: 1, showParticles: false });
            player.addEffect("speed", 200, { amplifier: 1, showParticles: false });
            player.addEffect("resistance", 200, { amplifier: 1, showParticles: false });
            let lastPos = { x: player.location.x, y: player.location.y, z: player.location.z };
            const trail = system.runInterval(() => {
                const currentPos = player.location;
                const dx = Math.abs(currentPos.x - lastPos.x);
                const dz = Math.abs(currentPos.z - lastPos.z);
                const moved = dx > 0.05 || dz > 0.05;
                if (moved) {
                    const blockBelow = player.dimension.getBlock({
                        x: Math.floor(currentPos.x),
                        y: Math.floor(currentPos.y - 1),
                        z: Math.floor(currentPos.z)
                    });
                    if (blockBelow && blockBelow.isAir === false) {
                        player.dimension.setBlockType(blockBelow.location, "minecraft:fire");
                    }
                    lastPos = currentPos;
                }
            }, 5);
            system.runTimeout(() => {
                player.removeTag("glitch_fire_trail");
                system.clearRun(trail);
            }, 100);
            //  (2400 ticks)
            system.runTimeout(() => {
                if (player?.isValid()) player.removeTag("glitch_escape_cooldown");
            }, 20);
        }
    }
},
    hitEntity: {
        dependenceFullSet: {
            key: "dive_hw:hacker_armor_red",
            excludeHandsSlots: true
        },
        extraActions: (player, damager) => {
            const { hacker_armor_red_helmet: { secondToAddFireAtEnemy, explodeProbability } } = dynamicArmorsConfig;
            damager.setOnFire(secondToAddFireAtEnemy, false);
            if (!explodeProbability.checkProbability) return;
            player.dimension.createExplosion(damager.location, 3, { breaksBlocks: false, causesFire: true, source: player });
        }
    }
});
daInjections.set("dive_hw:hacker_armor_full_set_blue", {
    hurtEntity: {
        dependenceFullSet: {
            key: "dive_hw:hacker_armor_blue",
            excludeHandsSlots: true
        },
        extraActions: (player, cause, damage, damager) => {
            const id = player.id;
            const health = player.getComponent("health");
            const {
                hacker_armor_blue_helmet: {
                    detectArea,
                    freezeAttackersProbability,
                    secondsInFreeze
                }
            } = dynamicArmorsConfig;
            // === 🔷 CYBER FREEZE ===
            const nearby = player.dimension.getEntities({
                location: player.location,
                maxDistance: detectArea,
                excludeFamilies: ["inanimate"]
            }).filter(e => e.id !== id);

            for (const entity of nearby) {
                entity.addEffect("slowness", 60, { amplifier: 1 });
            }

            if (freezeAttackersProbability >= 1 || Math.random() < freezeAttackersProbability) {
                if (damager?.isValid()) {
                    const freeze = system.runInterval(() => {
                        damager.teleport(damager.location);
                    }, 1);
                    system.runTimeout(() => system.clearRun(freeze), secondsInFreeze * 20);
                }
            }

            // === 🔰 GLITCH SHIELD (escudo activado en vida baja) ===
            if (health.currentValue <= 6 && !player.hasTag("glitch_shield_cooldown")) {
                player.addEffect("resistance", 200, { amplifier: 1, showParticles: true });
                player.addEffect("absorption", 200, { amplifier: 1, showParticles: true });
                const nearbyEnemies = player.dimension.getEntities({
                    location: player.location,
                    maxDistance: 3,
                    excludeFamilies: ["inanimate"]
                });

                for (const entity of nearbyEnemies) {
                    if (entity.id === id) continue;

                    const dx = entity.location.x - player.location.x;
                    const dz = entity.location.z - player.location.z;
                    const dist = Math.sqrt(dx ** 2 + dz ** 2);
                    if (dist > 0) {
                        entity.applyKnockback(dx / dist, dz / dist, 2.5, 0.5);
                    }
                }

                player.addTag("glitch_shield_cooldown");
                system.runTimeout(() => {
                    if (player?.isValid()) player.removeTag("glitch_shield_cooldown");
                }, 20); // 2400
            }
        }
    }
});
daInjections.set("dive_hw:hacker_armor_blue_helmet", {
    setInterval: {
        effectsToAdd: [
            ["night_vision", 300, 0, false]
        ],
        effectsToRemove: [
            "blindness"
        ]
    }
});
daInjections.set("dive_hw:hacker_armor_green_helmet", {
    setInterval: {
        effectsToAdd: [
            ["night_vision", 300, 0, false]
        ]
    }
});
daInjections.set("dive_hw:hacker_armor_red_helmet", {
    setInterval: {
        effectsToAdd: [
            ["night_vision", 300, 0, false]
        ],
        effectsToRemove: [
            "wither",
            "poison"
        ]
    }
});
daInjections.set("dive_hw:hacker_armor_blue_chestplate", {
    setInterval: {
        effectsToAdd: [
            ["health_boost", 25, 1, false],
            ["resistance", 25, 0, false]
        ],
        extraActions: (player) => {
            const currentHealth = player.getComponent(EntityHealthComponent.componentId).currentValue;
            if(currentHealth > 26) {
                player.getComponent(EntityHealthComponent.componentId).setCurrentValue(currentHealth-1);
            }
        }
    },
    hurtEntity: {
        extraActions: (player, cause, damage) => {
            const { hacker_armor_blue_chestplate: { cancelKnockbackProbability } } = dynamicArmorsConfig;
            if (!cancelKnockbackProbability.checkProbability) return;

            const currentHealth = player.getComponent(EntityHealthComponent.componentId).currentValue;
            player?.applyKnockback(0, 0, 0, 0);
            player.getComponent(EntityHealthComponent.componentId).setCurrentValue(currentHealth + damage);
        }
    }
});
daInjections.set("dive_hw:hacker_armor_green_chestplate", {
    setInterval: {
        effectsToAdd: [
            ["health_boost", 25, 0, false],
            ["resistance", 25, 0, false]
        ]
    },
    hurtEntity: {
    extraActions: (player, cause, data, damage) => {
        const health = player.getComponent(EntityComponentTypes.Health);
        if (cause === "fire" || cause === "lava" || cause === "fire_tick") {
            let damage=1;
            const reduced = Math.floor(damage * 0.75); 
            player.applyDamage(0);
            health.setCurrentValue(Math.min(health.effectiveMax, health.currentValue - reduced));
            return;
        }
        else {
            if (player?.getVelocity) {
                const velocity = player.getVelocity();
                player.applyKnockback(velocity.x, velocity.z, 0.5, 0.3);
            }
        }
        
    }
}

});
daInjections.set("dive_hw:hacker_armor_red_chestplate", {
    setInterval: {
        effectsToAdd: [
            ["health_boost", 25, 0, false],
            ["resistance", 25, 1, false]
        ]
    },
    hurtEntity: {
        extraActions: (player, cause) => {
            if (!["entityAttack", "projectile"].includes(cause)) return;

            const { hacker_armor_red_chestplate: { probabilityToResistance, secondsOfResistance, probabilityToProjectilesResistance } } = dynamicArmorsConfig;
            if (cause == "entityAttack" && probabilityToResistance.checkProbability) {
                player.addEffect("resistance", secondsOfResistance * 20, { amplifier: 0, showParticles: false });
                return;
            }
            if (probabilityToProjectilesResistance.checkProbability) {
                player.addEffect("regeneration", 20, { amplifier: 255, showParticles: false });
                sendRandomArrow(player.getHeadLocation(), player.dimension);
            }
        }
    },
});
daInjections.set("dive_hw:hacker_armor_blue_leggings", {
    setInterval: {
        effectsToAdd: [
            ["speed", 25, 0, false],
            ["jump_boost", 25, 0, false]
        ]
    }
});
daInjections.set("dive_hw:hacker_armor_green_leggings", {
    setInterval: {
        effectsToAdd: [
            ["speed", 25, 0, false],
            ["jump_boost", 25, 0, false]
        ]
    }
});
daInjections.set("dive_hw:hacker_armor_red_leggings", {
    setInterval: {
        effectsToAdd: [
            ["speed", 25, 0, false],
            ["jump_boost", 25, 0, false]
        ]
    }
});
daInjections.set("dive_hw:hacker_armor_blue_boots", {
    setInterval: {
        extraActions: (player) => {
            const { hacker_armor_blue_boots: { iceToDestroy, rangeToIce } } = dynamicArmorsConfig;
            const locs = getCircleFilled(player.location, rangeToIce);
            for (const loc of locs) {
                const block = player.dimension.getBlock(loc);

                if (block?.typeId == "minecraft:water") {
                    player.dimension.setBlockPermutation(loc, BlockPermutation.resolve("minecraft:ice"));
                    system.runTimeout(() => {
                        player.dimension.setBlockPermutation(loc, BlockPermutation.resolve("minecraft:water"));
                    }, iceToDestroy * 20);
                }
            }
        }
    }
});
daInjections.set("dive_hw:hacker_armor_green_boots", {
    setInterval: {
        requiresSneaking: true,
        effectsToAdd: [
            ["invisibility", 25, 0, false]
        ],
        extraActions: (player) => {
            player.playAnimation("animation.dive_hw.hacker_player.static", {
                controller: "ItemUseSneakPerson",
                stopExpression: "q.all_animations_finished"
            });
        }
    }
});
daInjections.set("dive_hw:hacker_armor_red_boots", {
    setInterval: {
        effectsToAdd: [
            ["fire_resistance", 25, 0, false]
        ],
        extraActions: (player) => {
            if (!player.isSprinting) return;
            player.dimension.spawnParticle("dive_hw:flame_trail", {x: player.location.x, y: player.location.y, z: player.location.z})
        }
    }
});
daInjections.set("dive_hw:hacker_shield", {
    hurtEntity: {
        requiresSneaking: true,
        extraActions: (player, cause, damage, damager) => {
            damageHackerShield(player);
            try {
                const { hacker_shield: { particleToHit, ondaProbability, ondaRange, particleToOnda } } = dynamicArmorsConfig;
                const directionVec = Vec3(damager?.location?.x - player.location.x, damager?.location?.y - player.location.y, damager?.location?.z - player.location.z);
                const direction = Vec3.normalize(directionVec);
                const lookDirection = player.getViewDirection();
                let angle = Math.atan2(lookDirection.x * direction.z - lookDirection.z * direction.x, lookDirection.x * direction.x + lookDirection.z * direction.z) * (180 / Math.PI);
                if (angle > 180) {
                    angle -= 360;
                } else if (angle < -180) {
                    angle += 360;
                };
                const angleThreshold = 45;
                if (Math.abs(angle) <= angleThreshold) {
                    const impulse = 1.3;
                    const currentHealth = player.getComponent("minecraft:health").currentValue;
                    damager?.applyKnockback(direction.x, direction.z, impulse, impulse * .4);
                    player.getComponent("minecraft:health").setCurrentValue(currentHealth + damage);
                    player?.applyKnockback(0, 0, 0, 0);
                    world.playSound(`item.shield.block`, player.location);
                    player.dimension.spawnParticle(particleToHit, player.location);
                    if (ondaProbability.checkProbability) {
                        player.playAnimation(`animation.dive_hw.hacker_shield.tpp_use`, { controller: `ItemUseFirstPerson`, stopExpression: `q.all_animations_finished` });
                        
                        player.addTag("dive_hw.stop_animations");
                        if (player.hasTag("dive_hw.stop_animations")) {
                            system.runTimeout(() => {
                                player.removeTag("dive_hw.stop_animations");
                            }, 22);
                        };
                        player.dimension.spawnParticle(particleToOnda, player.location);
                        system.runTimeout(() => {
                            const entities = player.dimension.getEntities({ location: player.location, minDistance: 0, maxDistance: ondaRange }).filter(e => e.id !== player.id);
                            entities.forEach(e => applyCircleImpulse(e, player.location));
                        }, 14);
                    }
                }
            } catch (error) {
                const currentHealth = player.getComponent("minecraft:health").currentValue;
                player.getComponent("minecraft:health").setCurrentValue(currentHealth + damage);
                player.applyKnockback(0, 0, 0, 0);
            }
        }
    }
});
const wingsUsageMap = new Map(); // <player.id, tickCount>
daInjections.set("dive_hw:hacker_wings", {
    setInterval: {
        extraActions: (player) => {
            if (!player.hasTag("WingsRigt")) return;
            if (player.isOnGround) {
                player.removeTag("WingsRigt");
                player.removeTag("WingsSound");
                return;
            }
            // Contador de uso
            const ticks = wingsUsageMap.get(player.id) ?? 0;
            if (ticks >= 40) { // 20 ticks ≈ 1 segundo
                damageEquippedItem(player, EquipmentSlot.Chest); // ✅ Aplica daño a alas
                wingsUsageMap.set(player.id, 0);
            } else {
                wingsUsageMap.set(player.id, ticks + 1);
            }
            const vw = player.getViewDirection();
            const rotX = player.getRotation().x;
            const getVerticalKnockback = (angle) => {
                if (angle > 75) return null;
                if (angle > 50) return -0.55;
                if (angle > 30) return -0.4;
                if (angle > 10) return -0.2;
                if (angle > 0) return -0.05;
                if (angle > -10) return 0.1;
                if (angle > -20) return 0.2;
                if (angle > -35) return 0.3;
                return 0.4;
            };
            const getHorizontalSpeed = (angle) => {
                if (angle > 60 || angle < -60) return 0.1;
                if (angle > 40 || angle < -40) return 0.2;
                if (angle > 20 || angle < -20) return 0.3;
                if (angle > 10 || angle < -10) return 0.4;
                return 0.5;
            };
            if (!player.hasTag("WingsSound")) {
                player.playSound("mob.enderdragon.flap", { volume: 1, pitch: 1 });
                player.addTag("WingsSound");
            }
            if (rotX > 50) {
                player.addEffect("slow_falling", 40, { showParticles: false, amplifier: 0 });
                return;
            }
            const verticalKnockback = getVerticalKnockback(rotX);
            const horizontalSpeed = getHorizontalSpeed(rotX);
            if (verticalKnockback !== null && (system.currentTick % 1 === 0)) {
                player.applyKnockback(vw.x, vw.z, horizontalSpeed, verticalKnockback);
                player.addEffect("slow_falling", 40, { showParticles: false, amplifier: 0 });
            }
        }
    }
});


function getCircleFilled(center, radius) {
    const { x, y, z } = center;
    const points = [];

    for (let dx = -radius; dx <= radius; dx++) {
        for (let dz = -radius; dz <= radius; dz++) {
            if (dx * dx + dz * dz <= radius * radius) {
                points.push({ x: x + dx, y: y - 1, z: z + dz });
            }
        }
    }

    return points;
}
function sendRandomArrow(center, dimension) {
    center.y = center.y + 1;
    const arrow = dimension.spawnEntity("minecraft:arrow", center);
    arrow.applyImpulse({
        x: Math.random(),
        y: 0.5,
        z: Math.random()
    });
}
function applyCircleImpulse(entity, player_location) {
    let dx = entity.location.x - player_location.x;
    let dy = entity.location.y - player_location.y;
    let dz = entity.location.z - player_location.z;
    let distance = Math.sqrt(dx * dx + dy * dy + dz * dz);

    if (distance == 0) return;

    let nx = dx / distance;
    let nz = dz / distance;

    if (entity instanceof Player) {
        entity.applyKnockback(nx, nz, 1.5, .5);
        return;
    }

    entity.applyImpulse({
        x: nx * .7,
        y: .3,
        z: nz * .7
    });
    return;
}

daICache.fly = new Set();
daICache.excludes = new Set();
daICache.counts = new WeakMap();
daICache.count = new Map();