import { world, system, ItemStack, ItemLockMode } from "@minecraft/server";
import { ActionFormData } from "@minecraft/server-ui";

const odLimits = {
    1: 100, 2: 150, 3: 200, 4: 250, 
    5: 300, 6: 320, 7: 350, 8: 370, 
    9: 400, 10: 420
};

function getScore(entity, objectiveId) {
    try {
        const objective = world.scoreboard.getObjective(objectiveId);
        if (!objective) return 0;
        return objective.getScore(entity) ?? 0;
    } catch (e) { return 0; }
}

function astral_book_setup(player) {
    if (!player || !player.isValid() || player.hasTag("magic_unlocked")) return;
    const inv = player.getComponent("inventory").container;
    let found = false;
    for (let i = 0; i < inv.size; i++) {
        const item = inv.getItem(i);
        if (item?.typeId === "nb:astral_world_book") {
            inv.setItem(i, undefined);
            found = true;
            break;
        }
    }
    if (found) {
        player.runCommandAsync("scoreboard objectives add od dummy Od");
        player.runCommandAsync("scoreboard objectives setdisplay sidebar od ascending");
        player.addTag("magic_unlocked");
        const menuMagic = new ItemStack("nb:menu_magia", 1);
        menuMagic.lockMode = ItemLockMode.inventory;
        menuMagic.keepOnDeath = true;
        inv.addItem(menuMagic);
        player.sendMessage("§bAstral Wisdom Unlocked...");
    }
}

system.runInterval(() => {
    const playersWithMagic = world.getPlayers({ tags: ["magic_unlocked"] });
    for (const player of playersWithMagic) {
        const stat_mgc = getScore(player, "stat_mgc") || 1;
        const max_od = odLimits[stat_mgc] || (stat_mgc > 10 ? 420 : 100);
        const regen = (stat_mgc >= 4) ? 4 : 2;
        const currentOd = getScore(player, "od");
        if (currentOd < max_od) {
            const objective = world.scoreboard.getObjective("od");
            objective.addScore(player, regen);
            if (getScore(player, "od") > max_od) objective.setScore(player, max_od);
        }
    }
}, 20);

function safeKnockback(entity, x, z, forceH, forceV) {
    try {
        if (entity.typeId !== "minecraft:player" && entity.typeId !== "minecraft:armor_stand") {
            entity.applyKnockback(x, z, forceH, forceV);
        }
    } catch (e) {}
}

function gale_force(player, magicScore) {
    const view = player.getViewDirection();
    const finalDamage = 5 + (magicScore * 1.5);
    player.runCommandAsync("inputpermission set @s movement disabled");
    player.runCommandAsync("playanimation @s animation.cajado.use1");
    player.runCommandAsync("particle nb:spell_wind ~ ~0.9 ~");
    system.runTimeout(() => {
        const entities = player.dimension.getEntities({ location: player.location, maxDistance: 5 });
        entities.forEach(e => {
            if (e.id !== player.id) {
                e.applyDamage(finalDamage, { cause: 'entityAttack', damagingEntity: player });
                safeKnockback(e, view.x, view.z, 0.8, 0.9);
            }
        });
        player.runCommandAsync("inputpermission set @s movement enabled");
        player.addTag("gale_force_cooldown");
        system.runTimeout(() => player.removeTag("gale_force_cooldown"), 80);
    }, 15);
}

function fire_tornado(player, magicScore) {
    const view = player.getViewDirection();
    const finalDamage = 7 + (magicScore * 1.8);
    player.runCommandAsync("inputpermission set @s movement disabled");
    player.runCommandAsync("playanimation @s animation.cajado.use1");
    player.runCommandAsync("particle nb:fire_tornado ~ ~0.9 ~");
    system.runTimeout(() => {
        const entities = player.dimension.getEntities({ location: player.location, maxDistance: 8 });
        entities.forEach(e => {
            if (e.id !== player.id) {
                e.applyDamage(finalDamage, { cause: 'magma', damagingEntity: player });
                safeKnockback(e, view.x, view.z, 0.6, 0.9);
                e.setOnFire(4, true);
            }
        });
        player.runCommandAsync("inputpermission set @s movement enabled");
        player.addTag("fire_tornado_cooldown");
        system.runTimeout(() => player.removeTag("fire_tornado_cooldown"), 320);
    }, 15);
}

function earth_bulwark(player, magicScore) {
    const view = player.getViewDirection();
    const finalDamage = 9 + (magicScore * 2.0);
    player.runCommandAsync("inputpermission set @s movement disabled");
    player.runCommandAsync("playanimation @s animation.cajado.use1");
    player.runCommandAsync("particle nb:earth_bulwark ~ ~0.9 ~");
    system.runTimeout(() => {
        const entities = player.dimension.getEntities({ location: player.location, maxDistance: 7 });
        entities.forEach(e => {
            if (e.id !== player.id) {
                e.applyDamage(finalDamage, { cause: 'blockExplosion', damagingEntity: player });
                safeKnockback(e, view.x, view.z, 0.8, 0.8);
                e.runCommandAsync("effect @s slowness 6 3 true");
            }
        });
        player.runCommandAsync("inputpermission set @s movement enabled");
        player.addTag("earth_bulwark_cooldown");
        system.runTimeout(() => player.removeTag("earth_bulwark_cooldown"), 350);
    }, 20);
}

world.beforeEvents.itemUse.subscribe(event => {
    const player = event.source;
    const item = event.itemStack;
    if (item.typeId === "nb:astral_world_book" && !player.hasTag("magic_unlocked")) {
        system.run(() => astral_book_setup(player));
    }
    if (item.typeId === "nb:cajado") {
        const od = getScore(player, "od");
        const mgc = getScore(player, "stat_mgc");
        const objective = world.scoreboard.getObjective("od");

        if (player.hasTag("gale_force")) {
            if (player.hasTag("gale_force_cooldown")) return;
            if (od >= 30) { system.run(() => { objective.addScore(player, -30); gale_force(player, mgc); }); }
            else { player.runCommandAsync(`title @s actionbar §eInsufficient OD! (30)`); }
        } else if (player.hasTag("fire_ball")) {
            if (player.hasTag("fire_tornado_cooldown")) return;
            if (od >= 40) { system.run(() => { objective.addScore(player, -40); fire_tornado(player, mgc); }); }
            else { player.runCommandAsync(`title @s actionbar §cInsufficient OD! (40)`); }
        } else if (player.hasTag("earth_bulwark")) {
            if (player.hasTag("earth_bulwark_cooldown")) return;
            if (od >= 35) { system.run(() => { objective.addScore(player, -35); earth_bulwark(player, mgc); }); }
            else { player.runCommandAsync(`title @s actionbar §2Insufficient OD! (35)`); }
        }
    }
});

world.afterEvents.itemUse.subscribe((event) => {
    const player = event.source;
    if (event.itemStack.typeId === 'nb:menu_magia') {
        const magicScore = getScore(player, 'stat_mgc');
        const form = new ActionFormData()
            .title(`Magic Abilities (Mgc: ${magicScore})`)
            .body('Select a Magic Ability based on your Stats.')
            .button(magicScore >= 1 ? '§2Gale Force\n§r§oMgc Cost:1' : '§cGale Force\n§r§oMgc Cost:1', 'textures/magia/gale_force.png')
            .button(magicScore >= 2 ? '§2Fire Tornado\n§r§oMgc Cost:2' : '§cFire Tornado\n§r§oMgc Cost:2', 'textures/magia/fire_tornado.png')
            .button(magicScore >= 5 ? '§2Earth Bulwark\n§r§oMgc Cost:5' : '§cEarth Bulwark\n§r§oMgc Cost:5', 'textures/magia/earth_bulwark.png');

        form.show(player).then((result) => {
            if (result.canceled) return;
            const tags = ['gale_force', 'fire_ball', 'earth_bulwark'];
            const reqs = [1, 2, 5];
            if (magicScore >= reqs[result.selection]) {
                tags.forEach(t => player.removeTag(t));
                player.addTag(tags[result.selection]);
                player.sendMessage(`§aSkill ${tags[result.selection].replace('_', ' ')} equipped.`);
            } else {
                player.sendMessage("§cYou need more Magic Stat to equip this.");
                player.playSound("note.bass");
            }
        });
    }
});