import { world, system, EasingType, EntityDamageCause, ItemStack } from "@minecraft/server";
import { ActionFormData, ModalFormData } from "@minecraft/server-ui";
import { getLearnPoints, spendLearnPoint, cacheLearnPoints } from "../utils/learnPoints.js";
import { buildOffensiveSummary, formatTyping } from "../utils/typeEffectiveness.js";

/**
 * Normalize Pokémon identifiers so UI/battle lookups don't crash.
 * Handles missing namespace, casing, spawn_egg suffixes, spaces/hyphens, and some "converted" names.
 */
function normalizePokemonId(id) {
    if (id === undefined || id === null) return null;

    let s = String(id).trim().toLowerCase();

    // strip common suffixes
    s = s.replace(/_spawn_egg$/g, "");
    s = s.replace(/_fainted$/g, "");

    // strip common export suffix
    s = s.replace(/ - converted$/g, "");
    s = s.replace(/-converted$/g, "");

    // normalize punctuation
    s = s.replace(/'/g, "");
    s = s.replace(/-/g, "_");
    s = s.replace(/\s+/g, "_");

    // ensure namespace
    if (!s.includes(":")) s = "pr:" + s;

    return s;
}

function getPokemonDataSafe(rawId) {
    const nid = normalizePokemonId(rawId);
    if (!nid) return null;
    return pokemonsData.find(p => normalizePokemonId(p.id) === nid) ?? null;
}

function evoSwapPokemon(player, pokemon, evoTargetId, newLevel) {
    try {
        try { pokemon.dimension.spawnParticle("snowstorm:magic", pokemon.location);
        try { pokemon.dimension.spawnParticle("pr:evolution_burst", pokemon.location); } catch (e) {} } catch (e) {}
        try { player.playSound("random.orb"); } catch (e) {}

        const slot = pokemon.getDynamicProperty("pr:slot");
        const isSended = pokemon.getDynamicProperty("pr:sended_pokemon") === true;

        const nick = pokemon.getDynamicProperty("pr:nickname");
        const owner = pokemon.getDynamicProperty("pr:owner");
        const ownerName = pokemon.getDynamicProperty("pr:owner_name");
        const tamed = pokemon.getDynamicProperty("pr:tamed");
        const move1 = pokemon.getDynamicProperty("pr:move1");
        const move2 = pokemon.getDynamicProperty("pr:move2");
        const move3 = pokemon.getDynamicProperty("pr:move3");
        const move4 = pokemon.getDynamicProperty("pr:move4");
        const onBattle = pokemon.getDynamicProperty("pr:on_battle");

        system.runTimeout(() => {
            try {
                const loc = pokemon.location;
                const dim = pokemon.dimension;
                const evolved = dim.spawnEntity(evoTargetId, {x: loc.x, y: loc.y, z: loc.z});
                try { dim.spawnParticle("pr:evolution_burst", {x: loc.x, y: loc.y + 1, z: loc.z}); } catch (e) {}
                try { evolved.setDynamicProperty("pr:slot_index", pokemon.getDynamicProperty("pr:slot_index")); } catch(e) {}

                evolved.setDynamicProperty("pr:level", newLevel);
                evolved.setDynamicProperty("pr:nickname", nick);
                evolved.setDynamicProperty("pr:owner", owner);
                evolved.setDynamicProperty("pr:owner_name", ownerName);
                evolved.setDynamicProperty("pr:tamed", tamed);
                evolved.setDynamicProperty("pr:move1", move1);
                evolved.setDynamicProperty("pr:move2", move2);
                evolved.setDynamicProperty("pr:move3", move3);
                evolved.setDynamicProperty("pr:move4", move4);
                evolved.setDynamicProperty("pr:on_battle", onBattle);

                evolved.setDynamicProperty("pr:slot", slot);
                evolved.setDynamicProperty("pr:sended_pokemon", isSended);

                try { evolved.getComponent("minecraft:tameable")?.tame(player); } catch (e) {}

                const evoInfo = pokemonsData.find(p => p.id === evoTargetId);
                const hp = evolved.getComponent("minecraft:health");
                if (evoInfo && hp) hp.setCurrentValue(evoInfo.maxHealth);

                if (nick == undefined) {
                    evolved.nameTag = formatEntityName(evolved) + " | Lvl: §a" + evolved.getDynamicProperty("pr:level") + "§r\n" + "Owner:§a " + ownerName;
                } else {
                    evolved.nameTag = nick + " | Lvl: §a" + evolved.getDynamicProperty("pr:level") + "§r\n" + "Owner:§a " + ownerName;
                }

                if (isSended) player.setDynamicProperty("pr:sended_pokemon_id", evolved.id);

                pokemon.remove();
                player.sendMessage(`§a${formatEntityName2({typeId: pokemon.typeId})} evolved into ${formatEntityName2({typeId: evolved.typeId})}!`);
            } catch (e) {}
        }, 30);
    } catch (e) {}
}


import { pokemonsData } from "./data.js"
import { pokemonCanLearn } from "./pokemonCanLearn.js";
import { MovesData } from "./moves.js";
import { optionsMenu, formatName } from "../importsmain.js";
import { pokemonUtils } from "../utils/pokemonUtils.js";

world.afterEvents.playerSpawn.subscribe(({ player }) => {
});
// ja foi
system.runInterval(() => {
    const players = world.getAllPlayers();
    for (let player of players) {
        const pokemons = player.dimension.getEntities({
            location: player.location,
            families: ["pokemon"],
            maxDistance: 32,
        })
        for (let pokemon of pokemons) {
            if (pokemon.getDynamicProperty("pr:battle") == true) {
                pokemon.runCommand("effect @s slowness 1 255 true")
            }
        }
    }
}, 1);

export function setMovesOnSpawn(player, pokemon) {
    const pokemonData = pokemonsData.find(poke => poke.id == pokemon.typeId)
    if (pokemon.getDynamicProperty("pr:move1") == undefined) {
        pokemon.setDynamicProperty("pr:move1", pokemonData.move1)
    }
    if (pokemon.getDynamicProperty("pr:move2") == undefined) {
        pokemon.setDynamicProperty("pr:move2", pokemonData.move2)
    }
    if (pokemon.getDynamicProperty("pr:move3") == undefined) {
        pokemon.setDynamicProperty("pr:move3", pokemonData.move3)
    }
    if (pokemon.getDynamicProperty("pr:move4") == undefined) {
        pokemon.setDynamicProperty("pr:move4", pokemonData.move4)
    }
    console.warn(pokemon.getDynamicProperty("pr:move1"))
    console.warn(pokemon.getDynamicProperty("pr:move2"))
    console.warn(pokemon.getDynamicProperty("pr:move3"))
    console.warn(pokemon.getDynamicProperty("pr:move4"))
}

world.afterEvents.itemUse.subscribe((data) => {
    let { source: player, itemStack: item } = data;
    if (item.typeId == "minecraft:stick") {
        //dailyMenu(player)
        //player.removeTag("pr:started")
        //player.setDynamicProperty("pr:sended_pokemon", false)
        //player.setDynamicProperty("pr:sended_pokemon_id", 0)
        //player.setDynamicProperty("pr:sended_pokemon_slot", 0)
        //starterMenu(player, 0)
    }
    if (item.typeId == "pr:arceus_phone" && player.isSneaking) {
        dailyMenu(player)
        //player.removeTag("pr:started")
        //starterMenu(player, 0)
    }
});

export function sendOutMenu(player) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Options");
    form.body(`000000000000`)
    const inv = player.getComponent("minecraft:inventory").container
    for (let i = 1; i < 7; i++) {
        form.button(`Slot ` + i);
        functions.push((res) => {
            /* multi-out (anti-duplicate) */
            const __pr_slotKey = `pr:out_slot_${i}`;
            let __pr_alreadyOut = false;

            // Fast, race-free check first (prevents spam-duplication)
            try { if (player.getDynamicProperty(__pr_slotKey) === true) __pr_alreadyOut = true; } catch (e) {}

            // Fallback scan (handles restarts / missing flags)
            try {
                const __pr_near = player.dimension.getEntities({ location: player.location, maxDistance: 160, families: ["pokemon"] });
                for (const __pr_e of __pr_near) {
                    try {
                        if (__pr_e.getDynamicProperty("pr:owner_name") !== player.name) continue;
                        if (Number(__pr_e.getDynamicProperty("pr:slot")) === i) { __pr_alreadyOut = true; try { player.setDynamicProperty(__pr_slotKey, true); } catch (e) {} break; }
                    } catch (e) {}
                }
            } catch (e) {}
            if (!__pr_alreadyOut) {
                // mark slot as out immediately to prevent duplicate spawns if the player spams the menu
                try { player.setDynamicProperty(__pr_slotKey, true); } catch (e) {}
                const slotIndex = i - 1; // 0-5
                const slotData = pokemonUtils.getPokemonFromSlot(player, slotIndex);
                const slotName = slotData?.typeId ? slotData.typeId.replace("pr:", "") : player.getDynamicProperty(`pr:slot_${i}_name`);
                const slotLevel = slotData?.level ?? player.getDynamicProperty(`pr:slot_${i}_level`) ?? 1;
                const slotHealth = slotData?.health ?? player.getDynamicProperty(`pr:slot_${i}_health`) ?? 0;

                const slotMove1 = slotData?.move1 ?? player.getDynamicProperty(`pr:slot_${i}_move_1`);
                const slotMove2 = slotData?.move2 ?? player.getDynamicProperty(`pr:slot_${i}_move_2`);
                const slotMove3 = slotData?.move3 ?? player.getDynamicProperty(`pr:slot_${i}_move_3`);
                const slotMove4 = slotData?.move4 ?? player.getDynamicProperty(`pr:slot_${i}_move_4`);

                const slotNick = slotData?.name ?? player.getDynamicProperty(`pr:slot_${i}_nickname`);

                const pokemon = player.dimension.spawnEntity("pr:" + formatName(slotName), {
                    x: player.location.x,
                    y: player.location.y + 1,
                    z: player.location.z
                })
                // track which entity belongs to this slot (best-effort)
                try { player.setDynamicProperty(`pr:out_id_${i}`, pokemon.id); } catch (e) {}
                if (!pokemon) {
                    try { player.setDynamicProperty(__pr_slotKey, false); } catch (e) {}
                    player.onScreenDisplay.setActionBar("Failed to send out (spawn error).")
                    return;
                }
                const currentHealthValue = pokemon.getComponent("minecraft:health");
                const valueHP = slotHealth
                const valueLV = slotLevel
                let valueInN = Number(valueHP);

                pokemon.setDynamicProperty(`pr:move1`, slotMove1)
                pokemon.setDynamicProperty(`pr:move2`, slotMove2)
                pokemon.setDynamicProperty(`pr:move3`, slotMove3)
                pokemon.setDynamicProperty(`pr:move4`, slotMove4)

                setMovesOnSpawn(player, pokemon)
                currentHealthValue.setCurrentValue(valueInN)
                pokemon.getComponent("minecraft:tameable").tame(player)
                pokemon.setDynamicProperty("pr:tamed", true)
                pokemon.setDynamicProperty("pr:nickname", slotNick)
                pokemon.setDynamicProperty("pr:owner", player.id)
                pokemon.setDynamicProperty("pr:owner_name", player.name)
                pokemon.setDynamicProperty("pr:level", slotLevel)
                if (pokemon.getDynamicProperty("pr:nickname") == undefined) {
                    pokemon.nameTag = formatEntityName(pokemon) + " | Lvl: §a" + pokemon.getDynamicProperty("pr:level") + "§r\n" + "Owner:§a " + player.name
                } else {
                    pokemon.nameTag = pokemon.getDynamicProperty("pr:nickname") + " | Lvl: §a" + pokemon.getDynamicProperty("pr:level") + "§r\n" + "Owner:§a " + player.name
                }
                pokemon.setDynamicProperty("pr:slot", i)
                pokemon.setDynamicProperty("pr:sended_pokemon", true)

                player.setDynamicProperty("pr:sended_pokemon", true)
                player.setDynamicProperty("pr:sended_pokemon_id", pokemon.id)
                player.setDynamicProperty("pr:sended_pokemon_slot", i)
                // (patched) keep slot UI data while Pokémon is sent out
} else {
                player.onScreenDisplay.setActionBar("That party slot is already out!")
            }
        });
    }
    {
        form.button("Close");
        functions.push((res) => {
        });
    }
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            return;
        }
        functions[res.selection]();
    });
}

export function arceusMenu(player) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Arceus");
    form.body(`000000000000`)
    {
        form.button("Send out");
        functions.push((res) => {
            sendOutMenu(player)
        });
    }
    {
        form.button("Return");
        functions.push((res) => {
            try {
                player.sendMessage("§aAttempting to return your Pokémon...");

                // Return ALL owned/tamed Pokémon near the player
                const nearby = player.dimension.getEntities({ location: player.location, maxDistance: 160, families: ["pokemon"] });

                let returned = 0;

                for (const pokemon of nearby) {
                    try {
                        if (pokemon.getDynamicProperty("pr:owner_name") !== player.name) continue;

                        // Only return things that look like player-owned/tamed Pokémon
                        const isTamed = pokemon.getDynamicProperty("pr:tamed") === true;
                        if (!isTamed) continue;

                        const pokemonData = pokemonsData.find(pokemone => pokemone.id == pokemon.typeId) ?? { maxHealth: 1 };
                        const slot = Number(pokemon.getDynamicProperty("pr:slot")) || 1;

                        let pokeHealth = 1;
                        try { pokeHealth = pokemon.getComponent("minecraft:health").currentValue; } catch (e) {}
                        const pokeMaxHealth = pokemonData.maxHealth ?? 1;
                        const pokeHBar = Math.round((pokeHealth / pokeMaxHealth) * 100);

                        // Save back to the correct slot
                        try { player.setDynamicProperty(`pr:slot_${slot}_level`, Number(pokemon.getDynamicProperty("pr:level")) || 1); } catch (e) {}
                        try { player.setDynamicProperty(`pr:slot_${slot}_health`, pokeHBar); } catch (e) {}
                        try { player.setDynamicProperty(`pr:slot_${slot}_health_true`, pokeHealth); } catch (e) {}
                        try { player.setDynamicProperty(`pr:slot_${slot}_name`, formatEntityName2(pokemon)); } catch (e) {}

                        // Remove it
                        pokemon.remove();

                        // clear multi-out tracking for this slot
                        try { player.setDynamicProperty(`pr:out_slot_${slot}`, false); } catch (e) {}
                        try { player.setDynamicProperty(`pr:out_id_${slot}`, undefined); } catch (e) {}

                        returned++;
                    } catch (err) {}
                }

                // Clear the "sent out" tracking (keeps other systems from thinking one is still out)
                try { player.setDynamicProperty("pr:sended_pokemon", false); } catch (e) {}
                try { player.setDynamicProperty("pr:sended_pokemon_slot", undefined); } catch (e) {}
                try { player.setDynamicProperty("pr:sended_pokemon_id", undefined); } catch (e) {}

                if (returned > 0) {
                    player.sendMessage(`§aReturned ${returned} Pokémon!`);
                } else {
                    player.sendMessage("§cNo owned Pokémon found nearby to return.");
                }
            } catch (e) {
                player.sendMessage("§cReturn failed (script error). Check Content Log.");
                console.warn(e);
            }
        });
}
    {
        form.button("Change Party");
        functions.push((res) => {
            optionsMenu(player)
        });
    }
    {
        form.button("Set Nickname");
        functions.push((res) => {
            slotPokeSelect2(player)
        });
    }
    {
        form.button("Edit Moves");
        functions.push((res) => {
            slotPokeSelect(player)
        });
    }
    {
        form.button("Summary");
        functions.push((res) => {
            slotPokeSelect3(player)
        });
    }
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            return;
        }
        functions[res.selection]();
    });
}
export function slotPokeSelect(player) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Options");
    form.body(`000000000000`)
    const inv = player.getComponent("minecraft:inventory").container
    for (let i = 1; i < 7; i++) {
        form.button(`Slot ` + i);
        functions.push((res) => {
            if (player.getDynamicProperty("pr:sended_pokemon") != true) {
                if (player.getDynamicProperty(`pr:slot_${i}_name`) != undefined) {
                    slotMoves(player, player.getDynamicProperty(`pr:slot_${i}_name`), i)
                } else {
                    player.onScreenDisplay.setActionBar("No have a pokemon in this slot!")
                }
            } else {
                player.onScreenDisplay.setActionBar("You can't change now!")
            }
        });
    }
    {
        form.button("Back");
        functions.push((res) => {
            arceusMenu(player)
        });
    }
    {
        form.button("Close");
        functions.push((res) => {
        });
    }
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            return;
        }
        functions[res.selection]();
    });
}

export function slotPokeSelect2(player) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Options");
    form.body(`000000000000`)
    const inv = player.getComponent("minecraft:inventory").container
    for (let i = 1; i < 7; i++) {
        form.button(`Slot ` + i);
        functions.push((res) => {
            if (player.getDynamicProperty("pr:sended_pokemon") != true) {
                renamePokemon(player, i)
            }
        });
    }
    {
        form.button("Back");
        functions.push((res) => {
            arceusMenu(player)
        });
    }
    {
        form.button("Close");
        functions.push((res) => {
        });
    }
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            return;
        }
        functions[res.selection]();
    });
}

export function slotPokeSelect3(player) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Options");
    form.body(`000000000000`)
    const inv = player.getComponent("minecraft:inventory").container
    for (let i = 1; i < 7; i++) {
        form.button(`Slot ` + i);
        functions.push((res) => {
            if (player.getDynamicProperty("pr:sended_pokemon") != true) {
                infoPokemon(player, i)
            }
        });
    }
    {
        form.button("Back");
        functions.push((res) => {
            arceusMenu(player)
        });
    }
    {
        form.button("Close");
        functions.push((res) => {
        });
    }
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            return;
        }
        functions[res.selection]();
    });
}

export function renamePokemon(player, pokemonSlot) {
    let form = new ModalFormData();
    let functions = [];
    form.title("Raname your pokemon:");
    form.textField('Pokemon name:', 'Type here');
    form.show(player).then(formData => {
        if (formData.formValues[0] && formData.formValues[0] != " ") {
            console.warn(formData.formValues[0])
            player.setDynamicProperty(`pr:slot_${pokemonSlot}_nickname`, formData.formValues[0])
        }
    })
}

export function infoPokemon(player, slot) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Summary");
    const icon = player.getDynamicProperty(`pr:slot_${slot}_name`)
    const pokeName = "pr:" + player.getDynamicProperty(`pr:slot_${slot}_name`)
    const pokemonData = getPokemonDataSafe(pokeName)

    if (!pokemonData) {
        form.body("§cMissing battle data for: " + pokeName);
        form.show(player);
        return;
    }
    const typingText = formatTyping(pokemonData.types);
    const offensive = buildOffensiveSummary(pokemonData.types);

    form.body(
        "000000000000" +
        "§7Pokemon:§r " + player.getDynamicProperty(`pr:slot_${slot}_name`) + "\n" +
        "§7Name:§r " + player.getDynamicProperty(`pr:slot_${slot}_nickname`) + "\n" +
        "§7Typing:§r " + typingText + "\n" +
        "§7Strong Against:§r " + offensive.strongAgainst + "\n" +
        "§7Weak Against:§r " + offensive.weakTo + "\n" +
        "§7Immune:§r " + offensive.immuneTo + "\n" +
        "§7Level:§r " + player.getDynamicProperty(`pr:slot_${slot}_level`) + "\n" +
        "§7Health:§r " + player.getDynamicProperty(`pr:slot_${slot}_health`) + "%%\n" +
        "§7Attack:§r " + pokemonData.attack + "\n" +
        "§7Defense:§r " + pokemonData.defense + "\n" +
        "§7SpAttack:§r " + pokemonData.spAttack + "\n" +
        "§7SpDefense:§r " + pokemonData.spDefense + "\n" +
        "§7Speed:§r " + pokemonData.speed + "\n"
    )
    const inv = player.getComponent("minecraft:inventory").container
    {
        form.button("Close", "textures/icons/pokemons/" + icon);
        functions.push((res) => {
        });
    }
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            return;
        }
        functions[res.selection]();
    });
}

export function slotMoves(player, pokemon, slot) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Options");
    form.body(`000000000000`)
    const inv = player.getComponent("minecraft:inventory").container
    for (let i = 1; i < 5; i++) {
        form.button(`Move ` + i);
        functions.push((res) => {
            if (player.getDynamicProperty("pr:sended_pokemon") != true) {
                movesMenu(player, pokemon, i, slot)
            } else {
                player.onScreenDisplay.setActionBar("You can't change now!")
            }
        });
    }
    {
        form.button("Back");
        functions.push((res) => {
            slotPokeSelect(player)
        });
    }
    {
        form.button("Close");
        functions.push((res) => {
        });
    }
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            return;
        }
        functions[res.selection]();
    });
}

async function movesMenu(player, pokemon, moveSlot, slot) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Moves");

    // Slot is 1..6 in your UI
    const slotNum = Math.max(1, Math.min(6, Number(slot) || 1));

    // Pull Learn Points from scoreboard (no dynamic property registration needed)
    let learnPoints = 0;
    try { learnPoints = await getLearnPoints(player, slotNum); } catch (e) { learnPoints = 0; }

    form.body(`Learn Points: ${learnPoints}`);

    const pokemonName = formatEntityFull(pokemon);
    const moveList = pokemonCanLearn.get(pokemonName) ?? [];

    const pokemonData = pokemonsData.find(poke => poke.id === "pr:" + pokemon);
    if (!pokemonData) return;

    // Current known moves (green)
    const knownMoves = [
        player.getDynamicProperty(`pr:slot_${slotNum}_move1`),
        player.getDynamicProperty(`pr:slot_${slotNum}_move2`),
        player.getDynamicProperty(`pr:slot_${slotNum}_move3`),
        player.getDynamicProperty(`pr:slot_${slotNum}_move4`)
    ].filter(m => m);

    for (const moveId of moveList) {
        const move = MovesData.find((m) => m.id === moveId);
        if (!move) continue;

        const isKnown = knownMoves.includes(moveId);

        // We can't rely on color codes in some custom UIs, so use clear text markers.
        // Known: plain. Learnable: star + (1 LP). Locked: (Locked)
        const label = isKnown
            ? `${move.name}`
            : (learnPoints > 0 ? `★ ${move.name} (1 LP)` : `${move.name} (Locked)`);

        form.button(label);

        functions.push(async () => {
            // Known: equip only
            if (isKnown) {
                teachMoveToSlot(player, slotNum, moveSlot, move.id);
                return;
            }

            // Locked
            if (learnPoints <= 0) {
                try { player.sendMessage("§cYou don't have any Learn Points.§r"); } catch (e) { }
                return;
            }

            // Spend 1 point, then teach + equip
            const ok = await spendLearnPoint(player, slotNum);
            if (!ok) {
                try { player.sendMessage("§cYou don't have any Learn Points.§r"); } catch (e) { }
                return;
            }

            // Recompute local points
            learnPoints = Math.max(0, learnPoints - 1);

            teachMoveToSlot(player, slotNum, moveSlot, move.id);
            try { player.sendMessage(`§a${pokemon} learned ${move.name}!§r`); } catch (e) { }

            // Re-open menu so it reflects new points and known moves
            try { movesMenu(player, pokemon, moveSlot, slotNum); } catch (e) { }
        });
    }

    form.button("Back");
    functions.push(() => { slotMoves(player, pokemon, slotNum); });

    form.button("Close");
    functions.push(() => { });

    const res = await form.show(player);
    if (res.canceled) return;

    const fn = functions[res.selection];
    if (fn) await fn();
}

function teachMoveToSlot(player, slot, moveSlot, moveId) {
    // save to legacy dynprop (kept for compatibility)
    try { player.setDynamicProperty(`pr:slot_${slot}_move_${moveSlot}`, moveId); } catch (e) { }

    // save to new slot system (used by battle/HUD)
    try {
        const slotIndex = slot - 1; // convert 1-6 => 0-5
        const slotData = pokemonUtils.getPokemonFromSlot(player, slotIndex);
        if (slotData) {
            slotData[`move${moveSlot}`] = moveId;
            pokemonUtils.updatePokemonSlot(player, slotIndex, slotData);
        }
    } catch (e) { }
}



const randomItemsPokeball = [
    "pr:antidote",
    "pr:awakening",
    "pr:berry_juice",
    "pr:burn_heal",
    "pr:elixir",
    "pr:energy_powder",
    "pr:energy_root",
    "pr:ether",
    "pr:fresh_water",
    "pr:full_heal",
    "pr:full_restore",
    "pr:heal_powder",
    "pr:hyper_potion",
    "pr:ice_heal",
    "pr:lemonade",
    "pr:max_elixir",
    "pr:max_ether",
    "pr:max_potion",
    "pr:max_revive",
    "pr:moomoo_milk",
    "pr:paralyze_heal",
    "pr:potion",
    "pr:revival_herb",
    "pr:revive",
    "pr:soda_pop",
    "pr:super_potion",
    "pr:ball_of_mud",
    "pr:scattering_bang",
    "pr:spoiled_apricon",
    "pr:sticky_glob",
    "pr:pokeball",
    "pr:great_ball",
    "pr:beast_ball",
    "pr:ultra_ball",
    "pr:master_ball",
    "pr:safari_ball",
    "pr:level_ball",
    "pr:lure_ball",
    "pr:moon_ball",
    "pr:friend_ball",
    "pr:love_ball",
    "pr:heavy_ball",
    "pr:net_ball",
    "pr:timer_ball",
    "pr:repeat_ball",
    "pr:premier_ball",
    "pr:nest_ball",
    "pr:dive_ball",
    "pr:luxury_ball",
    "pr:heal_ball",
    "pr:quick_ball",
    "pr:dusk_ball",
    "pr:cherish_ball",
    "pr:dream_ball"
]

const randomItemsChest = [
    "pr:chicken_key",
    "pr:pokeball_key",
    "pr:pumpkin_key",
    "pr:snow_key",
    "pr:ultra_key",
    "pr:upgrade_key"
]

const randomItemsPokecoins = [
    "pr:poke_coin"
]

export function dailyMenu(player) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Daily");
    const timerInGame = player.getDynamicProperty("pr:timerInGame")
    const min_20 = 1200
    form.body(`000000000000`)
    {
        form.button("Day 1");
        functions.push((res) => { // 0 mim
            if (!player.hasTag("pr:day_1")) {
                const itemsLenght = randomItemsPokeball.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.95 ? 1 : 1;
                const item = new ItemStack(randomItemsPokeball[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_1")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 2");
        functions.push((res) => { // 20 mim
            if (timerInGame >= min_20 && !player.hasTag("pr:day_2")) {
                const itemsLenght = randomItemsPokeball.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.95 ? 1 : 1;
                const item = new ItemStack(randomItemsPokeball[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_2")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 3");
        functions.push((res) => { // 40 mim
            if (timerInGame >= (min_20 * 2) && !player.hasTag("pr:day_3")) {
                const itemsLenght = randomItemsPokecoins.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.floor(Math.random() * 25) + 10
                const item = new ItemStack(randomItemsPokecoins[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_3")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 5");
        functions.push((res) => { // 60 mim
            if (timerInGame >= (min_20 * 3) && !player.hasTag("pr:day_5")) {
                const itemsLenght = randomItemsChest.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.5 ? 2 : 3;
                const item = new ItemStack(randomItemsChest[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_5")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 6");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 4) && !player.hasTag("pr:day_6")) {
                const itemsLenght = randomItemsPokecoins.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.floor(Math.random() * 25) + 10
                const item = new ItemStack(randomItemsPokecoins[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_6")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 8");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 5) && !player.hasTag("pr:day_8")) {
                const itemsLenght = randomItemsPokecoins.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.floor(Math.random() * 25) + 10
                const item = new ItemStack(randomItemsPokecoins[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_8")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 11");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 6) && !player.hasTag("pr:day_11")) {
                const itemsLenght = randomItemsPokeball.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.95 ? 1 : 1;
                const item = new ItemStack(randomItemsPokeball[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_11")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 10");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 7) && !player.hasTag("pr:day_10")) {
                const itemsLenght = randomItemsChest.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.5 ? 2 : 3;
                const item = new ItemStack(randomItemsChest[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_10")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 13");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 8) && !player.hasTag("pr:day_13")) {
                const itemsLenght = randomItemsPokeball.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.95 ? 1 : 1;
                const item = new ItemStack(randomItemsPokeball[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_13")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 15");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 9) && !player.hasTag("pr:day_15")) {
                const itemsLenght = randomItemsPokecoins.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.floor(Math.random() * 25) + 10
                const item = new ItemStack(randomItemsPokecoins[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_15")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 17");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 10) && !player.hasTag("pr:day_17")) {
                const itemsLenght = randomItemsPokecoins.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.floor(Math.random() * 25) + 10
                const item = new ItemStack(randomItemsPokecoins[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_17")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 16");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 11) && !player.hasTag("pr:day_16")) {
                const itemsLenght = randomItemsChest.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.5 ? 2 : 3;
                const item = new ItemStack(randomItemsChest[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_16")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 14");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 12) && !player.hasTag("pr:day_14")) {
                const itemsLenght = randomItemsPokeball.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.95 ? 1 : 1;
                const item = new ItemStack(randomItemsPokeball[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_14")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 21");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 13) && !player.hasTag("pr:day_21")) {
                const itemsLenght = randomItemsPokeball.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.95 ? 1 : 1;
                const item = new ItemStack(randomItemsPokeball[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_21")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 21");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 14) && !player.hasTag("pr:day_21")) {
                const itemsLenght = randomItemsPokeball.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.95 ? 1 : 1;
                const item = new ItemStack(randomItemsPokeball[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_21")
            } else {
                return;
            }
        });
    }
    {
        form.button("Day 24");
        functions.push((res) => {
            if (timerInGame >= (min_20 * 15) && !player.hasTag("pr:day_24")) {
                const itemsLenght = randomItemsPokeball.length
                const randomNumber = Math.floor(Math.random() * itemsLenght)
                const randomQuantity = Math.random() < 0.95 ? 1 : 1;
                const item = new ItemStack(randomItemsPokeball[randomNumber], randomQuantity);
                const spawnedItem = player.dimension.spawnItem(item, player.location)
                spawnedItem.applyImpulse({ x: 0, y: 0.5, z: 0 });
                player.playSound("random.levelup")
                player.addTag("pr:day_24")
            } else {
                return;
            }
        });
    }
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            return;
        }
        functions[res.selection]();
    });
}

export const starterPokes = new Map([
    [
        0,
        {
            icons: [
                {
                    id: "pr:squirtle",
                    icon: "squirtle",
                },
                {
                    id: "pr:charmander",
                    icon: "charmander",
                },
                {
                    id: "pr:bulbassaur",
                    icon: "bulbassaur",
                }
            ]
        }
    ],
    [
        1,
        {
            icons: [
                {
                    id: "pr:chikorita",
                    icon: "chikorita",
                },
                {
                    id: "pr:cyndaquil",
                    icon: "cyndaquil",
                },
                {
                    id: "pr:totodile",
                    icon: "totodile",
                }
            ]
        }
    ],
    [
        2,
        {
            icons: [
                {
                    id: "pr:treecko",
                    icon: "treecko",
                },
                {
                    id: "pr:torchic",
                    icon: "torchic",
                },
                {
                    id: "pr:mudkip",
                    icon: "mudkip",
                }
            ]
        }
    ],
    [
        3,
        {
            icons: [
                {
                    id: "pr:turtwig",
                    icon: "turtwig",
                },
                {
                    id: "pr:chimchar",
                    icon: "chimchar",
                },
                {
                    id: "pr:piplup",
                    icon: "piplup",
                }
            ]
        }
    ],
    [
        4,
        {
            icons: [
                {
                    id: "pr:snivy",
                    icon: "snivy",
                },
                {
                    id: "pr:tepig",
                    icon: "tepig",
                },
                {
                    id: "pr:oshawott",
                    icon: "oshawott",
                }
            ]
        }
    ],
    [
        5,
        {
            icons: [
                {
                    id: "pr:chespin",
                    icon: "chespin",
                },
                {
                    id: "pr:fennekin",
                    icon: "fennekin",
                },
                {
                    id: "pr:froakie",
                    icon: "froakie",
                }
            ]
        }
    ]
])
/*
export function starterMenu(player, index) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Starters");
    form.body(`000000000000`)
    let randomNumber = Math.floor(Math.random() * 5)
    if (randomNumber == index) {
        if (randomNumber < 5) {
            randomNumber++
            {
                form.button("Reroll");
                functions.push((res) => {
                    starterMenu(player, randomNumber)
                });
            }
        }
    } else {
        {
            form.button("Reroll");
            functions.push((res) => {
                starterMenu(player, randomNumber)
            });
        }
    }
    starterPokes.get(index)?.icons.forEach((p) => {
        const { id, icon } = p;
        {
            form.button("Select", "textures/icons/pokemons/" + icon);
            functions.push((res) => {
                const pokemonData = getPokemonDataSafe(id)
                if (pokemonData) {
                    const item = new ItemStack(id + "_spawn_egg", 1);
                    item.setLore([
                        `${formatAttackName(id)} Tamed`,
                        `Owner:§7 ${player.nameTag}`,
                        `Level:§7 ${pokemonData.minSpawnLevel}`,
                        `Health:§7 ${pokemonData.maxHealth}`
                    ]);
                    player.dimension.spawnItem(item, player.location);
                  //  dailyMenu(player)
                }
            });
        }
    })
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            return;
        }
        functions[res.selection]();
    });
}
*/

export function applyDamage(player, poke, enemy, level, enemyLevel) {
    const typeAdvantages = {
        fire: { strong: ['grass', 'bug', 'ice', 'steel'], weak: ['fire', 'water', 'rock', 'dragon'] },
        water: { strong: ['fire', 'rock', 'ground'], weak: ['water', 'grass', 'dragon'] },
        grass: { strong: ['water', 'rock', 'ground'], weak: ['fire', 'grass', 'poison', 'flying', 'bug', 'dragon', 'steel'] },
        electric: { strong: ['water', 'flying'], weak: ['electric', 'grass', 'dragon', 'ground'] },
        ground: { strong: ['fire', 'electric', 'poison', 'rock', 'steel'], weak: ['grass', 'bug'] },
        flying: { strong: ['grass', 'fighting', 'bug'], weak: ['electric', 'rock', 'steel'] },
        fighting: { strong: ['normal', 'rock', 'steel', 'ice', 'dark'], weak: ['poison', 'flying', 'psychic', 'bug', 'fairy'] },
        poison: { strong: ['grass', 'fairy'], weak: ['poison', 'ground', 'rock', 'ghost'] },
        rock: { strong: ['fire', 'ice', 'flying', 'bug'], weak: ['fighting', 'ground', 'steel'] },
        psychic: { strong: ['fighting', 'poison'], weak: ['psychic', 'steel', 'dark'] },
        ice: { strong: ['grass', 'ground', 'flying', 'dragon'], weak: ['fire', 'water', 'ice', 'steel'] },
        bug: { strong: ['grass', 'psychic', 'dark'], weak: ['fire', 'fighting', 'flying', 'ghost', 'steel', 'fairy'] },
        ghost: { strong: ['ghost', 'psychic'], weak: ['dark'] },
        steel: { strong: ['ice', 'rock', 'fairy'], weak: ['fire', 'water', 'electric', 'steel'] },
        dragon: { strong: ['dragon'], weak: ['steel', 'fairy'] },
        dark: { strong: ['psychic', 'ghost'], weak: ['fighting', 'dark', 'fairy'] },
        fairy: { strong: ['fighting', 'dragon', 'dark'], weak: ['fire', 'poison', 'steel'] },
        normal: { strong: [], weak: ['rock', 'steel', 'ghost'] },
    };
    function getPokemonType(typeId) {
        const data = pokemonsData.find(p => p.id === typeId);
        return data?.types?.[0] || "normal";
    }

    function getMultiplier(attackerType, defenderType) {
        const advantages = typeAdvantages[attackerType];
        if (!advantages) return 1;

        if (advantages.strong.includes(defenderType)) return 2;
        if (advantages.weak.includes(defenderType)) return 0.5;

        return 1;
    }

    function calculateDamage(attackerId, defenderId, attackerLevel, defenderLevel) {
        const attackerType = getPokemonType(attackerId);
        const defenderType = getPokemonType(defenderId);

        const baseDamage = 10;

        const typeMultiplier = getMultiplier(attackerType, defenderType);

        const levelDifference = attackerLevel - defenderLevel;
        let levelMultiplier = 1 + (levelDifference * 0.1);
        levelMultiplier = Math.max(0.5, Math.min(1.5, levelMultiplier));

        return baseDamage * levelMultiplier * typeMultiplier;
    }

    const damageToEnemy = calculateDamage(poke.typeId, enemy.typeId, level, enemyLevel);
    const damageToPoke = calculateDamage(enemy.typeId, poke.typeId, enemyLevel, level);

    const enemyHealthComp = enemy.getComponent("minecraft:health");
    const pokeHealthComp = poke.getComponent("minecraft:health");
    if (!enemyHealthComp || !pokeHealthComp) return;

    const enemyCurrent = enemyHealthComp.currentValue;
    const pokeCurrent = pokeHealthComp.currentValue;

    // === Aplicar dano no enemy ===
    if (enemyCurrent > 1) {
        const newEnemyHealth = Math.round(Math.max(1, enemyCurrent - damageToEnemy));
        enemyHealthComp.setCurrentValue(newEnemyHealth);

        if (newEnemyHealth == 1) {
            const playerName = enemy.getDynamicProperty("pr:owner_name");
            const players = enemy.dimension.getPlayers({
                location: enemy.location,
                maxDistance: 32
            });

            if (enemy.getDynamicProperty("pr:tamed") === true) {
                for (let p of players) {
                    if (p.id === playerName) {
                       /* const item = new ItemStack(enemy.typeId + "_fainted", 1);
                        item.setLore([
                            `${formatEntityName(enemy)} Tamed`,
                            `Owner:§7 ${p.nameTag}`,
                            `Level:§7 ${enemy.getDynamicProperty("pr:level")}`,
                            `§cDeath`
                        ]);
                        p.dimension.spawnItem(item, enemy.location);*/
                        p.onScreenDisplay.setActionBar("Battle is finished!");
                        p.camera.clear();
                        poke.setDynamicProperty("pr:on_battle", false)
                        enemy.remove();
                        return;
                    }
                }
            } else {
                let level = Number(poke.getDynamicProperty("pr:level"))
                const newLevel = (level + 1);
                poke.setDynamicProperty("pr:level", newLevel)

                // sync level back to slot save data so HUD + moves unlock persist
                try {
                    let slotIndex = poke.getDynamicProperty("pr:slot_index");
                    if (slotIndex === undefined || slotIndex === null || isNaN(Number(slotIndex))) {
                        slotIndex = (player.getDynamicProperty("pr:sended_pokemon_slot") ?? player.getDynamicProperty("pr:selectedSlot") ?? 1) - 1;
                    } else {
                        slotIndex = Number(slotIndex);
                    }
                    if (slotIndex >= 0) {
                        const slotData = pokemonUtils.getPokemonFromSlot(player, slotIndex);
                        if (slotData) {
                            slotData.level = newLevel;
                            pokemonUtils.updatePokemonSlot(player, slotIndex, slotData);
                        }
                        // legacy mirror (if used elsewhere)
                        player.setDynamicProperty(`pr:slot_${slotIndex + 1}_level`, newLevel);
                    }
                } catch (e) { console.warn(e); }


                // Auto evolution 16 / 32
                let evoTarget = null;
                if (newLevel >= 32) {
                    evoTarget = pokemonUtils.findEvolutionTarget(poke.typeId, 2) || pokemonUtils.findEvolutionTarget(poke.typeId, 1);
                } else if (newLevel >= 16) {
                    evoTarget = pokemonUtils.findEvolutionTarget(poke.typeId, 1);
                }
                if (evoTarget) {
                    evoSwapPokemon(player, poke, evoTarget, newLevel);
                    player.onScreenDisplay.setActionBar("Evolution!");
                    player.camera.clear();
                    player.playSound("firework.twinkle");
                    player.playSound("random.orb");
                    enemy.remove();
                    return;
                }
                
                if (poke.getDynamicProperty("pr:nickname") == undefined) {
                    poke.nameTag = formatEntityName(poke) + " | Lvl: §a" + poke.getDynamicProperty("pr:level") + "§r\n" + "Owner:§a " + poke.getDynamicProperty("pr:owner_name")
                } else {
                    poke.nameTag = poke.getDynamicProperty("pr:nickname") + " | Lvl: §a" + poke.getDynamicProperty("pr:level") + "§r\n" + "Owner:§a " + poke.getDynamicProperty("pr:owner_name")
                    
                }
                player.onScreenDisplay.setActionBar("Battle is finished!");
                player.camera.clear();
                player.playSound("firework.twinkle")
                player.playSound("random.orb")
                poke.setDynamicProperty("pr:on_battle", false)
                enemy.remove();
                return;
            }
        } else {
            enemy.playAnimation("attack")
            enemy.runCommand("damage @s 0"); // Atualiza o HP no client
        }
    }

    // === Aplicar dano no poke ===
    if (pokeCurrent > 1) {
        const newPokeHealth = Math.round(Math.max(1, pokeCurrent - damageToPoke));
        pokeHealthComp.setCurrentValue(newPokeHealth);

        if (newPokeHealth == 1) {
            const playerName = poke.getDynamicProperty("pr:owner");
            const players = poke.dimension.getPlayers({
                location: poke.location,
                maxDistance: 32
            });

            if (poke.getDynamicProperty("pr:tamed") === true) {
                for (let p of players) {
                    if (p.id === playerName) {
                       /* const item = new ItemStack(poke.typeId + "_spawn_egg", 1); // _fainted
                        item.setLore([
                            `${formatEntityName(poke)} Tamed`,
                            `Owner:§7 ${p.nameTag}`,
                            `Level:§7 ${poke.getDynamicProperty("pr:level")}`,
                            `§cDeath`
                        ]);
                        p.dimension.spawnItem(item, poke.location);*/
                        p.onScreenDisplay.setActionBar("Battle is finished!");
                        p.camera.clear();
                        if (poke.getDynamicProperty("pr:sended_pokemon") == true) {
                            const slot = player.getDynamicProperty("pr:sended_pokemon_slot")
                            player.setDynamicProperty(`pr:slot_${slot}_level`, 0)
                            player.setDynamicProperty(`pr:slot_${slot}_health`, 0)
                            player.setDynamicProperty(`pr:slot_${slot}_health_true`, 0)
                            player.setDynamicProperty(`pr:slot_${slot}_name`, undefined)
                            player.setDynamicProperty("pr:sended_pokemon", false)
                            player.setDynamicProperty("pr:sended_pokemon_slot", undefined)
                            player.setDynamicProperty("pr:sended_pokemon_id", undefined)
                        }
                        enemy.setDynamicProperty("pr:on_battle", false)
                        poke.kill();
                        return;
                    }
                }
            } else {
                player.onScreenDisplay.setActionBar("Battle is finished!");
                player.camera.clear();
                player.playSound("firework.twinkle")
                player.playSound("random.orb")
                enemy.setDynamicProperty("pr:on_battle", false)
                poke.kill();
                return;
            }
        } else {
            poke.playAnimation("attack")
            poke.runCommand("damage @s 0"); // Atualiza o HP visualmente
        }
    }

    // === Só abrir menu se os dois ainda estiverem vivos ===
    const stillAlive = (
        enemyHealthComp.currentValue > 1 &&
        pokeHealthComp.currentValue > 1
    );

    if (stillAlive) {
        battleMenu(player, poke, enemy, 0);
    }
}



// --- PvP turn-based helpers (tag based; avoids new dynamic properties) ---
function __getPvpBattleId(ent) {
    try {
        for (const t of ent.getTags()) {
            if (t.startsWith("pr:pvp_battle:")) return t.substring("pr:pvp_battle:".length);
        }
    } catch {}
    return "";
}
function __hasBattleTag(ent, battleId) {
    if (!battleId) return false;
    try { return ent.getTags().includes(`pr:pvp_battle:${battleId}`); } catch { return false; }
}
function __isPvpBattle(p1, p2) {
    const bid = __getPvpBattleId(p1);
    return !!bid && __hasBattleTag(p2, bid);
}
function __turnTag(bid) { return `pr:pvp_turn:${bid}`; }
function __battleTag(bid) { return `pr:pvp_battle:${bid}`; }
function __clearPvpTags(ent, bid) {
    try {
        const bt = __battleTag(bid);
        const tt = __turnTag(bid);
        for (const t of ent.getTags()) {
            if (t === bt || t === tt) ent.removeTag(t);
        }
    } catch {}
}
function __findOwnerPlayer(pokemon) {
    const ownerId = pokemon?.getDynamicProperty?.("pr:owner") ?? "";
    const ownerName = pokemon?.getDynamicProperty?.("pr:owner_name") ?? "";
    return world.getAllPlayers().find(p => ownerId && p.id === ownerId) || world.getAllPlayers().find(p => ownerName && (p.nameTag === ownerName || p.name === ownerName));
}
function __endPvpBattle(bid, p1, p2) {
    const pl1 = __findOwnerPlayer(p1);
    const pl2 = __findOwnerPlayer(p2);
    p1?.setDynamicProperty?.("pr:on_battle", false);
    p2?.setDynamicProperty?.("pr:on_battle", false);
    __clearPvpTags(p1, bid);
    __clearPvpTags(p2, bid);
    if (pl1) { __clearPvpTags(pl1, bid); try { pl1.camera.clear(); } catch {} }
    if (pl2) { __clearPvpTags(pl2, bid); try { pl2.camera.clear(); } catch {} }
}
function __pvpAfterMove(currentPlayer, myPoke, oppPoke) {
    const bid = __getPvpBattleId(myPoke);
    if (!bid || !__hasBattleTag(oppPoke, bid)) return;

    const myHp = myPoke?.getComponent?.("minecraft:health")?.currentValue ?? 0;
    const oppHp = oppPoke?.getComponent?.("minecraft:health")?.currentValue ?? 0;

    if (myHp <= 1 || oppHp <= 1) {
        __endPvpBattle(bid, myPoke, oppPoke);
        return;
    }

    const otherPlayer = __findOwnerPlayer(oppPoke);
    if (!otherPlayer) {
        __endPvpBattle(bid, myPoke, oppPoke);
        if (currentPlayer) currentPlayer.sendMessage("§cOpponent left. Battle ended.");
        return;
    }

    // swap turn tags
    system.run(() => {
                    try { currentPlayer.removeTag(__turnTag(bid)); } catch {}
                    try { otherPlayer.addTag(__turnTag(bid)); } catch {}
                });

    if (currentPlayer) currentPlayer.sendMessage("§7Waiting for opponent...");
    otherPlayer.sendMessage("§eYour turn!");

    // Open menu for other player next tick (avoid restricted context)
    system.run(() => {
        try { battleMenu(otherPlayer, oppPoke, myPoke, 0); } catch {}
    });
}


export function battleMenu(player, p1, p2, index) {
    let form = new ActionFormData();
    const pokemonData1 = getPokemonDataSafe(p1?.typeId)
    const pokemonData2 = getPokemonDataSafe(p2?.typeId)

    if (!pokemonData1 || !pokemonData2) {
        const p1id = normalizePokemonId(p1?.typeId);
        const p2id = normalizePokemonId(p2?.typeId);
        player.sendMessage(`§cBattle error: missing data for ${p1id ?? "?"} or ${p2id ?? "?"} in pokemonsData`);
        return;
    }
    let P1currentHealth = Math.round(
        p1.getComponent("minecraft:health").currentValue
    );
    let P1maxHealth = Math.round(
        pokemonData1.maxHealth
    );
    let P2currentHealth = Math.round(
        p2.getComponent("minecraft:health").currentValue
    );
    let P2maxHealth = Math.round(
        pokemonData2.maxHealth
    );
    let functions = [];
    let p1health = Math.round((P1currentHealth / P1maxHealth) * 100);
    let p2health = Math.round((P2currentHealth / P2maxHealth) * 100);
    let poke1 = p1
    let poke2 = p2

    const __pvp = __isPvpBattle(p1, p2);
    const __pvpBattleId = __pvp ? __getPvpBattleId(p1) : "";
    const __myTurn = !__pvp || (player?.hasTag && player.hasTag(__turnTag(__pvpBattleId)));

    // If this is PvP and it's not your turn, never show the move-picker page.
    if (__pvp && !__myTurn && index === 1) {
        index = 0;
    }

    form.title("Battle");
    //const damageToApply = applyDamage(poke1, poke2, 1, 1)
    const pokemonData = pokemonData1
    form.body(`P1:${p1health}`.padEnd(6, " ") + `P2:${p2health}`.padEnd(12, " "))
    {
        form.button(formatEntityName(poke1) + " (My)", "textures/icons/pokemons/" + formatEntityName2(poke1));
        functions.push((res) => {

            player.camera.setCamera("minecraft:free", {
                location: {
                    x: poke1?.location.x - (poke1.getViewDirection().x * 3),
                    y: poke1?.location.y + 1.5,
                    z: poke1?.location.z - (poke1.getViewDirection().z * 3),
                },
                rotation: poke1.getRotation(),
                easeOptions: {
                    easeTime: 0.25,
                    easeType: EasingType.Linear,
                },
                facingEntity: poke1,

            });
            system.runTimeout(() => {
                system.runTimeout(() => {
                    if (index == 0) {
                        battleMenu(player, p1, p2, 0)
                    } else {
                        battleMenu(player, p1, p2, 1)
                    }
                }, 0.25 * 20)
            }, 0.25 * 20)
        });
    }
    {
        form.button(formatEntityName(poke2), "textures/icons/pokemons/" + formatEntityName2(poke2));
        functions.push((res) => {
            player.camera.setCamera("minecraft:free", {
                location: {
                    x: poke2?.location.x - (poke2.getViewDirection().x * 3),
                    y: poke2?.location.y + 1.5,
                    z: poke2?.location.z - (poke2.getViewDirection().z * 3),
                },
                rotation: poke2.getRotation(),
                easeOptions: {
                    easeTime: 0.25,
                    easeType: EasingType.Linear,
                },
                facingEntity: poke2,

            });
            system.runTimeout(() => {
                if (index == 0) {
                    battleMenu(player, p1, p2, 0)
                } else {
                    battleMenu(player, p1, p2, 1)
                }
            }, 0.25 * 20)
        });
    }
    if (index == 0) {
        {
            if (!__pvp || __myTurn) {
                form.button("Battle");
                functions.push((res) => {
                    system.runTimeout(() => {
                        battleMenu(player, p1, p2, 1)
                    }, 0.25 * 20)
                });
            } else {
                form.button("Waiting...");
                functions.push((res) => {
                    // Not your turn; do nothing.
                });
            }
        }
        {
            form.button(__pvp ? "Forfeit" : "Run");
functions.push((res) => {
                if (__pvp) {
                    __endPvpBattle(__pvpBattleId, p1, p2);
                } else {
                    p1.setDynamicProperty("pr:on_battle", false)
                    p2.setDynamicProperty("pr:on_battle", false)
                    player.camera.clear()
                }
            });
        }
        {
            form.button("Pokeball");
            functions.push((res) => {
                //battleMenu(player, 0)
            });
        }
        {
            form.button("Bag");
            functions.push((res) => {
                //battleMenu(player, 0)
            });
        }
    } else {
        const pokemonId = p1.typeId.replace("pr:", "");
        const moveList = pokemonCanLearn.get(pokemonId);

        let moveName1 = "";
        let moveName2 = "";
        let moveName3 = "";
        let moveName4 = "";

        const moveId1 = p1.getDynamicProperty("pr:move1");
        const moveId2 = p1.getDynamicProperty("pr:move2");
        const moveId3 = p1.getDynamicProperty("pr:move3");
        const moveId4 = p1.getDynamicProperty("pr:move4");

        if (moveList && moveList.includes(moveId1)) {
            const move = MovesData.find((m) => m.id === moveId1);
            if (move) {
                moveName1 = move.name;
            }
        }

        if (moveList && moveList.includes(moveId2)) {
            const move = MovesData.find((m) => m.id === moveId2);
            if (move) {
                moveName2 = move.name;
            }
        }

        if (moveList && moveList.includes(moveId3)) {
            const move = MovesData.find((m) => m.id === moveId3);
            if (move) {
                moveName3 = move.name;
            }
        }

        if (moveList && moveList.includes(moveId4)) {
            const move = MovesData.find((m) => m.id === moveId4);
            if (move) {
                moveName4 = move.name;
            }
        }
        {
            form.button(moveName1);
            functions.push((res) => {
                if (P1currentHealth > 1 || P2currentHealth > 1) {
                    applyDamage(player, poke1, poke2, poke1.getDynamicProperty("pr:level"), poke2.getDynamicProperty("pr:level"))
                    if (__pvp) {
                        system.run(() => { __pvpAfterMove(player, poke1, poke2); });
                    }

                }
            });
        }
        {
            form.button(moveName2);
            functions.push((res) => {
                if (P1currentHealth > 1 || P2currentHealth > 1) {
                    applyDamage(player, poke1, poke2, poke1.getDynamicProperty("pr:level"), poke2.getDynamicProperty("pr:level"))
                    if (__pvp) {
                        system.run(() => { __pvpAfterMove(player, poke1, poke2); });
                    }

                }
            });
        }
        {
            form.button(moveName3);
            functions.push((res) => {
                if (P1currentHealth > 1 || P2currentHealth > 1) {
                    applyDamage(player, poke1, poke2, poke1.getDynamicProperty("pr:level"), poke2.getDynamicProperty("pr:level"))
                    if (__pvp) {
                        system.run(() => { __pvpAfterMove(player, poke1, poke2); });
                    }

                }
            });
        }
        {
            form.button(moveName4);
            functions.push((res) => {
                if (P1currentHealth > 1 || P2currentHealth > 1) {
                    applyDamage(player, poke1, poke2, poke1.getDynamicProperty("pr:level"), poke2.getDynamicProperty("pr:level"))
                    if (__pvp) {
                        system.run(() => { __pvpAfterMove(player, poke1, poke2); });
                    }

                }
            });

        {
            form.button("Bag");
            functions.push((res) => {
                // Same behavior as the Bag button on the main battle menu
                // (Bag handling is not implemented in this script yet)
            });
        }
        }
    }
    form.show(player).then((res) => {
        const canceled = res.canceled;
        if (canceled == true) {
            if (__pvp) {
                // PvP: never auto-reopen (prevents client freeze / UI spam)
                player.camera.clear();
                return;
            }
            if (index == 0) {
                p1.setDynamicProperty("pr:on_battle", false)
                p2.setDynamicProperty("pr:on_battle", false)
                player.camera.clear()
            } else {
                battleMenu(player, p1, p2, 1)
            }
            player.camera.clear()
            return;
        }
        functions[res.selection]();
    });
}

export function formatEntityName(entity) {
    if (!entity || !entity.typeId) return "Unknown";

    let id = entity.typeId;

    if (id.includes(":")) {
        id = id.split(":")[1];
    }

    // Troca _ por espaço
    id = id.replace(/_/g, " ");

    // Deixa a primeira letra de cada palavra maiúscula
    id = id.split(" ").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");

    return id;
}

export function formatEntityName2(entity) {
    if (!entity || !entity.typeId) return "Unknown";

    let id = entity.typeId;

    if (id.includes(":")) {
        id = id.split(":")[1];
    }

    // Troca _ por espaço
    id = id.replace(/_/g, " ");

    // Deixa a primeira letra de cada palavra maiúscula
    id = id.split(" ").map(word => word.charAt(0).toLowerCase() + word.slice(1)).join(" ");

    return id;

}

export function formatAttackName(attack) {
    if (!attack) return "Unknown";

    let id = attack;

    if (id.includes(":")) {
        id = id.split(":")[1];
    }

    // Troca _ por espaço
    id = id.replace(/_/g, " ");

    // Deixa a primeira letra de cada palavra maiúscula
    id = id.split(" ").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");

    return id;
}

export function formatEntityFull(entity) {
    if (!entity) return "Unknown";

    let id = entity

    if (id.includes(":")) {
        id = id.split(":")[1];
    }

    id = id.replace(/_/g, " ");


    id = id.split(" ").map(word => word.charAt(0).toLowerCase() + word.slice(1)).join(" ");

    id = id.replace(" ", "")
    id = id.replace("pr:", "")

    return id;

}