import { EntityComponentTypes } from "@minecraft/server";
import { POKEMONS_DATA } from "../data/pokemon.js";
import { MOVEMENTS_DATA } from "../data/movement.js";
import { slotDataManager } from "./slotDataManager.js";
import { StringUtils } from "./stringUtils.js";
import { Debugger } from "../api/debugger.js";
import { ActionFormData } from "@minecraft/server-ui";
import { addLearnPoints, cacheLearnPoints } from "./learnPoints.js";
const debug = Debugger.getInstance();
class PokemonUtils {
    normalizePokemonId(id) {
        if (!id) return null;
        id = String(id).toLowerCase().trim();
        id = id.replace("_spawn_egg", "").replace("_fainted", "");
        id = id.replace(/\s+/g, "_").replace(/-/g, "_").replace(/'/g, "");
        id = id.replace(/__+/g, "_");
        if (!id.includes(":")) id = "pr:" + id;
        // Treat mega forms as their base species for storage/UI systems
        // pr:mega_gyarados -> pr:gyarados ; pr:mega_charizard_x -> pr:charizard
        const megaMatch = /^pr:mega_(.+?)(?:_[xy])?$/i.exec(id);
        if (megaMatch) id = "pr:" + megaMatch[1];
        return id;
    }

    setMovesOnSpawn(pokemon) {
        const pid = this.normalizePokemonId(pokemon?.typeId);
        const pokemonData = POKEMONS_DATA.find(poke => this.normalizePokemonId(poke.id) === pid);
        if (!pokemonData)
            return;
        [1, 2, 3, 4].forEach(moveIndex => {
            const moveProperty = `pr:move${moveIndex}`;
            if (!pokemon.getDynamicProperty(moveProperty))
                pokemon.setDynamicProperty(moveProperty, pokemonData[`move${moveIndex}`]);
        });
    }
    randomValue(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    createSlotsPokemon(player) {
        for (let i = 0; i < 6; i++) {
            slotDataManager.clearPokemonSlot(player, i);
        }
    }
    capturePokemon(player, pokemonId, level) {
        pokemonId = this.normalizePokemonId(pokemonId);
        slotDataManager.initializePlayerPC(player);
        const pokemonSlotData = this.createPokemonSlotData(pokemonId, level, undefined, player.id);
        if (!pokemonSlotData) {
            return false;
        }
        const addedToSlot = slotDataManager.addPokemonToSlot(player, pokemonSlotData);
        if (addedToSlot) {
            player.sendMessage(`Captured Pokémon: ${pokemonSlotData.name} by ${player.nameTag}`);
            return true;
        }
        player.sendMessage(`Added Pokémon: ${pokemonSlotData.name} to PC of ${player.nameTag}`);
        return slotDataManager.addPokemonToPC(player, pokemonSlotData);
    }
    getPokemonFromSlot(player, slotIndex) {
        return slotDataManager.getPokemonSlotData(player, slotIndex);
    }
    updatePokemonSlot(player, slotIndex, data) {
        slotDataManager.setPokemonSlotData(player, slotIndex, data);
    }
    healPokemon(player, slotIndex) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return false;
        const pokemonInfo = POKEMONS_DATA.find(poke => poke.id === pokemonData.typeId);
        if (!pokemonInfo)
            return false;
        pokemonData.health = pokemonInfo.maxHealth;
        this.updatePokemonSlot(player, slotIndex, pokemonData);
        return true;
    }
    gainExperience(player, slotIndex, xpAmount) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return;
        const oldLevel = pokemonData.level;
        pokemonData.xp += xpAmount;
        // Lógica simples de level up (pode ser customizada)
        const xpNeededForNextLevel = pokemonData.level * 100;
        if (pokemonData.xp >= xpNeededForNextLevel) {
            pokemonData.level++;
            pokemonData.xp -= xpNeededForNextLevel;
            // Notificar sobre level up
            player.sendMessage(`§e${pokemonData.name} reached level ${pokemonData.level}!`);

            // +1 Learn Point per level (slotIndex is 0..5; slotNum is 1..6)
            const slotNum = (Number(slotIndex) || 0) + 1;
            try {
                addLearnPoints(player, slotNum, 1).then((total) => {
                    try { cacheLearnPoints(player, slotNum, total); } catch (e) { }
                    try { player.sendMessage(`§a+1 Learn Point§r (Total: §e${total}§r)`); } catch (e) { }
                });
            }
            catch (e) { }
        }
        this.updatePokemonSlot(player, slotIndex, pokemonData);
        // Verificar evolução automática se o nível mudou
        if (pokemonData.level > oldLevel) {
            this.checkAndEvolvePokemon(player, slotIndex);
        }
    }
    returnPokemonsSlots(player) {
        const slots = [];
        for (let i = 0; i <= 5; i++) {
            const pokemon = pokemonUtils.getPokemonFromSlot(player, i);
            if (!pokemon) {
                slots.push({ name: "empty", level: 0, health: 0 });
                continue;
            }
            const pokemonData = POKEMONS_DATA.find(p => p.id === pokemon?.typeId);
            if (!pokemon || !pokemonData) {
                slots.push({ name: "empty", level: 0, health: 0 });
                continue;
            }
            ;
            const name = pokemon.typeId.replace("pr:", "");
            const level = pokemon.level;
            const health = pokemon.health * 100 / pokemonData.maxHealth;
            slots.push({ name, level, health });
        }
        return slots;
    }
    updatePokemonDataHealth(pokemon) {
        try {
            if (!pokemon || pokemon.isValid === false) return;
            const healthComponent = pokemon.getComponent("minecraft:health");
            const tameableComponent = pokemon.getComponent(EntityComponentTypes.Tameable);
        if (!healthComponent || !tameableComponent || !tameableComponent?.tamedToPlayer)
            return;
        const currentHealth = parseInt(healthComponent.currentValue.toFixed(0));
        const owner = tameableComponent.tamedToPlayer;
        const pokemonFromSlot = this.getPokemonFromSlot(owner, owner?.getDynamicProperty("pr:selectedSlot"));
        if (pokemonFromSlot && pokemonFromSlot.typeId === pokemon.typeId) {
            this.updatePokemonSlot(owner, owner.getDynamicProperty("pr:selectedSlot"), {
                attack: pokemonFromSlot.attack,
                defense: pokemonFromSlot.defense,
                health: currentHealth,
                level: pokemonFromSlot.level,
                name: pokemonFromSlot.name,
                typeId: pokemonFromSlot.typeId,
                owner: pokemonFromSlot.owner,
                xp: pokemonFromSlot.xp,
                speed: pokemonFromSlot.speed,
                move1: pokemonFromSlot.move1,
                move2: pokemonFromSlot.move2,
                move3: pokemonFromSlot.move3,
                move4: pokemonFromSlot.move4,
                spAttack: pokemonFromSlot.spAttack,
                spDefense: pokemonFromSlot.spDefense
            });
        }
        }
        catch (e) {
            // Ignore invalid entity timing issues (e.g., entity swapped/despawned)
            return;
        }
    }
    getPokemonMoves(player, slotIndex) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return null;
        return [
            pokemonData.move1,
            pokemonData.move2,
            pokemonData.move3,
            pokemonData.move4
        ].filter(move => move && move !== ''); // Remove movimentos vazios
    }
    getCurrentPokemonMoves(player) {
        const currentSlot = player.getDynamicProperty('pr:selectedSlot') || 0;
        return this.getPokemonMoves(player, currentSlot);
    }
    renamePokemon(player, slotIndex, newName) {
        debug.log(`Tentando renomear Pokemon no slot ${slotIndex} para "${newName}"`, player);
        debug.log(`Player: ${player.nameTag}`, player);
        this.checkAndFixLegacyData(player, slotIndex);
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        debug.log(`Pokemon data retrieved: ${pokemonData ? 'Found' : 'NULL'}`, player);
        if (!pokemonData) {
            debug.log(`Pokemon data is null, checking raw data...`, player);
            const rawData = player.getDynamicProperty(`rp_pr:pokemon_slot_${slotIndex}`);
            debug.log(`Raw data: "${rawData}"`, player);
            if (rawData) {
                debug.log(`Raw data exists but decode failed. Parts: ${rawData.split('|').length}`, player);
                debug.log(`Raw data parts: ${JSON.stringify(rawData.split('|'))}`, player);
            }
            return;
        }
        debug.log(`Pokemon before rename: ${JSON.stringify(pokemonData)}`);
        pokemonData.name = newName;
        debug.log(`Pokemon after rename: ${JSON.stringify(pokemonData)}`);
        this.updatePokemonSlot(player, slotIndex, pokemonData);
        const pokemonEntity = player.dimension.getEntities({ type: pokemonData.typeId, location: player.location })[0];
        if (pokemonEntity) {
            pokemonEntity.nameTag = `${newName}\n§aOwner: ${player.name}\nLvl: §a${pokemonData.level}§r`;
        }
    }
    returnPokemonToSlot(player, pokemonSlotData) {
        const currentSlot = player.getDynamicProperty('pr:selectedSlot') || 0;

        // If the caller passed updated slot data (e.g. battle results), persist it first
        if (pokemonSlotData) {
            this.updatePokemonSlot(player, currentSlot, pokemonSlotData);
        }

        const pokemonData = this.getPokemonFromSlot(player, currentSlot);
        if (!pokemonData) return;

        // IMPORTANT:
        // Don't filter by typeId here. If a Pokémon evolves while it is out,
        // its entity.typeId changes and the old filter would fail, preventing recall.
        const nearbyEntities = player.dimension.getEntities({
            location: player.location,
            maxDistance: 100
        });

        for (const entity of nearbyEntities) {
            const ownerId = entity.getDynamicProperty("pr:owner");
            const isTamed = entity.getDynamicProperty("pr:tamed");

            // Only recall Pokémon that belong to this player
            if (ownerId === player.id && isTamed) {
                const slotIdx = Number(entity.getDynamicProperty("pr:slot_index"));
                if (!Number.isFinite(slotIdx) || slotIdx !== Number(currentSlot)) {
                    continue;
                }
                // If the Pokémon evolved while out, sync the slot's typeId to the current entity
                if (entity.typeId && pokemonData.typeId !== entity.typeId) {
                    pokemonData.typeId = entity.typeId;
                }

                // Sync current HP back into the slot
                const healthComponent = entity.getComponent("minecraft:health");
                if (healthComponent) {
                    pokemonData.health = Math.floor(healthComponent.currentValue);
                }

                this.updatePokemonSlot(player, currentSlot, pokemonData);

                // Despawn the entity
                entity.remove();
                break;
            }
        }

        player.setDynamicProperty('pr:selectedSlot', -1);
    }

    spawnPokemon(player, slotIndex) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return;
        if (pokemonData.health <= 0) {
            player.sendMessage(`§c${pokemonData.name} is disabled and cannot be sent!`);
            return;
        }
        // Verificar e aplicar evolução automática antes de spawnar
        const evolvedData = this.checkAndEvolvePokemon(player, slotIndex);
        const finalPokemonData = evolvedData || pokemonData;
        const pokemonEntity = player.dimension.spawnEntity(finalPokemonData.typeId, player.location);
        // Track which team slot this spawned from (0-based)
        pokemonEntity.setDynamicProperty("pr:slot_index", slotIndex);
        this.setMovesOnSpawn(pokemonEntity);
        // APPLY_SLOT_MOVES_ON_SPAWN: force slot-selected moves onto the spawned entity
        try {
            [1, 2, 3, 4].forEach(i => {
                const k = `pr:move${i}`;
                const v = finalPokemonData[`move${i}`];
                if (v && v !== '') pokemonEntity.setDynamicProperty(k, v);
            });
        } catch (e) {
            console.warn(`spawnPokemon: failed to apply slot moves: ${e}`);
        }
        const tameableComponent = pokemonEntity.getComponent("minecraft:tameable");
        tameableComponent.tame(player);
        // Sincronizar todas as propriedades dinâmicas
        this.syncPokemonEntityProperties(pokemonEntity, finalPokemonData, player);
    }
    // Função para verificar e evoluir um Pokémon automaticamente
    checkAndEvolvePokemon(player, slotIndex) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return null;
        // Verificar se o Pokémon pode evoluir baseado no nível
        const evolutionResult = this.getEvolutionForPokemon(pokemonData);
        if (!evolutionResult)
            return null;
        // Aplicar a evolução
        const evolvedPokemon = this.evolvePokemon(pokemonData, evolutionResult);
        if (!evolvedPokemon)
            return null;
        // Atualizar o slot com os dados do Pokémon evoluído
        this.updatePokemonSlot(player, slotIndex, evolvedPokemon);
        // Notificar o jogador sobre a evolução
        player.sendMessage(`§a🌟 ${pokemonData.name} evolved into ${evolvedPokemon.name}! 🌟`);
        
try {
    player.dimension.spawnParticle("pr:evolution_burst", {
        x: player.location.x,
        y: player.location.y + 1,
        z: player.location.z
    });
} catch (e) {
    console.warn("Evolution particle failed:", e);
}

        return evolvedPokemon;
    }
    // Função para determinar se um Pokémon pode evoluir e qual seria sua evolução
    getEvolutionForPokemon(pokemonData) {
        const currentPokemonInfo = POKEMONS_DATA.find(poke => poke.id === pokemonData.typeId);
        if (!currentPokemonInfo)
            return null;
        if (currentPokemonInfo.transformLevel && pokemonData.level >= currentPokemonInfo.transformLevel) {
            const evolutionTargetId = this.findEvolutionTarget(pokemonData.typeId, 1);
            if (evolutionTargetId) {
                return {
                    targetId: evolutionTargetId,
                    evolutionLevel: currentPokemonInfo.transformLevel
                };
            }
        }
        if (currentPokemonInfo.secondTransformLevel && pokemonData.level >= currentPokemonInfo.secondTransformLevel) {
            const evolutionTargetId = this.findEvolutionTarget(pokemonData.typeId, 2);
            if (evolutionTargetId) {
                return {
                    targetId: evolutionTargetId,
                    evolutionLevel: currentPokemonInfo.secondTransformLevel
                };
            }
        }
        return null;
    }
    // Função para encontrar o ID da evolução de um Pokémon
    findEvolutionTarget(currentPokemonId, evolutionStage) {
        // Lógica baseada nos padrões dos nomes dos Pokémon
        // Esta função mapeia evoluções conhecidas
        // AUTO_EVOLUTION_ALL_POKEMON_SAFE
const evolutionMap = {};
for (const p of POKEMONS_DATA) {
    evolutionMap[p.id] = [];
}

// Manual overrides / known evolution lines
const _manualEvolutionMap = {
// F
            "pr:froslass": [],
            "pr:furret": [],
            "pr:gabite": ["pr:garchomp"],
            "pr:gallade": [],
            "pr:galvantula": [],
            "pr:garchomp": [],
            "pr:gardevoir": [],
            "pr:genesect": [],
            "pr:gible": ["pr:gabite", "pr:garchomp"],
            "pr:girafarig": [],
            "pr:giratina": [],
            "pr:glalie": [],
            "pr:glameow": [],
            "pr:gligar": ["pr:gliscor"],
            "pr:gliscor": [],
            "pr:golduck": [],
            "pr:golett": ["pr:golurk"],
            "pr:golurk": [],
            "pr:goodra": [],
            "pr:goomy": ["pr:sliggoo", "pr:goodra"],
            "pr:gorebyss": [],
            "pr:granbull": [],
            "pr:growlithe": ["pr:arcanine"],
            "pr:grumpig": [],
            "pr:gabite": ["pr:garchomp"],

            // H
            "pr:hariyama": [],
            "pr:haxorus": [],
            "pr:heatmor": [],
            "pr:heatran": [],
            "pr:heracross": [],
            "pr:hippopotas": ["pr:hippowdon"],
            "pr:hitmonlee": [],
            "pr:hitmontop": [],
            "pr:ho_oh": [],
            "pr:hoopa": [],
            "pr:houndour": ["pr:houndoom"],
            "pr:houndoom": [],
            "pr:huntail": [],
            "pr:hydreigon": [],

            // I-J
            "pr:igglybuff": ["pr:jigglypuff", "pr:wigglytuff"],
            "pr:illumise": [],
            "pr:jirachi": [],
            "pr:jolteon": [],
            "pr:jumpluff": [],

            // K
            "pr:kakuna": ["pr:beedrill"],
            "pr:kangaskan": [],
            "pr:kecleon": [],
            "pr:keldeo": [],
            "pr:kingdra": [],
            "pr:kingler": [],
            "pr:kirlia": ["pr:gardevoir", "pr:gallade"],
            "pr:klang": ["pr:klinklang"],
            "pr:klefki": [],
            "pr:krabby": ["pr:kingler"],
            "pr:kricketot": ["pr:kricketune"],
            "pr:kricketune": [],
            "pr:kyogre": [],
            "pr:kyurem": [],

            // L
            "pr:lairon": ["pr:aggron"],
            "pr:lanturn": [],
            "pr:larvesta": ["pr:volcarona"],
            "pr:larvitar": ["pr:pupitar", "pr:tyranitar"],
            "pr:latias": [],
            "pr:latios": [],
            "pr:leafeon": [],
            "pr:ledian": [],
            "pr:ledyba": ["pr:ledian"],
            "pr:lickilicky": [],
            "pr:liepard": [],
            "pr:lileep": ["pr:cradily"],
            "pr:lillipup": ["pr:herdier", "pr:stoutland"],
            "pr:linoone": [],
            "pr:litwick": ["pr:lampent", "pr:chandelure"],
            "pr:lombre": ["pr:ludicolo"],
            "pr:lopunny": [],
            "pr:lotad": ["pr:lombre", "pr:ludicolo"],
            "pr:loudred": ["pr:exploud"],
            "pr:lucario": [],
            "pr:ludicolo": [],
            "pr:lugia": [],
            "pr:lumenon": [],
            "pr:lunatone": [],
            "pr:luvdisc": [],
            "pr:luxio": ["pr:luxray"],
            "pr:luxray": [],

            // M
            "pr:machop": ["pr:machoke", "pr:machamp"],
            "pr:machoke": ["pr:machamp"],
            "pr:machamp": [],
            "pr:magby": ["pr:magmar", "pr:magmortar"],
            "pr:magcargo": [],
            "pr:magmortar": [],
            "pr:magnemite": ["pr:magneton", "pr:magnezone"],
            "pr:magneton": ["pr:magnezone"],
            "pr:magnezone": [],
            "pr:makuhita": ["pr:hariyama"],
            "pr:mamoswine": [],
            "pr:manaphy": [],
            "pr:mandibuzz": [],
            "pr:manectric": [],
            "pr:mankey": ["pr:primeape"],
            "pr:mantine": [],
            "pr:mantyke": ["pr:mantine"],
            "pr:maractus": [],
            "pr:mareep": ["pr:flaaffy", "pr:ampharos"],
            "pr:marill": ["pr:azumarill"],
            "pr:marowak": [],
            "pr:masquerain": [],
            "pr:mawile": [],
            "pr:meditite": ["pr:medicham"],
            "pr:medicham": [],
            "pr:melmetal": [],
            "pr:meloetta": [],
            "pr:meowth": ["pr:persian"],
            "pr:mesprit": [],
            "pr:metang": ["pr:metagross"],
            "pr:metagross": [],
            "pr:metapod": ["pr:butterfree"],
            "pr:mew_two": [],
            "pr:mienfoo": ["pr:mienshao"],
            "pr:mienshao": [],
            "pr:mightyena": [],
            "pr:milotic": [],
            "pr:miltank": [],
            "pr:mime_jr": ["pr:mr_mime"],
            "pr:minccino": ["pr:cinccino"],
            "pr:minun": [],
            "pr:misdreavus": ["pr:mismagius"],
            "pr:mismagius": [],
            "pr:moltresss": [],
            "pr:mothim": [],
            "pr:muk": [],
            "pr:munchlax": ["pr:snorlax"],
            "pr:munna": ["pr:musharna"],
            "pr:murkrow": ["pr:honchkrow"],
            "pr:musharna": [],

            // N
            "pr:natu": ["pr:xatu"],
            "pr:nidoking": [],
            "pr:nidoqueen": [],
            "pr:nidoran_f": ["pr:nidorina", "pr:nidoqueen"],
            "pr:nidoran_m": ["pr:nidorino", "pr:nidoking"],
            "pr:nidorina": ["pr:nidoqueen"],
            "pr:nidorino": ["pr:nidoking"],
            "pr:nincada": ["pr:ninjask", "pr:shedinja"],
            "pr:ninetailes": [],
            "pr:ninjask": [],
            "pr:noctowl": [],
            "pr:nosepass": ["pr:probopass"],
            "pr:numel": ["pr:camerupt"],
            "pr:nuzleaf": ["pr:shiftry"],

            // O-P
            "pr:octillery": [],
            "pr:pachirisu": [],
            "pr:palkia": [],
            "pr:palpitoad": ["pr:seismitoad"],
            "pr:panpour": ["pr:simipour"],
            "pr:pansage": ["pr:simisage"],
            "pr:pansear": ["pr:simisear"],
            "pr:patrat": ["pr:watchog"],
            "pr:pelipper": [],
            "pr:persian": [],
            "pr:phanpy": ["pr:donphan"],
            "pr:phione": [],
            "pr:pichu": ["pr:pikachu", "pr:raichu"],
            "pr:pidove": ["pr:tranquill", "pr:unfezant"],
            "pr:pikachu": ["pr:raichu"],
            "pr:piloswine": ["pr:mamoswine"],
            "pr:pineco": ["pr:forretress"],
            "pr:plusle": [],
            "pr:politoed": [],
            "pr:poliwag": ["pr:poliwhirl", "pr:poliwrath"],
            "pr:poliwhirl": ["pr:poliwrath"],
            "pr:poliwrath": [],
            "pr:ponyta": ["pr:rapidash"],
            "pr:porygon2": ["pr:porygon_z"],
            "pr:porygon_z": [],
            "pr:primeape": [],
            "pr:probopass": [],
            "pr:psyduck": ["pr:golduck"],
            "pr:pupitar": ["pr:tyranitar"],
            "pr:purrloin": ["pr:liepard"],

            // Q-R
            "pr:quagsire": [],
            "pr:qwilfish": [],
            "pr:raichu": [],
            "pr:raikou": [],
            "pr:ralts": ["pr:kirlia", "pr:gardevoir", "pr:gallade"],
            "pr:rampardos": [],
            "pr:rapidash": [],
            "pr:rayquaza": [],
            "pr:regice": [],
            "pr:regigigas": [],
            "pr:regirock": [],
            "pr:registeel": [],
            "pr:relicanth": [],
            "pr:remoraid": ["pr:octillery"],
            "pr:reshiram": [],
            "pr:reuniclus": [],
            "pr:rhyperior": [],
            "pr:riolu": ["pr:lucario"],
            "pr:roselia": ["pr:roserade"],
            "pr:roserade": [],
            "pr:rotom": [],
            "pr:sableye": [],

            // S
            "pr:salamence": [],
            "pr:samoett": [],
            "pr:scizor": [],
            "pr:scolipede": [],
            "pr:scrafty": [],
            "pr:scraggy": ["pr:scrafty"],
            "pr:sealeo": ["pr:walrein"],
            "pr:seedot": ["pr:nuzleaf", "pr:shiftry"],
            "pr:seismitoad": [],
            "pr:sentret": ["pr:furret"],
            "pr:seviper": [],
            "pr:sewaddle": ["pr:swadloon", "pr:leavanny"],
            "pr:sharpedo": [],
            "pr:shaymin": [],
            "pr:shedinja": [],
            "pr:shelgon": ["pr:salamence"],
            "pr:shellos": ["pr:gastrodon"],
            "pr:shieldon": ["pr:bastiodon"],
            "pr:shinx": ["pr:luxio", "pr:luxray"],
            "pr:shroomish": ["pr:breloom"],
            "pr:shuckle": [],
            "pr:shuppet": ["pr:banette"],
            "pr:sigilyph": [],
            "pr:silcoon": ["pr:beautifly"],
            "pr:simipour": [],
            "pr:simisage": [],
            "pr:simisear": [],
            "pr:skarmory": [],
            "pr:skiploom": ["pr:jumpluff"],
            "pr:skitty": ["pr:delcatty"],
            "pr:skorupi": ["pr:drapion"],
            "pr:skuntank": [],
            "pr:slaking": [],
            "pr:slakoth": ["pr:vigoroth", "pr:slaking"],
            "pr:sliggoo": ["pr:goodra"],
            "pr:slowbro": [],
            "pr:slowking": [],
            "pr:slowpoke": ["pr:slowbro", "pr:slowking"],
            "pr:slugma": ["pr:magcargo"],
            "pr:smeargle": [],
            "pr:smoochum": ["pr:jynx"],
            "pr:sneasel": ["pr:weavile"],
            "pr:snorunt": ["pr:glalie", "pr:froslass"],
            "pr:snover": ["pr:abomasnow"],
            "pr:snubbull": ["pr:granbull"],
            "pr:solrock": [],
            "pr:spheal": ["pr:sealeo", "pr:walrein"],
            "pr:spinarak": ["pr:ariados"],
            "pr:spinda": [],
            "pr:spiritomb": [],
            "pr:spoink": ["pr:grumpig"],
            "pr:stantler": [],
            "pr:staraptor": [],
            "pr:staravia": ["pr:staraptor"],
            "pr:starly": ["pr:staravia", "pr:staraptor"],
            "pr:steelix": [],
            "pr:stunfisk": [],
            "pr:sudowoodo": [],
            "pr:suicune": [],
            "pr:sunflora": [],
            "pr:sunkern": ["pr:sunflora"],
            "pr:surskit": ["pr:masquerain"],
            "pr:swablu": ["pr:altaria"],
            "pr:swadloon": ["pr:leavanny"],
            "pr:swalot": [],
            "pr:swampert": [],
            "pr:swanna": [],
            "pr:swellow": [],
            "pr:swinub": ["pr:piloswine", "pr:mamoswine"],
            "pr:swirlix": ["pr:slurpuff"],
            "pr:swoobat": [],
            "pr:sylveon": [],

            // T
            "pr:taillow": ["pr:swellow"],
            "pr:talonflame": [],
            "pr:tangrowth": [],
            "pr:teddiursa": ["pr:ursaring"],
            "pr:tentacool": ["pr:tentacruel"],
            "pr:tentacruel": [],
            "pr:terrakion": [],
            "pr:throh": [],
            "pr:thundurus": [],
            "pr:timburr": ["pr:gurdurr", "pr:conkeldurr"],
            "pr:tirtouga": ["pr:carracosta"],
            "pr:togekiss": [],
            "pr:togepi": ["pr:togetic", "pr:togekiss"],
            "pr:togetic": ["pr:togekiss"],
            "pr:torkoal": [],
            "pr:tornadus": [],
            "pr:toxicroak": [],
            "pr:tranquill": ["pr:unfezant"],
            "pr:trapinch": ["pr:vibrava", "pr:flygon"],
            "pr:tropius": [],
            "pr:trubbish": ["pr:garbodor"],
            "pr:tympole": ["pr:palpitoad", "pr:seismitoad"],
            "pr:typhlosion": [],
            "pr:tyranitar": [],
            "pr:tyrantrum": [],
            "pr:tyrogue": ["pr:hitmonlee", "pr:hitmonchan", "pr:hitmontop"],

            // U-V
            "pr:umbreon": [],
            "pr:unfezant": [],
            "pr:unown": [],
            "pr:ursaring": [],
            "pr:uxie": [],
            "pr:vanillite": ["pr:vanillish", "pr:vanilluxe"],
            "pr:vanillish": ["pr:vanilluxe"],
            "pr:vanilluxe": [],
            "pr:vaporeon": [],
            "pr:vespiquen": [],
            "pr:vibrava": ["pr:flygon"],
            "pr:victini": [],
            "pr:victreebel": [],
            "pr:vigoroth": ["pr:slaking"],
            "pr:volbeat": [],
            "pr:volcanion": [],
            "pr:volcarona": [],
            "pr:voltorb": ["pr:electrode"],
            "pr:vullaby": ["pr:mandibuzz"],

            // W-Z
            "pr:wailmer": ["pr:wailord"],
            "pr:wailord": [],
            "pr:walrein": [],
            "pr:watchog": [],
            "pr:weavile": [],
            "pr:weedle": ["pr:kakuna", "pr:beedrill"],
            "pr:weepinbell": ["pr:victreebel"],
            "pr:whimsicott": [],
            "pr:whirlipede": ["pr:scolipede"],
            "pr:whiscash": [],
            "pr:whismur": ["pr:loudred", "pr:exploud"],
            "pr:wingull": ["pr:pelipper"],
            "pr:wobbuffet": [],
            "pr:woobat": ["pr:swoobat"],
            "pr:wooper": ["pr:quagsire"],
            "pr:wormadam": [],
            "pr:wurmple": ["pr:silcoon", "pr:cascoon"],
            "pr:wynaut": ["pr:wobbuffet"],
            "pr:xatu": [],
            "pr:xerneas": [],
            "pr:yamask": ["pr:cofagrigus"],
            "pr:yanma": ["pr:yanmega"],
            "pr:yanmega": [],
            "pr:yveltal": [],
            "pr:zangoose": [],
            "pr:zebstrika": [],
            "pr:zekrom": [],
            "pr:zigzagoon": ["pr:linoone"],
            "pr:zoroark": [],
            "pr:zorua": ["pr:zoroark"],
            "pr:zweilous": ["pr:hydreigon"],
            "pr:zygarde": [],
            "pr:feebas": ["pr:milotic"],
            "pr:ferroseed": ["pr:ferrothorn"],
            "pr:finneon": ["pr:lumenon"],
            "pr:elekid": ["pr:electabuzz", "pr:electivire"],
            "pr:electabuzz": ["pr:electivire"],
            "pr:electrike": ["pr:manectric"],
            "pr:cascoon": ["pr:dustox"],
            "pr:duskull": ["pr:dusclops", "pr:dusknoir"],
            "pr:dusclops": ["pr:dusknoir"],
            "pr:dunsparce": ["pr:dudunsparce"],
            "pr:drifloon": ["pr:drifblim"],
            "pr:diglett": ["pr:dugtrio"],
            "pr:croagunk": ["pr:toxicroak"],
            "pr:cubone": ["pr:marowak"],
            "pr:darumaka": ["pr:darmanitan"],
            "pr:bulbassaur": ["pr:ivysaur", "pr:venusaur"],
            "pr:ivysaur": ["pr:venusaur"],
            "pr:charmander": ["pr:charmeleon", "pr:charizard"],
            "pr:charmeleon": ["pr:charizard"],
            "pr:squirtle": ["pr:wartortle", "pr:blastoise"],
            "pr:wartortle": ["pr:blastoise"],
            "pr:caterpie": ["pr:metapod", "pr:butterfree"],
            "pr:metapod": ["pr:butterfree"],
            "pr:weedle": ["pr:kakuna", "pr:beedrill"],
            "pr:kakuna": ["pr:beedrill"],
            "pr:pidgey": ["pr:pidgeotto", "pr:pidgeot"],
            "pr:pidgeotto": ["pr:pidgeot"],
            "pr:rattata": ["pr:raticate"],
            "pr:spearow": ["pr:fearow"],
            "pr:ekans": ["pr:arbok"],
            "pr:pichu": ["pr:pikachu", "pr:raichu"],
            "pr:pikachu": ["pr:raichu"],
            "pr:sandshrew": ["pr:sandslash"],
            "pr:nidoran_female": ["pr:nidorina", "pr:nidoqueen"],
            "pr:nidorina": ["pr:nidoqueen"],
            "pr:nidoran_male": ["pr:nidorino", "pr:nidoking"],
            "pr:nidorino": ["pr:nidoking"],
            "pr:cleffa": ["pr:clefairy", "pr:clafable"],
            "pr:clefairy": ["pr:clafable"],
            "pr:vulpix": ["pr:ninetailes"],
            "pr:igglybuff": ["pr:jigglypuff", "pr:wigglytuff"],
            "pr:jigglypuff": ["pr:wigglytuff"],
            "pr:zubat": ["pr:golbat", "pr:crobat"],
            "pr:golbat": ["pr:crobat"],
            "pr:oddish": ["pr:gloom", "pr:vileplume"],
            "pr:gloom": ["pr:vileplume"],
            "pr:paras": ["pr:parasect"],
            "pr:venonat": ["pr:venomoth"],
            "pr:diglett": ["pr:dugtrio"],
            "pr:meowth": ["pr:persian"],
            "pr:psyduck": ["pr:golduck"],
            "pr:mankey": ["pr:primeape"],
            "pr:growlithe": ["pr:arcanine"],
            "pr:poliwag": ["pr:poliwhirl", "pr:poliwrath"],
            "pr:poliwhirl": ["pr:poliwrath"],
            "pr:abra": ["pr:kadabra", "pr:alakazam"],
            "pr:kadabra": ["pr:alakazam"],
            "pr:machop": ["pr:machoke", "pr:machamp"],
            "pr:machoke": ["pr:machamp"],
            "pr:bellsprout": ["pr:weepinbell", "pr:victreebel"],
            "pr:weepinbell": ["pr:victreebel"],
            "pr:tentacool": ["pr:tentacruel"],
            "pr:geodude": ["pr:graveler", "pr:golem"],
            "pr:graveler": ["pr:golem"],
            "pr:ponyta": ["pr:rapidash"],
            "pr:slowpoke": ["pr:slowbro"],
            "pr:magnemite": ["pr:magneton", "pr:magnezone"],
            "pr:magneton": ["pr:magnezone"],
            "pr:doduo": ["pr:dodrio"],
            "pr:seel": ["pr:dewgong"],
            "pr:grimer": ["pr:muk"],
            "pr:shellder": ["pr:cloyster"],
            "pr:gastly": ["pr:haunter", "pr:gengar"],
            "pr:haunter": ["pr:gengar"],
            "pr:onix": ["pr:steelix"],
            "pr:drawzee": ["pr:hypno"],
            "pr:krabby": ["pr:kingler"],
            "pr:voltorb": ["pr:electrode"],
            "pr:exeggcute": ["pr:exeggutor"],
            "pr:cubone": ["pr:marowak"],
            "pr:tyrogue": ["pr:hitmonlee"],
            "pr:lickitung": ["pr:lickilicky"],
            "pr:koffing": ["pr:weezing"],
            "pr:rhyhorn": ["pr:rhyhdon", "pr:rhyperior"],
            "pr:rhyhdon": ["pr:rhyperior"],
            "pr:happiny": ["pr:chansey", "pr:blissey"],
            "pr:chansey": ["pr:blissey"],
            "pr:tangela": ["pr:tangrowth"],
            "pr:kangaskan": [],
            "pr:horsea": ["pr:seadra", "pr:kingdra"],
            "pr:seadra": ["pr:kingdra"],
            "pr:goldeen": ["pr:seaking"],
            "pr:staryu": ["pr:starmie"],
            "pr:mime_jr": ["pr:mr_mime"],
            "pr:scyther": ["pr:scizor"],
            "pr:smoochum": ["pr:jynx"],
            "pr:elekid": ["pr:electabuzz", "pr:electivire"],
            "pr:electabuzz": ["pr:electivire"],
            "pr:magby": ["pr:magmar", "pr:magmortar"],
            "pr:magmar": ["pr:magmortar"],
            "pr:pinsir": [],
            "pr:tauros": [],
            "pr:magikarp": ["pr:gyarados"],
            "pr:lapras": [],
            "pr:ditto": [],
            "pr:eevee": ["pr:vaporeon"], // Eevee tem múltiplas evoluções, aqui só uma como exemplo
            "pr:porygon": ["pr:porygon2", "pr:porygon_z"],
            "pr:porygon2": ["pr:porygon_z"],
            "pr:omanyte": ["pr:omastar"],
            "pr:kabuto": ["pr:kabutops"],
            "pr:aerodactyl": [],
            "pr:munchlax": ["pr:snorlax"],
            "pr:articuno": [],
            "pr:zapdos": [],
            "pr:moltress": [],
            "pr:dratini": ["pr:dragonair", "pr:dragonite"],
            "pr:dragonair": ["pr:dragonite"],
            "pr:mew_two": [],
            "pr:mew": [],
    "pr:froakie": ["pr:frogadier"],
    "pr:frogadier": ["pr:greninja"],

            "pr:aron": ["pr:lairon", "pr:aggron"],
            "pr:azurill": ["pr:marill", "pr:azumarill"],
            "pr:bayleef": ["pr:meganium"],
            "pr:bidoof": ["pr:bibarel"],
            "pr:braxen": ["pr:delphox"],
            "pr:brionne": ["pr:primarina"],
            "pr:buizel": ["pr:floatzel"],
            "pr:chespin": ["pr:quilladin", "pr:chesnaught"],
            "pr:chikorita": ["pr:bayleef", "pr:meganium"],
            "pr:chimchar": ["pr:monferno", "pr:infernape"],
            "pr:chinchou": ["pr:lanturn"],
            "pr:combee": ["pr:vespiquen"],
            "pr:combusken": ["pr:blaziken"],
            "pr:cranidos": ["pr:rampardos"],
            "pr:croconaw": ["pr:feraligatr"],
            "pr:cyndaquil": ["pr:quilava", "pr:typhlosion"],
            "pr:dewott": ["pr:samurott"],
            "pr:fennekin": ["pr:braxen", "pr:delphox"],
            "pr:grotle": ["pr:torterra"],
            "pr:grovyle": ["pr:sceptile"],
            "pr:gulpin": ["pr:swalot"],
            "pr:marshtomp": ["pr:swampert"],
            "pr:monferno": ["pr:infernape"],
            "pr:mudkip": ["pr:marshtomp", "pr:swampert"],
            "pr:oshawott": ["pr:dewott", "pr:samurott"],
            "pr:pignite": ["pr:emboar"],
            "pr:piplup": ["pr:prinplup", "pr:empoleon"],
            "pr:quilava": ["pr:typhlosion"],
            "pr:quilladin": ["pr:chesnaught"],
            "pr:servine": ["pr:serperior"],
            "pr:snivy": ["pr:servine", "pr:serperior"],
            "pr:tepig": ["pr:pignite", "pr:emboar"],
            "pr:torchic": ["pr:combusken", "pr:blaziken"],
            "pr:totodile": ["pr:croconaw", "pr:feraligatr"],
            "pr:treecko": ["pr:grovyle", "pr:sceptile"],
            "pr:turtwig": ["pr:grotle", "pr:torterra"],
};

// Merge manual evolutions into the full map
for (const key in _manualEvolutionMap) {
    evolutionMap[key] = _manualEvolutionMap[key];
}
const evolutions = evolutionMap[currentPokemonId];
        if (!evolutions || evolutions.length === 0)
            return null;
        // Retorna a evolução baseada no estágio (1 = primeira evolução, 2 = segunda evolução)
        const evolutionIndex = evolutionStage - 1;
        if (evolutionIndex >= 0 && evolutionIndex < evolutions.length) {
            return evolutions[evolutionIndex];
        }
        return null;
    }
    // Função para aplicar a evolução a um Pokémon
    evolvePokemon(pokemonData, evolutionResult) {
        const evolutionTargetInfo = POKEMONS_DATA.find(poke => poke.id === evolutionResult.targetId);
        if (!evolutionTargetInfo)
            return null;
        // Criar nova data do Pokémon evoluído mantendo alguns dados do Pokémon original
        const evolvedPokemon = {
            health: pokemonData.health, // Manter a vida atual
            level: pokemonData.level, // Manter o nível atual
            xp: pokemonData.xp, // Manter XP atual
            typeId: evolutionResult.targetId,
            name: this.getPokemonNameFromTypeId(evolutionResult.targetId),
            owner: pokemonData.owner,
            // Atualizar stats para os stats da evolução
            attack: evolutionTargetInfo.attack,
            defense: evolutionTargetInfo.defense,
            speed: evolutionTargetInfo.speed,
            spAttack: evolutionTargetInfo.spAttack,
            spDefense: evolutionTargetInfo.spDefense,
            // Atualizar movimentos: preserve player-selected moves when available
            move1: pokemonData.move1 || evolutionTargetInfo.move1,
            move2: pokemonData.move2 || evolutionTargetInfo.move2,
            move3: pokemonData.move3 || evolutionTargetInfo.move3,
            move4: pokemonData.move4 || evolutionTargetInfo.move4
        };
        return evolvedPokemon;
    }
    // Função para evoluir manualmente um Pokémon (pode ser chamada por comandos)
    manuallyEvolvePokemon(player, slotIndex) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return false;
        const evolutionResult = this.getEvolutionForPokemon(pokemonData);
        if (!evolutionResult) {
            player.sendMessage(`§c${pokemonData.name} cannot evolve at this level!`);
            return false;
        }
        const evolvedPokemon = this.evolvePokemon(pokemonData, evolutionResult);
        if (!evolvedPokemon) {
            player.sendMessage(`§cEvolution failed for ${pokemonData.name}!`);
            return false;
        }
        this.updatePokemonSlot(player, slotIndex, evolvedPokemon);
        player.sendMessage(`§a🌟 ${pokemonData.name} evolved into ${evolvedPokemon.name}! 🌟`);
        
try {
    player.dimension.spawnParticle("pr:evolution_burst", {
        x: player.location.x,
        y: player.location.y + 1,
        z: player.location.z
    });
} catch (e) {
    console.warn("Evolution particle failed:", e);
}

        return true;
    }
    // Função para verificar se um Pokémon pode evoluir
    canPokemonEvolve(player, slotIndex) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return false;
        return this.getEvolutionForPokemon(pokemonData) !== null;
    }
    // Função para obter informações sobre a próxima evolução de um Pokémon
    getNextEvolutionInfo(player, slotIndex) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return null;
        const currentPokemonInfo = POKEMONS_DATA.find(poke => poke.id === pokemonData.typeId);
        if (!currentPokemonInfo)
            return null;
        // Verificar qual é a próxima evolução possível
        let targetId = null;
        let requiredLevel = null;
        // Se ainda não chegou ao nível da primeira evolução
        if (currentPokemonInfo.transformLevel && pokemonData.level < currentPokemonInfo.transformLevel) {
            targetId = this.findEvolutionTarget(pokemonData.typeId, 1);
            requiredLevel = currentPokemonInfo.transformLevel;
        }
        // Se já passou da primeira evolução mas não chegou na segunda
        else if (currentPokemonInfo.secondTransformLevel && pokemonData.level < currentPokemonInfo.secondTransformLevel) {
            targetId = this.findEvolutionTarget(pokemonData.typeId, 2);
            requiredLevel = currentPokemonInfo.secondTransformLevel;
        }
        if (!targetId || !requiredLevel)
            return null;
        const targetName = this.getPokemonNameFromTypeId(targetId);
        return {
            name: targetName,
            requiredLevel: requiredLevel
        };
    }
    deletePokemonFromSlot(player, slotIndex) {
        // Clear new slot system
        try {
            slotDataManager.clearPokemonSlot(player, slotIndex);
        } catch (e) {
            console.warn(`deletePokemonFromSlot: failed to clear new slot data for slot ${slotIndex}: ${e}`);
        }
        // Clear legacy sidebar properties (1-based indexing)
        const legacySlot = slotIndex + 1;
        try { player.setDynamicProperty(`pr:slot_${legacySlot}_name`, "none"); } catch (e) {}
        try { player.setDynamicProperty(`pr:slot_${legacySlot}_level`, 0); } catch (e) {}
        try { player.setDynamicProperty(`pr:slot_${legacySlot}_health`, 0); } catch (e) {}
    }
    // Métodos para sistema de PC
    // Inicializa o PC do jogador
    initializePlayerPC(player) {
        slotDataManager.initializePlayerPC(player);
    }
    openPC(player) {
        const formPC = new ActionFormData();

        // Keep title EXACTLY "PC" so your RP server_form skin (pc_menu) renders.
        formPC.title("PC");

        // Paging
        const pageSize = 30;
        const maxBoxes = 90;
        const maxPage = maxBoxes - 1;

        const page = (player.getDynamicProperty('pr_rp:pc_page') ?? 0);
        const safePage = Math.max(0, Math.min(maxPage, page));
        if (safePage !== page) player.setDynamicProperty('pr_rp:pc_page', safePage);

        // Party slots (0–5)
        [1, 2, 3, 4, 5, 6].forEach(i => {
            const pokemonData = this.getPokemonFromSlot(player, i - 1);
            if (pokemonData) {
                formPC.button(`${pokemonData.name} (Lvl ${pokemonData.level})`, `textures/icons/pokemons/${pokemonData.typeId.split(':')[1]}.png`);
            }
            else {
                formPC.button("Empty Slot");
            }
        });

        // Actions (6–9)
        formPC.button("Withdraw from PC");
        formPC.button("Deposit to PC");
        formPC.button("View Summary");
        formPC.button("Close");

        // PC slots: your RP uses indices 12 & 13 as arrow hitboxes.
        // So indices map like:
        // 10->slot0, 11->slot1, 12->Prev, 13->Next, 14->slot2 ... 41->slot29
        const pcAll = this.getPCPokemons(player);
        const startIndex = safePage * pageSize;
        const pcSlice = pcAll.slice(startIndex, startIndex + pageSize);

        // Slots 0–1
        for (let k = 0; k < 2; k++) {
            const poke = pcSlice[k];
            if (poke) formPC.button(`${poke.name} (Lvl ${poke.level})`, `textures/icons/pokemons/${poke.typeId.split(':')[1]}.png`);
            else formPC.button("Empty Slot");
        }

        // Arrow buttons (12/13)
        formPC.button("Prev Box");
        formPC.button("Next Box");

        // Slots 2–29
        for (let k = 2; k < pageSize; k++) {
            const poke = pcSlice[k];
            if (poke) formPC.button(`${poke.name} (Lvl ${poke.level})`, `textures/icons/pokemons/${poke.typeId.split(':')[1]}.png`);
            else formPC.button("Empty Slot");
        }

        formPC.show(player).then((response) => {
            if (response.canceled || response.cancelationReason) {
                player.setDynamicProperty('pr_rp:selectedSlot', -1);
                return;
            }

            const selectedButton = response.selection;

            // Arrow handling
            if (selectedButton === 12) {
                const next = Math.max(0, safePage - 1);
                player.setDynamicProperty('pr_rp:pc_page', next);
                player.setDynamicProperty('pr_rp:selectedSlot', -1);
                this.openPC(player);
                return;
            }
            if (selectedButton === 13) {
                const next = Math.min(maxPage, safePage + 1);
                player.setDynamicProperty('pr_rp:pc_page', next);
                player.setDynamicProperty('pr_rp:selectedSlot', -1);
                this.openPC(player);
                return;
            }

            switch (selectedButton) {
                case 6: {
                    this.withdrawPokemonFromPC(player);
                    player.setDynamicProperty('pr_rp:selectedSlot', -1);
                    this.openPC(player);
                    break;
                }
                case 7: {
                    this.depositPokemonToPC(player);
                    player.setDynamicProperty('pr_rp:selectedSlot', -1);
                    this.openPC(player);
                    break;
                }
                case 8: {
                    player.setDynamicProperty('pr_rp:selectedSlot', -1);
                    break;
                }
                case 9: {
                    player.setDynamicProperty('pr_rp:selectedSlot', -1);
                    return;
                }
                default: {
                    // PC slot clicked (skip 12/13)
                    let local = -1;
                    if (selectedButton === 10) local = 0;
                    else if (selectedButton === 11) local = 1;
                    else if (selectedButton >= 14 && selectedButton <= 41) local = selectedButton - 12; // 14->2 ... 41->29

                    if (local >= 0) {
                        const absPcIndex = startIndex + local;
                        player.setDynamicProperty('pr_rp:selectedSlot', 10 + absPcIndex);
                    } else {
                        player.setDynamicProperty('pr_rp:selectedSlot', selectedButton);
                    }
                    this.openPC(player);
                }
            }
        });
    }
    withdrawPokemonFromPC(player) {
        const slotIndex = player.getDynamicProperty('pr_rp:selectedSlot');
        if (slotIndex == -1)
            return false;
        if (slotIndex >= 10) {
            const pcIndex = slotIndex - 10;
            const hasEmptySlot = slotDataManager.findFirstEmptySlot(player) !== -1;
            if (!hasEmptySlot) {
                player.sendMessage("No empty slot available to withdraw Pokémon from PC.");
                return false;
            }
            const pcPokemon = slotDataManager.getPokemonFromPC(player, pcIndex);
            if (!pcPokemon) {
                player.sendMessage("No Pokémon found in this PC slot.");
                return false;
            }
            const success = this.movePokemonFromPC(player, pcIndex);
            if (success) {
                player.sendMessage(`Withdrew Pokémon: ${pcPokemon.name} from PC.`);
                return true;
            }
            else {
                player.sendMessage("Failed to withdraw Pokémon.");
                return false;
            }
        }
        return false;
    }
    depositPokemonToPC(player) {
        const slotIndex = player.getDynamicProperty('pr_rp:selectedSlot');
        if (slotIndex == -1)
            return false;
        if (slotIndex < 6) {
            const pokemonData = this.getPokemonFromSlot(player, slotIndex);
            if (!pokemonData)
                return false;
            if (this.getPCPokemonCount(player) >= 1800) {
                player.sendMessage("PC is full! Cannot deposit Pokémon.");
                return false;
            }
            const success = this.movePokemonToPC(player, slotIndex);
            if (success) {
                player.sendMessage(`Deposited Pokémon: ${pokemonData.name} to PC.`);
                return true;
            }
            else {
                player.sendMessage("Failed to deposit Pokémon.");
                return false;
            }
        }
        player.sendMessage("You must select a Pokémon from your slots to deposit.");
        return false;
    }
    // Obtém todos os Pokémon do PC
    getPCPokemons(player) {
        const pcData = slotDataManager.getPlayerPCData(player);
        return pcData.pokemons;
    }
    // Obtém contagem de Pokémon no PC
    getPCPokemonCount(player) {
        return slotDataManager.getPCPokemonCount(player);
    }
    // Move Pokémon do slot para o PC
    movePokemonToPC(player, slotIndex) {
        return slotDataManager.movePokemonToPC(player, slotIndex);
    }
    // Move Pokémon do PC para slot vazio
    movePokemonFromPC(player, pcIndex) {
        const emptySlot = slotDataManager.findFirstEmptySlot(player);
        if (emptySlot === -1)
            return false;
        return slotDataManager.movePokemonFromPC(player, pcIndex, emptySlot);
    }
    // Move Pokémon do PC para slot específico
    movePokemonFromPCToSlot(player, pcIndex, slotIndex) {
        return slotDataManager.movePokemonFromPC(player, pcIndex, slotIndex);
    }
    // Remove Pokémon do PC permanentemente
    releasePokemonFromPC(player, pcIndex) {
        return slotDataManager.removePokemonFromPC(player, pcIndex);
    }
    // Deleta Pokémon do PC permanentemente (alias para releasePokemonFromPC)
    deletePokemonFromPC(player, pcIndex) {
        return this.releasePokemonFromPC(player, pcIndex);
    }
    // Deleta todos os Pokémon do PC
    clearAllPokemonFromPC(player) {
        try {
            const pcData = slotDataManager.getPlayerPCData(player);
            pcData.pokemons = [];
            return slotDataManager.savePlayerPCData(player, pcData);
        }
        catch (error) {
            console.error('Erro ao limpar todos os Pokémon do PC:', error);
            return false;
        }
    }
    // Deleta múltiplos Pokémon do PC por índices
    deleteMultiplePokemonFromPC(player, pcIndices) {
        try {
            // Ordena os índices em ordem decrescente para remover sem afetar os índices seguintes
            const sortedIndices = pcIndices.sort((a, b) => b - a);
            for (const pcIndex of sortedIndices) {
                if (!this.releasePokemonFromPC(player, pcIndex)) {
                    return false;
                }
            }
            return true;
        }
        catch (error) {
            console.error('Erro ao deletar múltiplos Pokémon do PC:', error);
            return false;
        }
    }
    // Troca Pokémon entre slot e PC
    swapPokemonSlotWithPC(player, slotIndex, pcIndex) {
        try {
            const slotPokemon = this.getPokemonFromSlot(player, slotIndex);
            const pcPokemon = slotDataManager.getPokemonFromPC(player, pcIndex);
            if (!slotPokemon || !pcPokemon)
                return false;
            // Remove ambos temporariamente
            slotDataManager.clearPokemonSlot(player, slotIndex);
            slotDataManager.removePokemonFromPC(player, pcIndex);
            // Coloca o Pokémon do PC no slot
            slotDataManager.setPokemonSlotData(player, slotIndex, pcPokemon);
            // Coloca o Pokémon do slot no PC
            slotDataManager.addPokemonToPC(player, slotPokemon);
            return true;
        }
        catch (error) {
            console.error('Erro ao trocar Pokémon entre slot e PC:', error);
            return false;
        }
    }
    // Função utilitária para criar dados de Pokémon
    createPokemonSlotData(pokemonId, level, customName, ownerId) {
        const pokemonData = POKEMONS_DATA.find(poke => poke.id === pokemonId);
        if (!pokemonData)
            return null;
        const pokemonLevel = level || this.randomValue(pokemonData.minSpawnLevel, pokemonData.maxSpawnLevel);
        const pokemonName = customName || this.getPokemonNameFromTypeId(pokemonId);
        return {
            health: pokemonData.maxHealth,
            level: pokemonLevel,
            xp: 0,
            typeId: pokemonId,
            name: pokemonName,
            owner: ownerId || '',
            attack: pokemonData.attack,
            defense: pokemonData.defense,
            speed: pokemonData.speed,
            spAttack: pokemonData.spAttack,
            spDefense: pokemonData.spDefense,
            move1: pokemonData.move1,
            move2: pokemonData.move2,
            move3: pokemonData.move3,
            move4: pokemonData.move4
        };
    }
    // Função utilitária para obter o nome do Pokémon a partir do typeId
    getPokemonNameFromTypeId(typeId) {
        // Verificar se o typeId é válido
        if (!typeId || typeof typeId !== 'string') {
            console.warn(`typeId inválido: ${typeId}`);
            return "Unknown Pokemon";
        }
        // Remove o prefixo "pr:" e converte para Title Case
        const nameWithoutPrefix = typeId.replace('pr:', '');
        return StringUtils.toTitleCaseEntityName(nameWithoutPrefix);
    }
    // Método para migrar dados antigos (compatibilidade)
    migrateLegacyPokemonData(player) {
        for (let i = 0; i < 6; i++) {
            const legacyData = player.getDynamicProperty(`rp_pr:pokemon_slot_${i}`);
            if (legacyData && legacyData.includes('|')) {
                // Verifica se é formato antigo (8 partes ao invés de 9)
                const parts = legacyData.split('|');
                if (parts.length === 8) {
                    try {
                        // Converte dados antigos para novo formato
                        const pokemonData = slotDataManager.getPokemonSlotData(player, i);
                        if (pokemonData && !pokemonData.name) {
                            pokemonData.name = this.getPokemonNameFromTypeId(pokemonData.typeId);
                            slotDataManager.setPokemonSlotData(player, i, pokemonData);
                        }
                    }
                    catch (error) {
                        console.error(`Erro ao migrar dados do slot ${i}:`, error);
                    }
                }
            }
        }
    }
    // Método para migrar dados existentes para incluir as novas informações
    migratePokemonDataToNewFormat(player) {
        debug.log(`Migrando dados do jogador ${player.nameTag} para novo formato`);
        for (let i = 0; i < 6; i++) {
            const pokemonData = this.getPokemonFromSlot(player, i);
            if (!pokemonData)
                continue;
            // Verificar se precisa migrar (campos novos ausentes)
            if (pokemonData.owner === undefined || pokemonData.attack === undefined) {
                debug.log(`Migrando dados do slot ${i}`);
                // Buscar dados do Pokémon para obter stats
                const pokemonInfo = POKEMONS_DATA.find(poke => poke.id === pokemonData.typeId);
                if (!pokemonInfo) {
                    debug.log(`Não foi possível encontrar dados do Pokémon ${pokemonData.typeId}`);
                    continue;
                }
                // Atualizar dados com as novas informações
                pokemonData.owner = pokemonData.owner || player.id;
                pokemonData.attack = pokemonData.attack || pokemonInfo.attack;
                pokemonData.defense = pokemonData.defense || pokemonInfo.defense;
                pokemonData.speed = pokemonData.speed || pokemonInfo.speed;
                pokemonData.spAttack = pokemonData.spAttack || pokemonInfo.spAttack;
                pokemonData.spDefense = pokemonData.spDefense || pokemonInfo.spDefense;
                // Salvar dados atualizados
                this.updatePokemonSlot(player, i, pokemonData);
                debug.log(`Dados do slot ${i} migrados com sucesso`);
            }
        }
        // Migrar dados do PC também
        const pcData = slotDataManager.getPlayerPCData(player);
        let pcNeedsMigration = false;
        for (let i = 0; i < pcData.pokemons.length; i++) {
            const pokemonData = pcData.pokemons[i];
            if (pokemonData.owner === undefined || pokemonData.attack === undefined) {
                debug.log(`Migrando dados do PC índice ${i}`);
                const pokemonInfo = POKEMONS_DATA.find(poke => poke.id === pokemonData.typeId);
                if (!pokemonInfo)
                    continue;
                pokemonData.owner = pokemonData.owner || player.id;
                pokemonData.attack = pokemonData.attack || pokemonInfo.attack;
                pokemonData.defense = pokemonData.defense || pokemonInfo.defense;
                pokemonData.speed = pokemonData.speed || pokemonInfo.speed;
                pokemonData.spAttack = pokemonData.spAttack || pokemonInfo.spAttack;
                pokemonData.spDefense = pokemonData.spDefense || pokemonInfo.spDefense;
                pcNeedsMigration = true;
            }
        }
        if (pcNeedsMigration) {
            slotDataManager.savePlayerPCData(player, pcData);
            debug.log(`Dados do PC migrados com sucesso`);
        }
    }
    // Função para verificar e corrigir dados de formato antigo
    checkAndFixLegacyData(player, slotIndex) {
        debug.log(`Verificando dados legados no slot ${slotIndex}`);
        const rawData = player.getDynamicProperty(`rp_pr:pokemon_slot_${slotIndex}`);
        if (!rawData) {
            debug.log(`Nenhum dado encontrado no slot ${slotIndex}`);
            return false;
        }
        const parts = rawData.split('|');
        debug.log(`Dados brutos têm ${parts.length} partes`);
        if (parts.length === 8) {
            debug.log(`Dados antigos detectados (8 partes), convertendo para novo formato...`);
            try {
                // Dados antigos: [health, level, xp, pokemonId, move1, move2, move3, move4]
                // Vamos tentar decodificar usando o slotDataManager primeiro
                const tempData = slotDataManager.decodePokemonSlotData(rawData);
                if (tempData) {
                    debug.log(`Dados decodificados com sucesso pelo slotDataManager`);
                    return true;
                }
                // Se não conseguiu decodificar, é porque é formato antigo
                debug.log(`Dados antigos confirmados, realizando conversão manual...`);
                // Para dados antigos, vamos assumir que parts[3] é o pokemonId codificado
                // e tentar encontrar o typeId correspondente
                const pokemonIdCode = parts[3];
                let typeId = '';
                // Buscar nos dados de Pokemon para encontrar o typeId
                POKEMONS_DATA.forEach((pokemon, index) => {
                    const shortCode = this.encodeNumber(index);
                    if (shortCode === pokemonIdCode) {
                        typeId = pokemon.id;
                    }
                });
                if (!typeId) {
                    debug.log(`Não foi possível encontrar typeId para o código ${pokemonIdCode}`);
                    return false;
                }
                const name = this.getPokemonNameFromTypeId(typeId);
                // Buscar dados do Pokémon para obter stats
                const pokemonInfo = POKEMONS_DATA.find(poke => poke.id === typeId);
                if (!pokemonInfo) {
                    debug.log(`Não foi possível encontrar dados do Pokémon ${typeId}`);
                    return false;
                }
                const newData = {
                    health: parseInt(parts[0]) || 0,
                    level: parseInt(parts[1]) || 1,
                    xp: parseInt(parts[2]) || 0,
                    typeId: typeId,
                    name: name,
                    owner: '', // Será definido quando necessário
                    attack: pokemonInfo.attack,
                    defense: pokemonInfo.defense,
                    speed: pokemonInfo.speed,
                    spAttack: pokemonInfo.spAttack,
                    spDefense: pokemonInfo.spDefense,
                    move1: this.findMovementById(parts[4]) || '',
                    move2: this.findMovementById(parts[5]) || '',
                    move3: this.findMovementById(parts[6]) || '',
                    move4: this.findMovementById(parts[7]) || ''
                };
                debug.log(`Dados convertidos: ${JSON.stringify(newData)}`);
                // Salvar no novo formato
                this.updatePokemonSlot(player, slotIndex, newData);
                debug.log(`Dados salvos no novo formato`);
                return true;
            }
            catch (error) {
                console.error(`Erro ao converter dados antigos:`, error);
                return false;
            }
        }
        else if (parts.length === 9) {
            debug.log(`Dados já estão no novo formato`);
            return true;
        }
        else {
            debug.log(`Formato de dados inválido (${parts.length} partes)`);
            return false;
        }
    }
    // Helper para encontrar movimento por código
    findMovementById(code) {
        for (let index = 0; index < MOVEMENTS_DATA.length; index++) {
            const shortCode = this.encodeNumber(index);
            if (shortCode === code) {
                return MOVEMENTS_DATA[index].id;
            }
        }
        return '';
    }
    // Helper para codificar números (copiado do slotDataManager)
    encodeNumber(num) {
        const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        if (num === 0)
            return '0';
        let result = '';
        while (num > 0) {
            result = chars[num % 62] + result;
            num = Math.floor(num / 62);
        }
        return result;
    }
    // Função de debug para verificar dados de slot
    debugSlotData(player, slotIndex) {
        debug.log(`===== DEBUGGING SLOT ${slotIndex + 1} =====`);
        debug.log(`Player: ${player.nameTag}`);
        // Verificar dados brutos
        const rawData = player.getDynamicProperty(`rp_pr:pokemon_slot_${slotIndex}`);
        debug.log(`Raw data: "${rawData}"`);
        if (!rawData) {
            debug.log(`No raw data found in slot ${slotIndex + 1}`);
            return;
        }
        // Tentar decodificar
        const decodedData = this.getPokemonFromSlot(player, slotIndex);
        debug.log(`Decoded data: ${decodedData ? JSON.stringify(decodedData) : 'NULL'}`);
        // Verificar se é possível re-codificar
        if (decodedData) {
            try {
                const reEncodedData = slotDataManager.encodePokemonSlotData(decodedData);
                debug.log(`Re-encoded data: "${reEncodedData}"`);
                debug.log(`Data matches: ${rawData === reEncodedData}`);
            }
            catch (error) {
                console.error(`Error re-encoding:`, error);
            }
        }
        // Verificar outros slots para comparação
        debug.log(`Checking other slots for comparison:`);
        for (let i = 0; i < 6; i++) {
            const otherRawData = player.getDynamicProperty(`rp_pr:pokemon_slot_${i}`);
            if (otherRawData) {
                debug.log(`Slot ${i + 1} has data: "${otherRawData}"`);
            }
        }
    }
    // Método para obter stats de um Pokémon específico
    getPokemonStats(player, slotIndex) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return null;
        return {
            attack: pokemonData.attack,
            defense: pokemonData.defense,
            speed: pokemonData.speed,
            spAttack: pokemonData.spAttack,
            spDefense: pokemonData.spDefense
        };
    }
    // Método para atualizar stats de um Pokémon
    updatePokemonStats(player, slotIndex, stats) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return false;
        if (stats.attack !== undefined)
            pokemonData.attack = stats.attack;
        if (stats.defense !== undefined)
            pokemonData.defense = stats.defense;
        if (stats.speed !== undefined)
            pokemonData.speed = stats.speed;
        if (stats.spAttack !== undefined)
            pokemonData.spAttack = stats.spAttack;
        if (stats.spDefense !== undefined)
            pokemonData.spDefense = stats.spDefense;
        this.updatePokemonSlot(player, slotIndex, pokemonData);
        return true;
    }
    // Método para obter informações do dono de um Pokémon
    getPokemonOwner(player, slotIndex) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        return pokemonData ? pokemonData.owner : null;
    }
    // Método para atualizar o dono de um Pokémon
    updatePokemonOwner(player, slotIndex, newOwnerId) {
        const pokemonData = this.getPokemonFromSlot(player, slotIndex);
        if (!pokemonData)
            return false;
        pokemonData.owner = newOwnerId;
        this.updatePokemonSlot(player, slotIndex, pokemonData);
        return true;
    }
    // Método para sincronizar propriedades dinâmicas de uma entidade Pokémon
    syncPokemonEntityProperties(pokemonEntity, pokemonData, ownerPlayer) {
        // (BoB13) aq define as propertys corretamentez

        // Definir propriedades básicas
        pokemonEntity.setDynamicProperty("pr:tamed", true);
        try { pokemonEntity.triggerEvent("tamed"); } catch (e) {}

        pokemonEntity.setDynamicProperty("pr:level", pokemonData.level);
        pokemonEntity.setDynamicProperty("pr:health", pokemonData.health);
        pokemonEntity.setDynamicProperty("pr:xp", pokemonData.xp);
        pokemonEntity.setDynamicProperty("pr:owner", pokemonData.owner || ownerPlayer.id);
        pokemonEntity.setDynamicProperty("pr:owner_name", ownerPlayer.name);
        // Definir stats do Pokémon
        pokemonEntity.setDynamicProperty("pr:attack", pokemonData.attack);
        pokemonEntity.setDynamicProperty("pr:defense", pokemonData.defense);
        pokemonEntity.setDynamicProperty("pr:speed", pokemonData.speed);
        pokemonEntity.setDynamicProperty("pr:spAttack", pokemonData.spAttack);
        pokemonEntity.setDynamicProperty("pr:spDefense", pokemonData.spDefense);
        // Atualizar componente de saúde
        const healthComponent = pokemonEntity.getComponent("minecraft:health");
        if (healthComponent) {
            healthComponent.setCurrentValue(pokemonData.health);
        }
        // Atualizar nome da entidade
        pokemonEntity.nameTag = `${pokemonData.name}\n§aOwner: ${ownerPlayer.name}\nLvl: §a${pokemonData.level}§r`;
    }
    // Método para obter dados completos de um Pokémon incluindo stats
    getPokemonCompleteData(player, slotIndex) {
        return this.getPokemonFromSlot(player, slotIndex);
    }
}
export const pokemonUtils = new PokemonUtils();
