import { ItemStack, world , system} from "@minecraft/server";
import { ActionFormData, ModalFormData, uiManager } from "@minecraft/server-ui";
import { StringUtils } from "../../utils/stringUtils.js";
import { pokemonUtils } from "../../utils/pokemonUtils.js";
import { POKEMON_CAN_LEARN, POKEMONS_DATA } from "../pokemon.js";
import { MOVEMENTS_DATA } from "../movement.js";
import { getLearnPoints, spendLearnPoint, getLearnPointsSync } from "../../utils/learnPoints.js";
import { buildOffensiveSummary, formatTyping } from "../../utils/typeEffectiveness.js";

// Fast lookup to avoid repeated MOVEMENTS_DATA.find() in menus
const MOVE_BY_ID = new Map();
try { for (const m of MOVEMENTS_DATA) { if (m && m.id) MOVE_BY_ID.set(m.id, m); } } catch (e) { }

import { UIManagerPokemon } from "../../utils/uiManagerPokemon.js";
const uiManagerPokemon = new UIManagerPokemon();
export function arceusMenu(player) {
    const form = uiManagerPokemon.registerForm(player, {
        title: "Arceus",
        buttons: [
            { text: "Send out" },
            { text: "Return" },
            { text: "Change Party" },
            { text: "Set Nickname" },
            { text: "Edit Moves" },
            { text: "Summary" }
        ]
    });
    uiManagerPokemon.showForm(player, form, (response, player) => {
        const selection = response.selection;
        world.sendMessage(`§a[Arceus] §7You selected slot ${selection}`);
        buttonOfArceus[selection]?.(player);
    });
}
export const buttonOfArceus = {
    0: (player) => {
        sendOut(player);
    },
    1: (player) => {
        // Return ALL out Pokémon (multi-out support)
        for (let s = 0; s < 6; s++) {
            player.setDynamicProperty("pr:selectedSlot", s);
            pokemonUtils.returnPokemonToSlot(player);
        }
    },
    2: (player) => {
        changeParty(player);
    },
    3: (player) => {
        setNickname(player);
    },
    4: (player) => {
        editMove(player);
    },
    5: (player) => {
        summary(player);
    }
};
export function sendOut(player) {
    let form = new ActionFormData();
    form.title("Options");
    form.body(`000000000000`);
    [1, 2, 3, 4, 5, 6].forEach((i) => {
        form.button(`Slot ${i}`);
    });
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
        const selection = response.selection;
        if (selection > 5)
            return;
        sendOutSlots(player, selection);
    });
}
function sendOutSlots(player, slotIndex) {
    // Multi-out: DO NOT auto-return your currently selected Pokémon.
    // Prevent duplicate spawns for the same party slot.
    // IMPORTANT: Pokémon entities in this pack reliably store:
    //  - pr:owner  (player.id)
    //  - pr:tamed  (boolean)
    //  - pr:slot_index (0-5)  <-- set in pokemonUtils.spawnPokemon()
    // Some entities do NOT have the "pokemon" family, so we cannot filter by families.
    try {
        const nearby = player.dimension.getEntities({ location: player.location, maxDistance: 160 });
        for (const e of nearby) {
            try {
                if (e.getDynamicProperty("pr:owner") !== player.id) continue;
                if (e.getDynamicProperty("pr:tamed") !== true) continue;
                if (Number(e.getDynamicProperty("pr:slot_index")) === Number(slotIndex)) {
                    player.onScreenDisplay.setActionBar("That party slot is already out!");
                    return;
                }
            }
            catch (e2) { }
        }
    }
    catch (e) { }

    // Keep selectedSlot as "active slot" for menus/battle/etc.
    player.setDynamicProperty("pr:selectedSlot", slotIndex);
    pokemonUtils.spawnPokemon(player, slotIndex);
}
export function changeParty(player) {
    let form = new ActionFormData()
        .title("Options")
        .body(`000000000000`)
        .button("Set")
        .button("Remove")
        .button("Close");
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
        const selection = response.selection;
        if (selection == 0) {
            optionsMenuRA(player);
        }
        ;
        if (selection == 1) {
            optionsMenuAR(player);
        }
    });
}
export function optionsMenuRA(player) {
    let form = new ActionFormData();
    form.title("Options");
    form.body(`000000000000`);
    for (let i = 1; i < 7; i++) {
        form.button(`Slot ` + i);
    }
    form.button("Close");
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
        const selection = response.selection;
        if (selection > 5)
            return;
        optionsMenuSlotsRA(player, selection);
    });
}
function optionsMenuSlotsRA(player, slotIndex) {
    const selectedSlot = player.getDynamicProperty("pr:selectedSlot");
    if (selectedSlot === slotIndex) {
        player.onScreenDisplay.setActionBar("There is already a pokemon in this slot, your main one!");
        return;
    }
    const pokemonData = pokemonUtils.getPokemonFromSlot(player, slotIndex);
    if (pokemonData) {
        player.onScreenDisplay.setActionBar("You already have a pokemon in this slot, remove to add another one!");
    }
    else {
        selectPokeToSlot(player, slotIndex);
    }
}
export function optionsMenuAR(player) {
    let form = new ActionFormData();
    form.title("Options");
    form.body(`000000000000`);
    for (let i = 1; i < 7; i++) {
        form.button(`Slot ` + i);
    }
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
        const selection = response.selection;
        if (selection > 5)
            return;
        optionsMenuSlots(player, selection);
    });
}
function optionsMenuSlots(player, slotIndex) {
    const pokemonData = pokemonUtils.getPokemonFromSlot(player, slotIndex);
    if (!pokemonData) {
        player.onScreenDisplay.setActionBar("You don't have a pokemon in this slot!");
        return;
    }

    // Always clear the slot first so it cannot get stuck as "occupied" if spawning the egg fails.
    pokemonUtils.deletePokemonFromSlot(player, slotIndex);

    // Then try to give the player the spawn egg representing the removed Pokémon.
    try {
        const pokemonName = pokemonData.typeId.replace("pr:", "");
        const itemNew = new ItemStack(pokemonData.typeId + "_spawn_egg", 1);
        itemNew.setLore([
            `${StringUtils.formatAttackName(pokemonName)} Tamed`,
            `Owner:§7 ${player.nameTag}`,
            `Level:§7 ${pokemonData.level}`,
            `Health:§7 ${pokemonData.health}`
        ]);
        player.dimension.spawnItem(itemNew, player.location);
    } catch (e) {
        console.warn(`Change Party > Remove: failed to spawn egg for slot ${slotIndex}: ${e}`);
    }
}
function selectPokeToSlot(player, slot) {
    let form = new ActionFormData();
    form.title("Options");
    form.body(`000000000000`);
    const inventoryContainer = player.getComponent("minecraft:inventory").container;
    for (let i = 0; i < inventoryContainer.size; i++) {
        const item = inventoryContainer.getItem(i);
        if (item) {
            if (item.getLore().length > 0 && item.getLore()[0].includes("Tamed") && !item.getLore()[3].includes("Death")) {
                const pokemonData = POKEMONS_DATA.find(pokemon => pokemon.id == item.typeId.replace("_spawn_egg", ""));
                if (!pokemonData)
                    continue;
                let pokeHealth = parseInt(item.getLore()[3].replace("Health:§7 ", ""));
                let pokeLevel = item.getLore()[2].replace("Level:§7 ", "");
                form.button("§f" + StringUtils.toTitleCaseEntityName(item.typeId) + "§7\nLvl.§r" + pokeLevel + " §0|§7 HP: §r" + pokeHealth, "textures/icons/pokemons/" + StringUtils.toLowerCaseEntityName(item.typeId));
            }
        }
    }
    form.button("Close");
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
        const selection = response.selection;
        if (selection > 26)
            return;
        selectPokeSlot(player, selection, inventoryContainer, slot);
    });
}
function selectPokeSlot(player, slotIndex, inventoryContainer, slot) {
    const item = inventoryContainer.getItem(slotIndex);
    let pokeHealth = parseInt(item.getLore()[3].replace("Health:§7 ", ""));
    let pokeLevel = parseInt(item.getLore()[2].replace("Level:§7 ", ""));
    const pokemonTypeId = item.typeId.replace("_spawn_egg", "");
    const pokemonData = POKEMONS_DATA.find(pokemon => pokemon.id == pokemonTypeId);
    if (!pokemonData)
        return;
    // Create Pokemon slot data using the new system
    const pokemonSlotData = pokemonUtils.createPokemonSlotData(pokemonTypeId, pokeLevel, undefined, player.id);
    if (!pokemonSlotData)
        return;
    // Set the correct health
    pokemonSlotData.health = pokeHealth;
    // Update the slot with the new data
    pokemonUtils.updatePokemonSlot(player, slot, pokemonSlotData);
    console.warn(`Added ${pokemonSlotData.name} to slot ${slot} with level ${pokeLevel} and health ${pokeHealth}`);
    inventoryContainer.setItem(slotIndex);
}
export function editMove(player) {
    let form = new ActionFormData();
    form.title("Options");
    form.body(`000000000000`);
    for (let i = 1; i < 7; i++) {
        form.button(`Slot ${i}`);
    }
    form.button("Back");
    form.button("Close");
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
        const selection = response.selection;
        if (selection < 6) {
            buttonSlotMoves(player, selection);
        }
        if (selection == 6) {
            arceusMenu(player);
        }
    });
}
function buttonSlotMoves(player, slotIndex) {
    const selectedSlot = player.getDynamicProperty("pr:selectedSlot");
    const pokemonData = pokemonUtils.getPokemonFromSlot(player, slotIndex);
    if (pokemonData) {
        slotMoves(player, pokemonData.typeId.replace("pr:", ""), slotIndex);
    }
    else {
        player.onScreenDisplay.setActionBar("No have a pokemon in this slot!");
    }
}
export function slotMoves(player, pokemon, slot) {
    let form = new ActionFormData();
    form.title("Options");
    form.body(`000000000000`);
    [1, 2, 3, 4].forEach((i) => {
        form.button(`Move ${i}`);
    });
    form.button("Back");
    form.button("Close");
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
        const selection = response.selection;
        if (selection < 4) {
            movesButtonExecute(player, pokemon, selection, slot);
        }
        ;
        if (selection == 4) {
            editMove(player);
        }
    });
}
function movesButtonExecute(player, pokemon, i, slot) {
    // Team data slots are 0-5 (rp_pr:pokemon_slot_0..5).
    // Learn Points are stored 1-6 (one per team slot).
    const rawSlot = Number(slot);
    const slotIndex0 = Math.max(0, Math.min(5, Number.isFinite(rawSlot) ? rawSlot : 0));
    const slotNum1 = slotIndex0 + 1;

    // Sync pokemon entity slot props
    try { pokemon?.setDynamicProperty?.("pr:slot_index", slotIndex0); } catch (e) { }
    try { pokemon?.setDynamicProperty?.("pr:slot", slotNum1); } catch (e) { }

    try { player.onScreenDisplay.setActionBar("Opening move picker..."); } catch (e) { }
    system.run(() => {
        try { movesMenu(player, pokemon, i, slotIndex0); } catch (e) {
            try { player.sendMessage(`§cMove picker error: ${e}`); } catch (e2) { }
        }
    });
}
function movesMenu(player, pokemon, moveSlot, slot) {
    const rawSlot = Number(slot);
        const slotIndex0 = Math.max(0, Math.min(5, Number.isFinite(rawSlot) ? rawSlot : 0));
        const slotNum1 = slotIndex0 + 1;
// Open on next tick to avoid nested-form freezes
    system.run(() => {
        const pokemonName = StringUtils.formatEntityFull(pokemon);
        const moveListFull = POKEMON_CAN_LEARN.get(pokemonName) ?? [];
        const pokemonSlotData = pokemonUtils.getPokemonFromSlot(player, slotIndex0);
        if (!pokemonSlotData) { try { player.sendMessage(`§cNo pokemon data found for slot ${slotIndex0}.§r`); } catch (e) { } return; }

        const knownMoves = [pokemonSlotData.move1, pokemonSlotData.move2, pokemonSlotData.move3, pokemonSlotData.move4].filter(m => m);
        getLearnPoints(player, slotNum1).then((learnPoints) => {

        // Step 1: search/filter form (keeps options list small so it won't freeze)
        const searchForm = new ModalFormData();
        searchForm.title("Move Search");
        searchForm.textField("Search (leave blank for all):", "e.g. wing");
        searchForm.toggle("Show only learnable/known");

        searchForm.show(player).then((res) => {
            if (res.canceled) return;

            const search = String(res.formValues?.[0] ?? "").trim().toLowerCase();
            const onlyGood = Boolean(res.formValues?.[1]);

            // Build filtered list, but keep it capped so the dropdown stays safe.
            const filtered = [];
            for (const moveId of moveListFull) {
                const move = MOVE_BY_ID.get(moveId);
                if (!move) continue;

                const name = String(move.name ?? move.id);
                if (search && !name.toLowerCase().includes(search)) continue;

                const isKnown = knownMoves.includes(moveId);
                const canLearn = !isKnown && learnPoints > 0;

                if (onlyGood && !(isKnown || canLearn)) continue;

                filtered.push({ moveId, name, isKnown, canLearn });
                if (filtered.length >= 120) break; // hard cap to prevent freeze
            }

            if (filtered.length === 0) {
                try { player.onScreenDisplay.setActionBar("§cNo moves found (try a different search).§r"); } catch (e) { }
                return;
            }

            // Step 2: pick from dropdown (stable, small list)
            const picker = new ModalFormData();
            picker.title("Move Picker");

            const options = filtered.map((m) => {
                const prefix = m.isKnown ? "✓ " : (m.canLearn ? "★ " : "🔒 ");
                return prefix + m.name;
            });

            const label = `Learn Points: ${learnPoints} | Set Move ${moveSlot + 1}`;
            // Your API version expects 2 args for dropdown
            picker.dropdown(label, options);

            picker.show(player).then((pickRes) => {
                if (pickRes.canceled) return;

                const idx = Number(pickRes.formValues?.[0] ?? 0);
                const choice = filtered[idx];
                if (!choice) return;

                // Locked: no points and not already known
                if (!choice.isKnown && learnPoints <= 0) {
                    try { player.onScreenDisplay.setActionBar("§cNo Learn Points.§r"); } catch (e) { }
                    return;
                }

                // Spend a point if learning a new move (schedule to avoid UI deadlocks)
                if (!choice.isKnown) {
                    system.run(() => { try { spendLearnPoint(player, slotNum1); } catch (e) { } });
                }

                const pdata = pokemonUtils.getPokemonFromSlot(player, slotIndex0);
                if (!pdata) return;

                const move = MOVE_BY_ID.get(choice.moveId);
                if (!move) return;

                if (moveSlot === 0) pdata.move1 = move.id;
                else if (moveSlot === 1) pdata.move2 = move.id;
                else if (moveSlot === 2) pdata.move3 = move.id;
                else if (moveSlot === 3) pdata.move4 = move.id;

                pokemonUtils.updatePokemonSlot(player, slotIndex0, pdata);

                try { player.onScreenDisplay.setActionBar(`§a${pokemon} learned ${choice.name}!§r`); } catch (e) { }
                try { player.sendMessage(`§a${pokemon} learned ${choice.name}!§r`); } catch (e) { }
            });
        });

        }); // end getLearnPoints
    });
}
export function setNickname(player) {
    let form = new ActionFormData();
    let functions = [];
    form.title("Options");
    form.body(`000000000000`);
    for (let i = 1; i < 7; i++) {
        form.button(`Slot ${i}`);
    }
    form.button("Back");
    form.button("Close");
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
        const selection = response.selection;
        if (selection <= 5)
            renamePokemon(player, selection);
        else if (selection == 6) {
            arceusMenu(player);
        }
        else
            return;
    });
}
function renamePokemon(player, pokemonSlot) {
    let form = new ModalFormData();
    form.title("Rename your pokemon:");
    form.textField('Pokemon name:', 'Type here');
    form.show(player).then(response => {
        if (response.canceled || response.cancelationReason)
            return;
        if (!response.formValues)
            return;
        const [textField] = response.formValues;
        if (textField && textField != " ") {
            pokemonUtils.renamePokemon(player, pokemonSlot, textField);
        }
    });
}
export function summary(player) {
    let form = new ActionFormData();
    form.title("Options");
    form.body(`000000000000`);
    for (let i = 1; i < 7; i++) {
        form.button(`Slot ${i}`);
    }
    form.button("Back");
    form.button("Close");
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
        const selection = response.selection;
        if (selection < 6) {
            infoPokemon(player, selection);
        }
        else if (selection == 6) {
            arceusMenu(player);
        }
    });
}
function infoPokemon(player, slot) {
    const form = new ActionFormData();
    form.title("Summary");
    const pokemonSlot = pokemonUtils.getPokemonFromSlot(player, slot);
    if (!pokemonSlot) {
        player.onScreenDisplay.setActionBar("You don't have a pokemon in this slot!");
        uiManager.closeAllForms(player);
        return;
    }
    const pokemonData = POKEMONS_DATA.find(pokemon => pokemon.id === pokemonSlot.typeId);
    if (!pokemonData) {
        player.onScreenDisplay.setActionBar("Pokemon data not found!");
        uiManager.closeAllForms(player);
        return;
    }
    const idTexture = pokemonSlot.typeId.split(":")[1];
    const nickname = pokemonSlot.name;
    const level = pokemonSlot.level;
    const healthPercent = pokemonSlot.health / pokemonData.maxHealth * 100;
    const healthTrue = pokemonSlot.health > 0 ? true : false;

    const typingText = formatTyping(pokemonData.types);
    const offensive = buildOffensiveSummary(pokemonData.types);
    form.body(`000000000000
    §7Pokemon:§a ${StringUtils.toTitleCaseEntityName(pokemonSlot.typeId)}
    §7Nickname:§a ${nickname}
    §7Typing:§a ${typingText}
    §7Strong Against:
    §a${offensive.strongAgainst}
    §7Weak Against:
    §a${offensive.weakTo}
    §7Immune:§a ${offensive.immuneTo}
    §7Level:§a ${level}
    §7Health:§a ${pokemonSlot.health} / ${pokemonData.maxHealth}
    §7Attack:§a ${pokemonData.attack}
    §7Defense:§a ${pokemonData.defense}
    §7Sp. Attack:§a ${pokemonData.spAttack}
    §7Sp. Defense:§a ${pokemonData.spDefense}
    §7Speed:§a ${pokemonData.speed}`);
    if (healthTrue) {
        form.button("Close", "textures/icons/pokemons/" + idTexture);
    }
    else {
        form.button("Close", "textures/icons/fainted/" + idTexture);
    }
    form.show(player).then((response) => {
        if (response.canceled || response.cancelationReason)
            return;
    });
}